Supun Kavinda I started as a self-taught PHP developer before creating my own company, Hyvor. I am particularly interested in physics and machine learning.

Creating beautiful tooltips with only CSS

4 min read 1153

Creating a tooltip using only CSS.

Have you seen those boxes with extra descriptions when you hover on a text?

Those are tooltips! Even thought it can seem intimidating to start creating your first tooltip, you actually only need to know basic CSS.

This article will show you how to create beautiful tooltips with only CSS.

An example of a tooltip appearing above text saying 'hover over me.'
A tooltip.

First, let’s start with a <span> element with tooltip class and add an anchor text.

<span class="tooltip">Hover over me!</span>

Creating the tooltip

I promised only to use CSS — no additional HTML elements.

How can we create the tooltip in that way? If your guess was :before or :after pseudo elements, you are correct.

Where do you define the tooltip text? One might say to define directly in the content property of the pseudo elements.

However, it will make things more difficult to handle.

For example, if you need to add several tooltips, you’ll always need to add more CSS rules and define content. So, here we are going to use HTML custom data attributes to define the text.

Let’s add tooltip text as the data-text attribute to our tooltip span. (You can use whatever name prefixed by data-. Moreover, you can even drop the prefix in some cases.)

  data-text="Thanks for hovering! I'm a tooltip" 
>Hover over me!</span>

Now, we can add CSS rules to style the container:

