Fashionable CSS Tooltips And Speech Bubbles (Half 1) — Smashing Journal

0
2


In a earlier article, we explored ribbon shapes and other ways to strategy them utilizing intelligent combos of CSS gradients and clip-path(). This time, I’d prefer to discover one other form, one that you just’ve probably needed to deal with no less than as soon as in your front-end life: tooltips. You recognize what we’re speaking about, these little issues that seem like speech bubbles from comedian books. They’re in all places within the wild, from a hover impact for buttons to the textual content messaging app in your cellphone.

The shapes could look simple to make in CSS at first look, nevertheless it at all times ends with quite a lot of struggles. For instance, how do you modify the place of the tail to point whether or not the tooltip is coming from a left, proper, or heart place? There are loads of concerns to take note of when making tooltips — together with overflowage, collision detection, and semantics — nevertheless it’s the form and path of the tail that I need to give attention to as a result of I usually see rigid fastened models used to place them.

Neglect what you already learn about tooltips as a result of on this article, we are going to begin from zero, and you’ll learn to construct a tooltip with minimal markup powered by fashionable CSS that gives flexibility to configure the element by adjusting CSS variables. We’re not going to construct one or two shapes, however… 100 completely different shapes!

Which will sound like we’re getting right into a super-long article, however really, we are able to simply get there by adjusting a number of values. In the long run, you’ll have a again pocket filled with CSS methods that may be mixed to create any form you need.

And guess what? I’ve already created a web based assortment of 100 completely different tooltip shapes the place you’ll be able to simply copy and paste the code on your personal use, however stick with me. You’re going to need to know the key to unlocking a whole bunch of potentialities with the least potential code.

We’ll begin with the shapes themselves, discussing how we are able to lower out the bubble and tail by combining CSS gradients and clipping. Then, we’ll choose issues again up in a second article devoted to enhancing one other frequent strategy to tooltips utilizing borders and customized shapes.

The HTML

We’re solely working with a single factor:

<div class="tooltip">Your textual content content material goes right here</div>

That’s the problem: Create a whole bunch of tooltip variations in CSS with solely a single factor to hook into within the HTML.

I’m going to skip proper over the essential rectangular form; you understand how to set a width and top (or aspect-ratio) on components. Let’s begin with the best form for the tooltip’s tail, one that may be achieved with solely two CSS properties:

