Quite a few CSS libraries have been created to help you with this task, some offer customisation options on what the tooltip looks like, where it’s positioned and other various modifiers such as animations!
Some of these libraries can be found here:
So let’s get deep into the code to understand how these actually work. To get ourselves started I have created a code sample of the main structure prior to adding the CSS tooltips. You can go ahead copy/fork it or create your own example:
From here we will add in the necessary CSS and (very little) HTML to create our tooltips.
To start let’s actually design our tooltip. Typical tooltips take on the form of a speech bubble, with a tail coming from the relevant content and then the bubble/block of text that provides further context to the user. We will build the tooltip in two parts, the tail and the block.
To make things easier we won’t start off with any of the fancy animations on hover etc. Instead, let’s first enable a way to target our styles for the tooltip, a neat trick is to use a data attribute which will eventually hold the content of out tooltip. Add
data-tip="This is a mighty fine tooltip" to the anchor tag. You will notice nothing actually changes, now to add styles!
Our first bit of CSS will be applied directly to the data attribute itself to help align the tail and tooltip body. Apply the following styles
[data-tip] targets all elements with the data attribute of “tip”. We apply the position relative, so the children elements can be positioned
relative to it.
Next the Tail Styles. To accomplish a tail and a message body, we will be using a CSS pseudo class of
:after. Create a CSS selector to target the
[data-tip] before pseudo class and add the following CSS:
:after classes utilise a CSS property called content, meaning the content it will inject either before or after the selected element. In our case, we want no content so we include an empty string. We position
absolute to our parent item, push our items height out with
top: 100%, we position it exactly half way through the parent element (50% – the width of the tail which is 6px), we set the
pointer-event to none to prevent it from targeting any mouse events, we set a
6px transparent border around the entire element and finally set the bottom border to
#333 creating the triangle.
The tooltip body
Now comes the interesting part. We will do something very similar to the tail however now we will use the
:after and specify the tooltip in our content. Create another CSS selector on the
:after pseudo class.
This is pretty much the same as the before with some differences, such as within content we are now specifying
attr(data-tip) which brings in the text content of the data attribute data-tip (very cool!). In addition, we also have a transform
translate(-50%, 0); on the
:after class, this will center our element against the center of the link.
Hide and Seek
A tooltip that always shows isn’t very useful. Let’s now add some CSS styles that can help bring our tooltip to life and animate it in on hover.
Firstly let’s create a selector that will target both :before and :after, you can do this by just comma separating them to apply it to both. You can move some of the previous styles that double up into this selector such as the
Inside this selector lets set the default state to hidden by setting our
visibility to hidden and
opacity to 0;
Duplicate this current selector of both before and
:after, add a
:hover pseudo class to each (just before the
:after) and remove the styles inside this block. Like so:
BAM! our tooltip is now functioning! It will now show and hide on hover!
A project is not complete without any animations! Let’s transition our hide and show and add some movement in there!
For the sake of simplicity, we can add this
transition: all ease-out 0.2s; to our
:after block selection (non-hover). This will animate all changing styles 0.2-second animation that eases in, in our case, it will just animate opacity. Let’s add some movement to polish it off.
:before selector add
transform: translateY(8px); and then reset this back to 0px (
transform: translateY(0)) by creating a hover selector for it.
As we already use a transform on the
:after, we can simply append with a separated space to our existing transform like so:
transform: translateX(-50%) translateY(8px) then once again reset on the
:hover, however when we reset we need to keep the existing
translateX so set it just to
These will initial translate the tail and message body 8px in the Y direction and then transition them to 0 (normal position) during the fade in.
And there we have it, a very simple pure CSS tooltip!