Pure CSS Tooltip

Pure CSS Tooltip

The theme for week #11 of the Weekly Coding Challenge is:

Tooltip

A tooltip is a message which appears when you hover over an item. Usually this item is an image, a hyperlink or an icon.

In this article we're going to build a Tooltip with Pure CSS:

https://codepen.io/FlorinPop17/pen/YbrNxZ/

The HTML

We don't need a complicated HTML structure. We are only going to use a simple div, with a couple of class names, and we're going to have a tooltip for each of the following positions: top, right, left, bottom.

<div class="tooltip top">Show Top</div>
<div class="tooltip right">Show Right</div>
<div class="tooltip left">Show Left</div>
<div class="tooltip bottom">Show Bottom</div>

The CSS

In order to make the tooltip functional we'll need to style 3 things:

  1. the parent .tooltip div - this is the actual element that is being hovered
  2. the message box or the ::after selector - we'll use this to display the message in the corresponding position (left, right, top, bottom)
  3. the arrow or the ::before selector - we'll use this to display a small arrow towards the parent div from the message box

And finally, we'll use the .top, .right, .left, .bottom classes to position the ::after and ::before selectors differently. (You'll see what I mean in a moment 😉)

1. The parent .tooltip styling

This will be a simple rounded element with relative positioning.

.tooltip {
    background-color: #ffaffc;
    border-radius: 10px;
    padding: 10px 15px;
    position: relative;
    margin: 15px;
    text-align: center;
}

2. The message box

As mentioned above, we'll use the ::after selector to create a new element which will display the message:

.tooltip::after {
    background-color: #333;
    border-radius: 10px;
    color: #b254ff;
    display: none;
    padding: 10px 15px;
    position: absolute;
    text-align: center;
    z-index: 999;
}

Initially the message is hidden (with display: none) and we're going to show it only on :hover.

Also as you can see we don't have yet the 2 crucial parts that we need: the content property of the selector and the actual positioning of the element. We will style these independently for each separate position by using the other class that we have:

.tooltip.top::after {
    content: 'top';
    top: 0;
    left: 50%;
    transform: translate(-50%, calc(-100% - 10px));
}

.tooltip.bottom::after {
    content: 'bottom';
    bottom: 0;
    left: 50%;
    transform: translate(-50%, calc(100% + 10px));
}

.tooltip.right::after {
    content: 'right';
    top: 0;
    right: 0;
    transform: translateX(calc(100% + 10px));
}

.tooltip.left::after {
    content: 'left';
    top: 0;
    left: 0;
    transform: translateX(calc(-100% - 10px));
}

As you can see we are adding the message in the content property. Also, depending on where we want to position it, we'll have to calculate the top, left, right and bottom values.

For the top & bottom positions we have the left property set the 50% and the translate on the X axis is at -50% because we want it to be displayed in the middle.

In our example for the left & right positions we don't have to center on the Y axis because the elements (the parent .tooltip and the message) are the same height, but you have to calculate this as well if the height will be different.

Lastly, you can see that inside the translate function we are calculating the proper position by subtracting or adding to the total width of the message element (100%), an extra 10 pixels. This is how much further we want the message to be from the actual component.

Now, let's show the message on hover:

.tooltip:hover::after {
    display: block;
}

3. The arrow

As mentioned above, we'll create an arrow in the ::before selector.

Basically this will be a simple square that will be rotated 45 degrees and then half of the square will be hidden by the actual message box creating an arrow. Also we're going to have to properly position each arrow depending on the particular class name (as we did above), but we need to take into consideration that half of the square must be covered in order to create the arrow, for this we'll change the above 10px offset to only 5px:

.tooltip::before {
    background-color: #333;
    content: ' ';
    display: none;
    position: absolute;
    width: 15px;
    height: 15px;
    z-index: 999;
}

.tooltip:hover::before {
    display: block;
}

.tooltip.top::before {
    top: 0;
    left: 50%;
    transform: translate(-50%, calc(-100% - 5px)) rotate(45deg);
}

.tooltip.bottom::before {
    bottom: 0;
    left: 50%;
    transform: translate(-50%, calc(100% + 5px)) rotate(45deg);
}

.tooltip.right::before {
    top: 50%;
    right: 0;
    transform: translate(calc(100% + 5px), -50%) rotate(45deg);
}

.tooltip.left::before {
    top: 50%;
    left: 0;
    transform: translate(calc(-100% - 5px), -50%) rotate(45deg);
}

Conclusion

This is all for today! 😄

You might get a little confused by all the positioning that's going around and all the calculations, but that is only because I wanted to have all the 4 positions covered (sorry 😅). You can build your tooltip message to appear only on top or underneath (bottom) the actual element.

As always, let me know if you have any questions and let me see what you've built!

Happy Coding! 😇

Tagged with html5, css3, transform, after, before, tooltip, weekly-coding-challenge