.tooltip {
  /* tail dimension */
  --b: 2em; /* base */
  --h: 1em; /* top*/

  border-image: fill 0 // var(--h)
    conic-gradient(#CC333F 0 0); /* the colour  */
  clip-path: 
    polygon(0 100%, 0 0, 100% 0, 100% 100%,
      calc(50% + var(--b) / 2) 100%,
      50% calc(100% + var(--h)),
      calc(50% - var(--b) / 2) 100%);
}

The border-image property creates an “overflowing shade” whereas clip-path defines the form of the tooltip with polygon() coordinates. (Talking of border-image, I wrote a deep-dive on it and clarify the way it is perhaps the one CSS property that helps double slashes within the syntax!)

The tooltip’s tail is positioned on the backside heart, and now we have two variables to manage its dimensions:

Illustrating the border-image coloration and the clip-path polygon()
(Massive preview)

We are able to do the very same factor in additional intuitive methods, like defining a background after which border (or padding) to create house for the tail:

background: #CC333F;
border-bottom: var(--h) stable #0000;

…or utilizing box-shadow (or define) for the skin shade:

background: #CC333F;
box-shadow: 0 0 0 var(--h) #CC333F;

Whereas these approaches are certainly simpler, they require an additional declaration in comparison with the one border-image declaration we used. Plus, we’ll see later that border-image is actually helpful for carrying out extra advanced shapes.

Here’s a demo with the completely different instructions so you’ll be able to see how simple it’s to regulate the above code to vary the tail’s place.

See the Pen [A simple Tooltip using 2 CSS properties](https://codepen.io/smashingmag/pen/ExrEXoO) by Temani Afif.

See the Pen A easy Tooltip utilizing 2 CSS properties by Temani Afif.

Subsequent, we’re going to check shapes that embrace the tail on the backside, however you’ll be able to simply discover the opposite variations in my on-line assortment.

Adjusting The Tail Place

Let’s add a 3rd variable, --p, that we are able to use to manage the tooltip’s tail place. Within the final instance, we used 50% within the clip-path, which positions the tail straight within the horizontal heart alongside the underside of the tooltip’s rectangular form. If we assign a variable to it, we are able to simply change the path of the tooltip to face left or proper by updating 50% to a smaller or bigger worth, respectively.

.tooltip {
  /* tail dimension */
  --b: 2em; /* base */
  --h: 1em; /* top*/
  --p: 50%; /* tail place */   

  border-image: fill 0 // var(--h)
    conic-gradient(#CC333F 0 0); /* the colour  */
  clip-path: 
    polygon(0 100%, 0 0, 100% 0, 100% 100%,
      calc(var(--p) + var(--b) / 2) 100%,
      var(--p) calc(100% + var(--h)),
      calc(var(--p) - var(--b) / 2) 100%);
}

The --p variable can go from 0% to 100%, the place 0% is aligned with the left facet of the tooltip and 100% is aligned with the appropriate facet. Right here is an interactive demo the place you’ll be able to replace the variable utilizing a variety slider:

See the Pen [Updating the tail position](https://codepen.io/smashingmag/pen/mdoLOGJ) by Temani Afif.

See the Pen Updating the tail place by Temani Afif.

Good, proper?! It’s undoubtedly cool, however there’s a glitch. When the tail’s place is about to the extremes, it seems to slip proper off the sting of the bubble. Go forward and toggle the vary slider within the demo between 0% and 100% to see the problem.

Red rectangle tooltip where the tail of the tooltip is overflowing the container.
The tooltip’s tail is allowed to overflow its container on the extremes. (Massive preview)

We are able to repair this by setting limits to some values so the tail by no means falls outdoors the container. Two factors of the polygon are involved with the repair.

This:

calc(var(--p) + var(--b) / 2) 100%

…and this:

calc(var(--p) - var(--b) / 2) 100%

The primary calc() must be clamped to 100% to keep away from the overflow from the appropriate facet, and the second must be clamped to 0% to keep away from the overflow from the left facet. We are able to use the min() and max() capabilities to determine the vary limits:

clip-path: 
  polygon(0 100%, 0 0, 100% 0, 100% 100%,
    min(100%, var(--p) + var(--b) / 2) 100%,
    var(--p) calc(100% + var(--h)),
    max(0%, var(--p) - var(--b) / 2) 100%);

See the Pen [Fixing the overflow issue](https://codepen.io/smashingmag/pen/mdoLRVr) by Temani Afif.

See the Pen Fixing the overflow situation by Temani Afif.

Tada! We’ve fastened the sting instances, and now the tail will get a unique form as a substitute of overflowing!

Illustrating the tail’s at the left and right edges of the tooltip
(Massive preview)

Adjusting The Tail Form

Let’s combine one other variable, --x, into the clip-path() and use it to regulate the form of the tail:

.tooltip {
  /* tail dimension */
  --b: 2em; /* base */
  --h: 1em; /* top*/

  --p: 50%;  /* tail place */
  --x: -2em; /* tail form */

  border-image: fill 0 // 9999px
    conic-gradient(#CC333F 0 0); /* the colour  */
  clip-path: 
    polygon(0 100%, 0 0, 100% 0, 100% 100%,
      min(100%, var(--p) + var(--b) / 2) 100%,
      calc(var(--p) + var(--x)) calc(100% + var(--h)),
      max(0%, var(--p) - var(--b) / 2) 100%);
}

The --x variable might be both constructive or damaging (utilizing no matter unit you need, together with percentages). What we’re doing is including the variable that establishes the tail’s form, --x, to the tail’s place, --p. In different phrases, we’ve up to date this:

var(--p) calc(100% + var(--h))

…to this:

calc(var(--p) + var(--x)) calc(100% + var(--h))

And right here is the end result:

Two variations of the same red rectangular tooltip, one with a tail in the left direction and one with the tail in the right position.
(Massive preview)

The tooltip’s tail factors in both the appropriate or left path, relying on whether or not --x is a constructive or damaging worth. Go forward and use the vary sliders within the following demo to see how the tooltip’s tail is re-positioned (--p) and re-shaped (--x) when adjusting two variables.

See the Pen [Updating the tail shape](https://codepen.io/smashingmag/pen/ExMLZZB) by Temani Afif.

See the Pen Updating the tail form by Temani Afif.

Cool, proper? In case you’ve ever tried tooltips by yourself, I’m positive you’ll recognize the best way this strategy eliminates the necessity to use magic numbers to tweak the tooltip’s look. That’s one vital headache we now not have to fret about!

And did you discover how the tail, when stretched, is allowed to overflow the container? That’s good! Utilizing min() and max(), we’re accurately fixing the overflow situation whereas permitting the tail to stretch additional away from the container.

Two variations of the same red rectangular tooltip, one with a tail in the left direction and one with the tail in the right position.
(Massive preview)

Be aware that I’ve up to date the border-image outset to an impractically giant worth (9999px) as a substitute of utilizing the --h variable. The form of the tail might be any sort of triangle and may take a much bigger space. Since there’s no method for us to know the precise worth of the outset, we use that huge worth to ensure now we have sufficient room to fill the tail in with shade, irrespective of its form.

Does the outset idea look unusual to you? I do know that working with border-image isn’t one thing many people do all that usually, so if this strategy is hard to wrap your head round, undoubtedly go take a look at my border-image article for an intensive demonstration of the way it works.

Working With Gradients

A lot of the hassle begins after we need to shade the tooltip with a gradient as a substitute of a flat shade. Making use of one shade is easy — even with older methods — however in terms of gradients, it’s not simple to make the tail shade circulate easily into the container’s shade.

However guess what? That’s no drawback for us as a result of we’re already utilizing a gradient in our border-image declaration!

border-image: fill 0 // var(--h)
  conic-gradient(#CC333F 0 0);

border-image solely accepts gradients or photographs, so to supply a stable shade, I had to make use of a gradient consisting of only one shade. However should you change it right into a “actual” gradient that transitions between two or extra colours, then you definately get your tooltip gradient. That’s all!

See the Pen [Adding gradient coloration](https://codepen.io/smashingmag/pen/GRedryE) by Temani Afif.

See the Pen Including gradient coloration by Temani Afif.

The one factor we have to take note of is the outset worth. When utilizing one shade, we don’t actually care what the outset worth is; it simply must be as huge as potential to cowl the clip-path space, as we did when setting it to 9999px. Nonetheless, when working with a number of colours, we must always not use too huge of a worth in order that we keep away from clipping the gradient by chance.

Within the final demo, you’ll discover I’m utilizing a worth equal to 0 0 var(--h) 0, which signifies that we’re setting solely a backside outset; the tail is on the backside, and the gradient won’t lengthen in all of the instructions because it did within the different examples. I don’t need to get into all the varied edge instances that would come up, however you probably have hassle working with the gradient’s shade, it’s normally the border-image’s outset worth that you’ll want to examine.

Working With Rounded Corners

If we attempt to add a border-radius to the earlier examples, nothing occurs. That’s as a result of the border-radius and border-image properties aren’t actually all that good of mates. We have to tweak border-image and mix it with background to get issues working proper.

Illustrating the three steps needed to create rounded tooltip corners in sequential order.
(Massive preview)

We begin by declaring a background and border-radius on the .tooltip. Nothing fancy. Then, we transfer to the border-image property in order that we are able to add a bar (highlighted in purple within the final determine) that barely overflows the container from the underside. This half is a bit tough, and right here I invite you to learn my earlier article about border-image to grasp this little bit of CSS magic. From there, we add the clip-path and get our ultimate form.

.tooltip {
  /* triangle dimension */
  --b: 2em; /* base */
  --h: 1em; /* top */

  --p: 50%; /* place  */
  --r: 1.2em; /* the radius */
  --c: #4ECDC4;

  border-radius: var(--r);
  clip-path: polygon(0 100%, 0 0, 100% 0, 100% 100%,
    min(100%, var(--p) + var(--b) / 2) 100%,
    var(--p) calc(100% + var(--h)),
    max(0%, var(--p) - var(--b) / 2) 100%);
  background: var(--c);
  border-image: conic-gradient(var(--c) 0 0) fill 0/
    var(--r) calc(100% - var(--p) - var(--b) / 2) 0 calc(var(--p) - var(--b) / 2)/
    0 0 var(--h) 0;
}

See the Pen [Adding border radius](https://codepen.io/smashingmag/pen/MWxGvYg) by Temani Afif.

See the Pen Including border radius by Temani Afif.

We’re good however nonetheless have a tiny situation when the tail will get near the intense edges.

Showing two versions of the same tooltip where the tail overflows the container on the left and right edges, respectively, creating a jagged edge between the tail and tooltip.
(Massive preview)

This visible glitch occurs when the border-image overlaps with the rounded corners. To repair this, we have to modify the border-radius worth based mostly on the tail’s place (--p).

We’re not going to replace all of the radii, solely the underside ones and, extra exactly, the horizontal values. I need to remind you that border-radius accepts as much as eight values — every nook takes two values that set the horizontal and vertical instructions — and in our case, we are going to replace the horizontal worth of the bottom-left and bottom-right corners:

border-radius:
  /* horizontal values */
  var(--r) 
  var(--r) 
  min(var(--r),100% - var(--p) - var(--b)/2) /* horizontal bottom-right */
  min(var(--r),var(--p) - var(--b)/2) /* horizontal bottom-left */
  /
  /* vertical values */
  var(--r)
  var(--r)
  var(--r)
  var(--r)

All of the nook values are equal to --r, aside from the bottom-left and bottom-right corners. Discover the ahead slash (/), as it’s a part of the syntax that separates the horizontal and vertical radii values.

Now, let’s dig in and perceive what is occurring right here. For the bottom-left nook, when the place of the tail is on the appropriate, the place (--p) variable worth might be huge with the intention to hold the radius equal to the radius (--r), which serves because the minimal worth. However when the place will get nearer to the left, the worth of --p decreases and, sooner or later, turns into smaller than the worth of --r. The result’s the worth of the radius slowly lowering till it reaches 0. It adjusts because the place updates!

I do know that’s loads to course of, and a visible assist normally helps. Strive slowly updating the tail’s place within the following demo to get a clearer image of what’s taking place.

See the Pen [Fixing the edge cases](https://codepen.io/smashingmag/pen/ZEPoJpG) by Temani Afif.

See the Pen Fixing the sting instances by Temani Afif.

What about situations after we need a customized form for the tail? The method we simply used will solely work when the tail has two equal sides — you recognize, an isosceles triangle. We have to modify the border-image worth and contemplate one other trick to get issues working accurately once more.

Illustrating three steps for correcting the tooltip’s overflow when the tail is a custom shape.
(Massive preview)

This time, the border picture creates a horizontal bar alongside the underside that’s positioned straight beneath the factor and extends outdoors of its boundary in order that now we have sufficient shade for the tail when it’s nearer to the sting.

.tooltip {
  /* tail dimension */
  --b: 2em; /* base */
  --h: 1.5em; /* top */

  --p: 50%; /* place */
  --x: 1.8em; /* tail place */
  --r: 1.2em; /* the radius */
  --c: #4ECDC4;

  border-radius: var(--r) var(--r) min(var(--r), 100% - var(--p) - var(--b) / 2) min(var(--r), var(--p) - var(--b) / 2) / var(--r);
  clip-path: polygon(0 100%, 0 0, 100% 0, 100% 100%,
    min(100%, var(--p) + var(--b) / 2) 100%,
    calc(var(--p) + var(--x)) calc(100% + var(--h)),
    max(0%, var(--p) - var(--b) / 2) 100%);
  background: var(--c);
  border-image: conic-gradient(var(--c) 0 0) 0 0 1 0 / 0 0 var(--h) 0 / 0 999px var(--h) 999px;
}

See the Pen [Custom tail with border radius](https://codepen.io/smashingmag/pen/MWxGEpv) by Temani Afif.

See the Pen Customized tail with border radius by Temani Afif.

Once more, the border-image declaration seems to be unusual and tough as a result of, effectively, it’s! Please do your self a favor and examine my earlier article if you wish to dig deeper into this strategy — you undoubtedly gained’t remorse it.

“Why not use this strategy for the primary instance we checked out?” you may ask. You might be proper that we are able to use this identical strategy for the primary instance, even when we don’t have the --x variable. That stated, the rationale we’re not moving into that path is that there’s a tiny disadvantage to it in some specific instances, as you’ll be able to see within the determine beneath.

Showing visual imperfections in the tooltip, including a gap between the tail and the tooltip, and a slight color bleed at the left and right edges of the container.
(Massive preview)

That’s why I don’t use this strategy when working with a easy isosceles triangle. This stated, the tactic is completely high quality, and usually, you could not see any visible glitches.

Placing Every part Collectively

We’ve checked out tooltips with tails which have equal sides, ones with tails that change form, ones the place the tail adjustments place and path, ones with rounded corners, and ones which can be stuffed in with gradients. What would it not seem like if we mixed all of those examples into one mega-demo?

We are able to do it, however not by combining the approaches we’ve lined. We’d like one other technique, this time utilizing a pseudo-element. No border-image for this one, I promise!

.tooltip {
  /* triangle dimension */
  --b: 2em; /* base */
  --h: 1em; /* top */

  --p: 50%; /* place */
  --r: 1.2em; /* the radius */

  border-radius: var(--r) var(--r) min(var(--r), 100% - var(--p) - var(--b) / 2) min(var(--r), var(--p) - var(--b) / 2) / var(--r);
  background: 0 0 / 100% calc(100% + var(--h)) 
    linear-gradient(60deg, #CC333F, #4ECDC4); /* the gradient */
  place: relative;
  z-index: 0;
}
.tooltip:earlier than {
  content material: "";
  place: absolute;
  z-index: -1;
  inset: 0 0 calc(-1*var(--h));
  background-image: inherit;
  clip-path: 
    polygon(50% 50%,
      min(100%, var(--p) + var(--b) / 2) calc(100% - var(--h)),
      var(--p) 100%,
      max(0%, var(--p) - var(--b) / 2) calc(100% - var(--h)));
}

The pseudo-element is used to create the tail on the backside and see the way it inherits the gradient from the primary factor to simulate a steady gradient that covers your entire form.

Showing the tail at bottom that inherits the gradient from the main element
(Massive preview)

One other necessary factor to notice is the background-size declared within the .tooltip. The pseudo-element is overlaying a much bigger space as a result of damaging backside worth, so now we have to extend the peak of the gradient so it covers the identical space.

See the Pen [Gradient and border radius](https://codepen.io/smashingmag/pen/ZEPoayw) by Temani Afif.

See the Pen Gradient and border radius by Temani Afif.

For the customized tail form, now we have to replace the code barely to think about the overflow on the left and proper sides of the tooltip. The thought is to extend the gradient’s space when the tail is about to go away the container.

.tooltip {
  --p: 50%;  /* place  */
  --x: -2em; /* tail form and path */

  --_e: max(0%, -1 * var(--x) - var(--p), var(--x) + var(--p) - 100%);
  
  background:
    50% 0 / calc(100% + 2*var(--_e)) calc(100% + var(--h)) 
    linear-gradient(60deg, #CC333F, #4ECDC4); /* the gradient */
}
.tooltip:earlier than {
  inset: 0 calc(-1 * var(--_e)) calc(-1 * var(--h));
  padding-inline: var(--_e);
}

Alongside the --x variable that controls the tail’s form and path, I’ve launched a brand new variable, --_e, that defines the gradient’s width for overlaying the .tooltip in addition to the pseudo-element’s inline padding and its left and proper values. It could seem like a fancy configuration, however the concept is that --_e will, usually, be equal to 0, which provides us the identical code because the final instance we made. However when the tail overflows the .tooltip container, the --_e worth will increase, which will increase the realm of the gradient as effectively with the intention to cowl the overflow.

Play with the place and form of the tail within the following demo and see how the gradient adjustments when the tail overflows the edges.

See the Pen [Custom tail with border radius and gradient](https://codepen.io/smashingmag/pen/RwdyExJ) by Temani Afif.

See the Pen Customized tail with border radius and gradient by Temani Afif.

I do know this final code could look advanced (identical for among the earlier ones), and because of this, I created a web based assortment of tooltips from the place you’ll be able to simply seize the code. I’ve tried to cowl as many instances as potential, even those you’ll in all probability by no means want. That stated, it’s good to have an concept of how one can construct varied tooltip shapes.

One Final Thought

If we do the depend, now we have made 32 completely different tooltip shapes. That’s two varieties of shade (stable or gradient), two varieties of corners (sharp or rounded) that produce 4 extra variations, and two varieties of tail shapes (isosceles triangle and customized) for 2 further variations, and 4 completely different tail positions (prime, backside, left, and proper) which brings the ultimate tally to 32 tooltip variations.

The final instance we studied can be utilized to supply all of the shapes just by adjusting the completely different variables.

I do know what you’re pondering: Why didn’t I merely share the final snippet and name it a day? Did this text actually need to be so lengthy after we might have jumped straight into the answer?

Positive, we might have performed that, however In case you evaluate the primary instance with solely two CSS properties with the final instance, the code for the final instance is way too advanced to create what can in any other case be achieved in fewer traces. We began with a primary tooltip form and launched into a journey to make it account for extra advanced varieties of tooltips. Plus, now we have discovered quite a lot of methods that may be helpful in different conditions and never essentially for creating tooltips.

Conclusion

That’s all for Half 1 of this transient two-part collection. We nonetheless have many extra shapes to cowl in Half 2, so take the time to digest what we lined in Half 1 earlier than leaping forward. In actual fact, right here’s a little bit homework to assist put together you for Half 2: attempt creating the next tooltips utilizing the CSS methods you discovered from this text.

Showing four different tooltip shapes
(Massive preview)

Can you work it out? The code for all of them is included in my tooltip assortment should you want a reference, however do attempt to make them your self — it’s good train! Possibly you will see a unique (or maybe higher) strategy than mine.

Smashing Editorial
(gg, yk)

LEAVE A REPLY

Please enter your comment!
Please enter your name here