.tooltip {
  position:relative; /* making the .tooltip span a container for the tooltip text */
  border-bottom:1px dashed #000; /* little indicater to indicate it's hoverable */

Finally, we are going to create the tooltip text, which is positioned on the right side:

.tooltip:before {
  content: attr(data-text); /* here's the magic */
  /* vertically center */
  /* move to right */
  margin-left:15px; /* and add a small left margin */
  /* basic styles */
  color: #fff;

  display:none; /* hide by default */

content: attr(data-text) is the magic here. This takes the data-text attribute of the parent element and uses it as the content.

Tooltip text is positioned absolute, and it is relative to the .tooltip element.

Final rule: showing the tooltip text when hovering:

.tooltip:hover:before {

You just created your first tooltip! Next, let’s see how we can improve on this.

Positioning tooltips

In the above example, we positioned the tooltip on the right. But what if we want to put the tooltip in a different place? We can use additional classes to define other positions.

      data-text="Thanks for hovering! I'm a tooltip"
      class="tooltip left"
>Hover over me!</span>

CSS for the new class:

.tooltip.left:before {
  /* reset defaults */

  /* set new values */

You can use the same method to create classes for bottom and top positions. Additionally, you’ll need to reset the top value and override the transform value accordingly.

Adding arrows

Usually, CSS tooltips has arrows pointing towards the anchor text.

Thankfully, we have another pseudo element that can be used to make arrows.

Here’s the code for an arrow on a right-aligned tooltip:

.tooltip:after {
  content: "";
  /* position tooltip correctly */
  /* vertically center */
  /* the arrow */
  border:10px solid #000;
  border-color: transparent black transparent transparent;
.tooltip:hover:before, .tooltip:hover:after {

The trick here is to set a border. border: 10px solid #000; creates a border with 10px width.

Since we haven’t defined the width and height for .tooltip:after, width and height is equal to two times the border width:

A solid black square with dimensions of 10px.

What if we set the border color of each side to different colors?

border-color: blue black red green;

A colored square.

Guess what? Setting all colors to transparent except one side makes the arrow we need.

border-color: transparent black transparent transparent;

A black sideways triangle.

Why do we use margin-left:-5px?

A diagram of colored margins.

When we set a border width to 10px, the total width become 20px. We use margin-left to position the arrow correctly (note that we used margin-left:15px in the tooltip).

How do we get rid of this annoying margin? Easy!

Set the border width to half of the tooltip’s left margin (7.5px in our case). I intentionally made it 10px to show you how to deal with the above situation. Now you’re familiar with both.

Creating arrows for other positions (left, top, and bottom) is done in the same way. Positioning them requires the same approach we used in .tooltip.left:before.

Animating the tooltip

A common animation to use for tooltips is the fade-in.

You can also use other animations like zoom-in or bounce, but I personally think they are too much for a tooltip.

Let’s see how to add fade-in animation to our CSS tooltip.

The best method would be to use opacity and transition. There are several advantages of using these instead of CSS animations.

First off, they’re easy to implement. Secondly, you won’t have to worry about fade-out animation —  opacity and transition does that for us.

Instead of setting display:none on the tooltip by default, we are going to use opacity:0. We’re going to set the transition time we need:

.tooltip:before {
  /* other styles */

  /*  display:none; */

  transition:.3s opacity;   

opacity:0 makes the tooltip transparent. Additionally, transition: .3s opacity tells the CSS engine to make a transition effect for 0.3 seconds when the opacity changes.

.tooltip:hover:before {

When you hover over the tooltip, opacity is set to 1 (fully visible). The browser will automatically create both fade-in and fade-out animations for you because we have already set an opacity transition.

You can add the same animation to the tooltip arrow:

.tooltip:after {
.tooltip:hover:after {


In this article, we created a tooltip with only CSS (without extra HTML elements).

We used :before as the tooltip text and :after as the arrow. Now you understand that writing nested HTML elements below for simple tooltips isn’t necessary.

<span class="tooltip">
  Hover over me
  <span class="tooltip-text">
    Some tooltip text

However, our approach has one downside: what if we need to add a link to the tooltip text?

<a> tags in the data-text attribute won’t be shown as a link, but as text. Therefore, if you need to include HTML in the tooltip you’ll need to have HTML tags like the above code.

Positioning, adding arrows, and animating those HTML tags is similar to what we did in this article. The only changes are:

  • .tooltip:before becomes .tooltip-text
  • tooltip:after becomes .tooltip-text:before or .tooltip-text:after.

In conclusion, we mainly used pseudo elements and content:attr() to create CSS tooltips. To add arrows, we used a trick with border. To animate it, we used opacity and transition.

The final result was a CSS-only tooltip.

Is your frontend hogging your users' CPU?

As web frontends get increasingly complex, resource-greedy features demand more and more from the browser. If you’re interested in monitoring and tracking client-side CPU usage, memory usage, and more for all of your users in production, try LogRocket.

LogRocket is like a DVR for web and mobile apps, recording everything that happens in your web app, mobile app, or website. Instead of guessing why problems happen, you can aggregate and report on key frontend performance metrics, replay user sessions along with application state, log network requests, and automatically surface all errors.

Modernize how you debug web and mobile apps — .

Supun Kavinda I started as a self-taught PHP developer before creating my own company, Hyvor. I am particularly interested in physics and machine learning.

15 Replies to “Creating beautiful tooltips with only CSS”

  1. There is a big issue with this tooltip.
    Actually, setting its opacity to 0 makes it disappear to the users eyes only, to to their mouse pointer.
    So, the tooltip actually shows up even though we don’t hover the triggering element, but also where the tooltip is supposed to be…

    1. Sorry for the delay. Have you tried adding `pointer-events: none` to the tooltip?

  2. I noticed this too, but I found an easy fix! Just add “visibility: hidden;” wherever it says “opacity:0;”, and add “visibility: visible;” wherever it says “opacity:1;”. Should work like a charm.

    1. This does work, but I found that it undoes the transition when you hover off the tooltip (in the case that it contains a link). So, the opacity changes over the specified time when you hover the triggering element, but “snaps” off when you unhover over it or the tooltip itself.

  3. Is there a way to do this with a list of generated items in the tooltip? I tried doing this, but the list has a bunch of text in it instead of actual line breaks. In other words, can it only be text when you use this method to make the tooltip?

  4. For reasons I haven’t figured out, if there are two items with tooltips, one immediately below the other, you can “see through” the upper one to the content of the one below it. With white text, this shows up as imperfections in the letters. The effect is much more apparent with black text on a buff yellow background. The fix is to give the tooltip class a z-index larger than anything else in the area right after “position: absolute;”

  5. I’ve also added “transition-delay: 100ms;” right after transition. I have three tooltips one below the other, and this keeps them from popping in and out if the skims over that area. An intentional hover is needed to make the tooltip disappear.

    With the small changes mentioned in the comments, I now have beautiful tooltips. Thank you,
    Supun Kavinda!

  6. This is terrific! I saw you wrote that “You can use the same method to create classes for bottom and top positions. Additionally, you’ll need to reset the top value and override the transform value accordingly,” though, and I’ve been playing with the CSS for quite awhile, but can’t fully figure out how to reset and override the CSS correctly to get top and bottom tooltips working–could you (or anyone else seeing this) let me know how I can do this? Any help would be greatly appreciated!

  7. Hi All,

    I have managed to get the box to appear at the top, however when I apply this effect to the next word in my paragraph which I also want the hover to appear, the second tooltip starts out hovering where the first tooltip was and then when it fades out, it jumps to the second word.

    How would I position the second tooltip to appear above the second word initially instead of inheriting the first tooltip position?

    Would really appreciate some feedback here.


    Simon Carter

Leave a Reply