Search code examples
cssmask

How to make element inside masked div fully visible (tooltip style)?


For an icon based menu, I have several <div> elements in a grid. Each element is actually empty with some general CSS applied and inline CSS to set the mask.

The reason to use images as masks is to have the icons coloured in various ways (by setting the div's background color). See the example snippet below, the icons change colour when hovered and stay coloured when clicked.

$('.qs').click(function() {
  $(this).toggleClass('active');
});
div.icons {
    display: grid;
    grid-template-columns: repeat(auto-fill, 48px);
    grid-gap: 0rem;
    justify-content: space-between;
    background-color: #eee;
}
div.icons .qs {
    height: 30px;
    width: 30px;
    cursor: help;
    margin: 9px;
    transition: all 250ms;
}
div.icons div.qs {
    background-color: rgb(134,134,134);
}
div.icons div.qs.qs-ecod:hover,
div.icons div.qs.qs-ecod.active {
    background-color: rgb(39, 128, 186);
}
div.icons div.qs.qs-sust:hover,
div.icons div.qs.qs-sust.active {
    background-color: rgb(235, 98, 28);
}
div.icons div.qs.qs-cost:hover,
div.icons div.qs.qs-cost.active {
    background-color: rgb(51, 172, 95);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="icons">
<div class="qs qs-ecod" style="-webkit-mask-image: url(https://png.icons8.com/material/30/key.png); mask-mode: alpha;" data-tid="1" title="Login"></div>
<div class="qs qs-sust" style="-webkit-mask-image: url(https://png.icons8.com/material/30/settings.png); mask-mode: alpha;" data-tid="2" title="Settings"></div>
<div class="qs qs-cost" style="-webkit-mask-image: url(https://png.icons8.com/material/30/home.png); mask-mode: alpha;" data-tid="3" title="Add something"></div>
</div>

Now, each element has a title attribute that contains the menu item name. When the user leaves the mouse cursor on an element, the browser will (delayed) show a tooltip revealing the menu item name. This was fine so far, but now the client wants a styled tooltip, so I thought about using a initially hidden span element inside the div or using a pseudo element to show the title attribute.

However, both solutions do not work as normal as the div element is masked. If I put the span element outside the div - which I still could target e.g. by div:hover + span, it will be an element within the defined CSS grid and cannot be placed absolutely in relation to the div element.

Is there a way to make an element fully visible even if it is contained inside a masked element? I do have control over the output but I would like to not add wrapper elements if it is possible.

What I tried:

(1) span inside div

$('.qs').click(function() {
  $(this).toggleClass('active');
});
div.icons {
    display: grid;
    grid-template-columns: repeat(auto-fill, 48px);
    grid-gap: 0rem;
    justify-content: space-between;
    background-color: #eee;
}
div.icons .qs {
    height: 30px;
    width: 30px;
    cursor: help;
    margin: 9px;
    transition: all 250ms;
}
div.icons div.qs {
    background-color: rgb(134,134,134);
}
div.icons div.qs.qs-ecod:hover,
div.icons div.qs.qs-ecod.active {
    background-color: rgb(39, 128, 186);
}
div.icons div.qs.qs-sust:hover,
div.icons div.qs.qs-sust.active {
    background-color: rgb(235, 98, 28);
}
div.icons div.qs.qs-cost:hover,
div.icons div.qs.qs-cost.active {
    background-color: rgb(51, 172, 95);
}

div.qs span {
  display: none;
}
div.qs:hover span {
  display: inline-block;
  background-color: #fc0;
  color: black;
  line-height: 30px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="icons">
<div class="qs qs-ecod" style="-webkit-mask-image: url(https://png.icons8.com/material/30/key.png); mask-mode: alpha;" data-tid="1" title="Login"><span>Login</span></div>
<div class="qs qs-sust" style="-webkit-mask-image: url(https://png.icons8.com/material/30/settings.png); mask-mode: alpha;" data-tid="2" title="Settings"><span>Settings</span></div>
<div class="qs qs-cost" style="-webkit-mask-image: url(https://png.icons8.com/material/30/home.png); mask-mode: alpha;" data-tid="3" title="Add something"><span>Add</span></div>
</div>

(2) :pseudo element

$('.qs').click(function() {
  $(this).toggleClass('active');
});
div.icons {
    display: grid;
    grid-template-columns: repeat(auto-fill, 48px);
    grid-gap: 0rem;
    justify-content: space-between;
    background-color: #eee;
}
div.icons .qs {
    height: 30px;
    width: 30px;
    cursor: help;
    margin: 9px;
    transition: all 250ms;
}
div.icons div.qs {
    background-color: rgb(134,134,134);
}
div.icons div.qs.qs-ecod:hover,
div.icons div.qs.qs-ecod.active {
    background-color: rgb(39, 128, 186);
}
div.icons div.qs.qs-sust:hover,
div.icons div.qs.qs-sust.active {
    background-color: rgb(235, 98, 28);
}
div.icons div.qs.qs-cost:hover,
div.icons div.qs.qs-cost.active {
    background-color: rgb(51, 172, 95);
}

div.qs:hover:before {
  content: attr(title);
  display: inline-block;
  background-color: #fc0;
  color: black;
  line-height: 30px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="icons">
<div class="qs qs-ecod" style="-webkit-mask-image: url(https://png.icons8.com/material/30/key.png); mask-mode: alpha;" data-tid="1" title="Login"></div>
<div class="qs qs-sust" style="-webkit-mask-image: url(https://png.icons8.com/material/30/settings.png); mask-mode: alpha;" data-tid="2" title="Settings"></div>
<div class="qs qs-cost" style="-webkit-mask-image: url(https://png.icons8.com/material/30/home.png); mask-mode: alpha;" data-tid="3" title="Add something"></div>
</div>

(3) span after div

$('.qs').click(function() {
  $(this).toggleClass('active');
});
div.icons {
    display: grid;
    grid-template-columns: repeat(auto-fill, 48px);
    grid-gap: 0rem;
    justify-content: space-between;
    background-color: #eee;
}
div.icons .qs {
    height: 30px;
    width: 30px;
    cursor: help;
    margin: 9px;
    transition: all 250ms;
}
div.icons div.qs {
    background-color: rgb(134,134,134);
}
div.icons div.qs.qs-ecod:hover,
div.icons div.qs.qs-ecod.active {
    background-color: rgb(39, 128, 186);
}
div.icons div.qs.qs-sust:hover,
div.icons div.qs.qs-sust.active {
    background-color: rgb(235, 98, 28);
}
div.icons div.qs.qs-cost:hover,
div.icons div.qs.qs-cost.active {
    background-color: rgb(51, 172, 95);
}

div.qs + span {
  display: none;
}
div.qs:hover + span {
  display: inline-block;
  background-color: #fc0;
  color: black;
  width: auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="icons">
<div class="qs qs-ecod" style="-webkit-mask-image: url(https://png.icons8.com/material/30/key.png); mask-mode: alpha;" data-tid="1" title="Login"></div><span>Login</span>
<div class="qs qs-sust" style="-webkit-mask-image: url(https://png.icons8.com/material/30/settings.png); mask-mode: alpha;" data-tid="2" title="Settings"></div><span>Settings</span>
<div class="qs qs-cost" style="-webkit-mask-image: url(https://png.icons8.com/material/30/home.png); mask-mode: alpha;" data-tid="3" title="Add something"></div><span>Add</span>
</div>


Solution

  • This is a functional code of the "span after div" version. I added some JS & CSS code.

    $('.qs').click(function() {
      $(this).toggleClass('active');
    });
    
    $('div.qs + span').each(function() {
      var offset = $(this).prev().offset().left;
      $(this).css('left', offset + 'px');
    });
    div.icons {
        display: grid;
        grid-template-columns: repeat(auto-fill, 48px);
        grid-gap: 0rem;
        justify-content: space-between;
        background-color: #eee;
    }
    div.icons .qs {
        height: 30px;
        width: 30px;
        cursor: help;
        margin: 9px;
        transition: all 250ms;
    }
    div.icons div.qs {
        background-color: rgb(134,134,134);
    }
    div.icons div.qs.qs-ecod:hover,
    div.icons div.qs.qs-ecod.active {
        background-color: rgb(39, 128, 186);
    }
    div.icons div.qs.qs-sust:hover,
    div.icons div.qs.qs-sust.active {
        background-color: rgb(235, 98, 28);
    }
    div.icons div.qs.qs-cost:hover,
    div.icons div.qs.qs-cost.active {
        background-color: rgb(51, 172, 95);
    }
    
    div.qs + span {
      display: none;
    }
    div.qs:hover + span {
      display: inline-block;
      background-color: #fc0;
      color: black;
      width: auto;
      position: absolute;
      top: 57px;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <div class="icons">
    <div class="qs qs-ecod" style="-webkit-mask-image: url(https://png.icons8.com/material/30/key.png); mask-mode: alpha;" data-tid="1" title="Login"></div><span>Login</span>
    <div class="qs qs-sust" style="-webkit-mask-image: url(https://png.icons8.com/material/30/settings.png); mask-mode: alpha;" data-tid="2" title="Settings"></div><span>Settings</span>
    <div class="qs qs-cost" style="-webkit-mask-image: url(https://png.icons8.com/material/30/home.png); mask-mode: alpha;" data-tid="3" title="Add something"></div><span>Add</span>
    </div>