Saturday, May 18, 2024
HomeWeb developmentTrendy CSS Tooltips And Speech Bubbles (Half 1) — Smashing Journal

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


In a earlier article, we explored ribbon shapes and other ways to method them utilizing intelligent combos of CSS gradients and clip-path(). This time, I’d prefer to discover one other form, one that you simply’ve seemingly needed to deal with at the least 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 all over the place within the wild, from a hover impact for buttons to the textual content messaging app in your cellphone.

The shapes could look straightforward to make in CSS at first look, nevertheless it all the time ends with a number 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 bear in mind when making tooltips — together with overflowage, collision detection, and semantics — nevertheless it’s the form and course of the tail that I need to give attention to as a result of I typically see rigid fastened models used to place them.

Overlook what you already find out 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 part by adjusting CSS variables. We’re not going to construct one or two shapes, however… 100 completely different shapes!

That will sound like we’re getting right into a super-long article, however truly, we will simply get there by adjusting just a few values. Ultimately, you’ll have a again pocket filled with CSS tips 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 possibly can simply copy and paste the code in 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 doable code.

We’ll begin with the shapes themselves, discussing how we will reduce out the bubble and tail by combining CSS gradients and clipping. Then, we’ll decide issues again up in a second article devoted to enhancing one other widespread method to tooltips utilizing borders and customized shapes.

The HTML

We’re solely working with a single component:

<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 component to hook into within the HTML.

I’m going to skip proper over the fundamental rectangular form; you understand how to set a width and peak (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; /* peak*/

  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 could be the one CSS property that helps double slashes within the syntax!)

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

Illustrating the border-image coloration and the clip-path polygon()
(Giant 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 area for the tail:

background: #CC333F;
border-bottom: var(--h) strong #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 only border-image declaration we used. Plus, we’ll see later that border-image is admittedly helpful for engaging in extra advanced shapes.

Here’s a demo with the completely different instructions so you possibly can see how straightforward 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 embody the tail on the backside, however you possibly can simply discover the opposite variations in my on-line assortment.

Adjusting The Tail Place

Let’s add a 3rd variable, --p, that we will use to regulate the tooltip’s tail place. Within the final instance, we used 50% within the clip-path, which positions the tail instantly within the horizontal heart alongside the underside of the tooltip’s rectangular form. If we assign a variable to it, we will simply change the course 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; /* peak*/
  --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 aspect of the tooltip and 100% is aligned with the fitting aspect. Right here is an interactive demo the place you possibly can replace the variable utilizing a spread 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. (Giant 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 fitting aspect, and the second must be clamped to 0% to keep away from the overflow from the left aspect. We are able to use the min() and max() features to ascertain 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 subject by Temani Afif.

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

Illustrating the tail’s at the left and right edges of the tooltip
(Giant 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; /* peak*/

  --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 could be both constructive or adverse (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.
(Giant preview)

The tooltip’s tail factors in both the fitting or left course, relying on whether or not --x is a constructive or adverse 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 the event you’ve ever tried tooltips by yourself, I’m certain you’ll admire the way in which this method eliminates the necessity to use magic numbers to tweak the tooltip’s look. That’s one vital headache we not have to fret about!

And did you discover how the tail, when stretched, is allowed to overflow the container? That’s excellent! Utilizing min() and max(), we’re accurately fixing the overflow subject 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.
(Giant 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 could be any sort of triangle and may take a much bigger space. Since there’s no manner for us to know the precise worth of the outset, we use that massive worth to ensure we’ve 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 always, so if this method is hard to wrap your head round, undoubtedly go try my border-image article for a radical demonstration of the way it works.

Working With Gradients

Many of the bother begins once we need to shade the tooltip with a gradient as a substitute of a flat shade. Making use of one shade is straightforward — even with older strategies — however on the subject of gradients, it’s not straightforward to make the tail shade circulation easily into the container’s shade.

However guess what? That’s no downside 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 pictures, so to supply a strong 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, you then 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 massive as doable 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 massive 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 bother working with the gradient’s shade, it’s normally the border-image’s outset worth that you must 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 pals. 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.
(Giant 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 will add a bar (highlighted in crimson 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 last form.

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

  --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 subject 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.
(Giant 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 primarily based 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 going on right here. For the bottom-left nook, when the place of the tail is on the fitting, the place (--p) variable worth will likely be massive 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, in some unspecified time in the future, 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 quite a bit to course of, and a visible help normally helps. Strive slowly updating the tail’s place within the following demo to get a clearer image of what’s occurring.

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 once we desire a customized form for the tail? The method we simply used will solely work when the tail has two equal sides — you already know, an isosceles triangle. We have to modify the border-image worth and take into account 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.
(Giant preview)

This time, the border picture creates a horizontal bar alongside the underside that’s positioned instantly underneath the component and extends outdoors of its boundary in order that we’ve sufficient shade for the tail when it’s nearer to the sting.

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

  --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 unusual and tough as a result of, properly, it’s! Please do your self a favor and examine my earlier article if you wish to dig deeper into this method — you undoubtedly received’t remorse it.

“Why not use this method for the primary instance we checked out?” you may ask. You might be proper that we will use this similar method for the primary instance, even when we don’t have the --x variable. That mentioned, the rationale we’re not moving into that course is that there’s a tiny disadvantage to it in some explicit instances, as you possibly can see within the determine under.

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.
(Giant preview)

That’s why I don’t use this method when working with a easy isosceles triangle. This mentioned, the tactic is completely nice, and most often, 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 course, ones with rounded corners, and ones which might 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 want 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; /* peak */

  --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 component to simulate a steady gradient that covers the complete form.

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

One other vital factor to notice is the background-size declared within the .tooltip. The pseudo-element is masking a much bigger space as a result of adverse backside worth, so we’ve 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, we’ve to replace the code barely to contemplate the overflow on the left and proper sides of the tooltip. The concept 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 course */

  --_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 course, I’ve launched a brand new variable, --_e, that defines the gradient’s width for masking the .tooltip in addition to the pseudo-element’s inline padding and its left and proper values. It might seem like a fancy configuration, however the concept is that --_e will, most often, 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 world of the gradient as properly 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 perimeters.

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 (similar for among the earlier ones), and because of this, I created a web-based assortment of tooltips from the place you possibly can simply seize the code. I’ve tried to cowl as many instances as doable, even those you’ll most likely by no means want. That mentioned, it’s good to have an concept of methods to construct varied tooltip shapes.

One Final Thought

If we do the rely, we’ve made 32 completely different tooltip shapes. That’s two varieties of shade (strong 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 considering: Why didn’t I merely share the final snippet and name it a day? Did this text actually should be so lengthy once we might have jumped straight into the answer?

Positive, we might have carried out that, however In the event you examine the primary instance with solely two CSS properties with the final instance, the code for the final instance is much too advanced to create what can in any other case be achieved in fewer strains. We began with a fundamental tooltip form and launched into a journey to make it account for extra advanced varieties of tooltips. Plus, we’ve discovered a number of tips that may be helpful in different conditions and never essentially for creating tooltips.

Conclusion

That’s all for Half 1 of this temporary 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 reality, right here’s a bit homework to assist put together you for Half 2: strive creating the next tooltips utilizing the CSS tips you discovered from this text.

Showing four different tooltip shapes
(Giant 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 can find a special (or maybe higher) method than mine.

Smashing Editorial
(gg, yk)
RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments