{"id":363,"date":"2024-03-01T11:00:00","date_gmt":"2024-03-01T12:00:00","guid":{"rendered":"http:\/\/sobre-portugal.com\/?p=363"},"modified":"2024-06-12T20:24:55","modified_gmt":"2024-06-12T20:24:55","slug":"modern-css-tooltips-and-speech-bubbles-part-1","status":"publish","type":"post","link":"http:\/\/sobre-portugal.com\/index.php\/2024\/03\/01\/modern-css-tooltips-and-speech-bubbles-part-1\/","title":{"rendered":"Modern CSS Tooltips And Speech Bubbles (Part 1)"},"content":{"rendered":"

Modern CSS Tooltips And Speech Bubbles (Part 1)<\/title><\/p>\n<article>\n<header>\n<h1>Modern CSS Tooltips And Speech Bubbles (Part 1)<\/h1>\n<address>Temani Afif<\/address>\n<p> 2024-03-01T12:00:00+00:00<br \/>\n 2024-06-12T20:05:40+00:00<br \/>\n <\/header>\n<p>In <a href=\"https:\/\/www.smashingmagazine.com\/2023\/11\/css-responsive-multi-line-ribbon-shapes-part1\/\">a previous article<\/a>, we explored ribbon shapes and different ways to approach them using clever combinations of CSS gradients and <code>clip-path()<\/code>. This time, I\u2019d like to explore another shape, one that you\u2019ve likely had to tackle at least once in your front-end life: <strong>tooltips<\/strong>. You know what we\u2019re talking about, those little things that look like speech bubbles from comic books. They\u2019re everywhere in the wild, from a <a href=\"https:\/\/css-tricks.com\/long-hover\/\">hover effect for buttons<\/a> to <a href=\"https:\/\/css-tricks.com\/introducing-trashy-css\/\">the text messaging app on your phone<\/a>.<\/p>\n<p>The shapes may look easy to make in CSS at first glance, but it always ends with a lot of struggles. For example, how do you adjust the position of the tail to indicate whether the tooltip is coming from a left, right, or center position? There are <a href=\"https:\/\/www.smashingmagazine.com\/2021\/02\/designing-tooltips-mobile-user-interfaces\/\">plenty of considerations to take into account<\/a> when making tooltips \u2014 including <a href=\"https:\/\/css-tricks.com\/can-css-prevent-tooltips-from-overflowing\/\">overflowage<\/a>, <a href=\"https:\/\/css-tricks.com\/collision-detection\/\">collision detection<\/a>, and <a href=\"https:\/\/css-tricks.com\/exploring-what-the-details-and-summary-elements-can-do\/\">semantics<\/a> \u2014 but it\u2019s the shape and direction of the tail that I want to focus on because I often see inflexible fixed units used to position them.<\/p>\n<p>Forget what you already know about tooltips because in this article, we will start from zero, and you will learn how to build a tooltip with minimal markup powered by modern CSS that provides flexibility to configure the component by adjusting CSS variables. We are not going to build one or two shapes, but\u2026 <em>100 different shapes!<\/em><\/p>\n<p>That may sound like we\u2019re getting into a super-long article, but actually, we can easily get there by adjusting a few values. In the end, you will have a back pocket full of CSS tricks that can be combined to create any shape you want.<\/p>\n<p>And guess what? I\u2019ve already created <a href=\"https:\/\/css-generators.com\/tooltip-speech-bubble\/\">an online collection of 100 different tooltip shapes<\/a> where you can easily copy and paste the code for your own use, but stay with me. You\u2019re going to want to know the secret to unlocking hundreds of possibilities with the least possible code.<\/p>\n<p>We\u2019ll start with the shapes themselves, discussing how we can cut out the bubble and tail by combining CSS gradients and clipping. Then, we\u2019ll pick things back up in a second article dedicated to improving another common approach to tooltips using borders and custom shapes.<\/p>\n<h2 id=\"the-html\">The HTML<\/h2>\n<p>We\u2019re only working with a single element:<\/p>\n<pre><code class=\"language-html\"><div class=\"tooltip\">Your text content goes here<\/div>\n<\/code><\/pre>\n<p>That\u2019s the challenge: Create hundreds of tooltip variations in CSS with only a single element to hook into in the HTML.<\/p>\n<div data-audience=\"non-subscriber\" data-remove=\"true\" class=\"feature-panel-container\">\n<aside class=\"feature-panel\">\n<div class=\"feature-panel-left-col\">\n<div class=\"feature-panel-description\">\n<p>Meet <strong><a data-instant href=\"https:\/\/www.smashingconf.com\/online-workshops\/\">Smashing Workshops<\/a><\/strong> on <strong>front-end, design & UX<\/strong>, with practical takeaways, live sessions, <strong>video recordings<\/strong> and a friendly Q&A. With Brad Frost, St\u00e9ph Walter and <a href=\"https:\/\/smashingconf.com\/online-workshops\/workshops\">so many others<\/a>.<\/p>\n<p><a data-instant href=\"smashing-workshops\" class=\"btn btn--green btn--large\">Jump to the workshops \u21ac<\/a><\/div>\n<\/div>\n<div class=\"feature-panel-right-col\"><a data-instant href=\"smashing-workshops\" class=\"feature-panel-image-link\"><\/p>\n<div class=\"feature-panel-image\">\n<img decoding=\"async\" loading=\"lazy\" class=\"feature-panel-image-img\" src=\"\/images\/smashing-cat\/cat-scubadiving-panel.svg\" alt=\"Feature Panel\" width=\"257\" height=\"355\" \/><\/p>\n<\/div>\n<p><\/a>\n<\/div>\n<\/aside>\n<\/div>\n<h2 id=\"a-simple-tooltip-tail\">A Simple Tooltip Tail<\/h2>\n<p>I\u2019m going to skip right over the basic rectangular shape; you know how to set a <code>width<\/code> and <code>height<\/code> (or <code>aspect-ratio<\/code>) on elements. Let\u2019s start with <a href=\"https:\/\/css-tip.com\/simple-tooltip\/\">the simplest shape<\/a> for the tooltip\u2019s tail, one that can be accomplished with only two CSS properties:<\/p>\n<pre><code class=\"language-css\">.tooltip {\n \/* tail dimension *\/\n --b: 2em; \/* base *\/\n --h: 1em; \/* height*\/\n\n border-image: fill 0 \/\/ var(--h)\n conic-gradient(#CC333F 0 0); \/* the color *\/\n clip-path: \n polygon(0 100%, 0 0, 100% 0, 100% 100%,\n calc(50% + var(--b) \/ 2) 100%,\n 50% calc(100% + var(--h)),\n calc(50% - var(--b) \/ 2) 100%);\n}\n<\/code><\/pre>\n<p>The <code>border-image<\/code> property creates an \u201coverflowing color\u201d while <code>clip-path<\/code> defines the shape of the tooltip with <code>polygon()<\/code> coordinates. (Speaking of <code>border-image<\/code>, <a href=\"https:\/\/www.smashingmagazine.com\/2024\/01\/css-border-image-property\/\">I wrote a deep-dive on it<\/a> and explain how it might be the only CSS property that supports double slashes in the syntax!)<\/p>\n<p>The tooltip\u2019s tail is placed at the bottom center, and we have two variables to control its dimensions:<\/p>\n<figure class=\"\n \n break-out article__image\n \n \n \"><\/p>\n<p> <a href=\"https:\/\/files.smashing.media\/articles\/modern-css-tooltips-part1\/1-border-image-coloration-clip-path-polygon.png\"><\/p>\n<p> <img decoding=\"async\" loading=\"lazy\" width=\"800\" height=\"270\" src=\"https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_80\/w_400\/https:\/\/files.smashing.media\/articles\/modern-css-tooltips-part1\/1-border-image-coloration-clip-path-polygon.png\" alt=\"Illustrating the border-image coloration and the clip-path polygon()\" \/><\/p>\n<p> <\/a><figcaption class=\"op-vertical-bottom\">\n (<a href=\"https:\/\/files.smashing.media\/articles\/modern-css-tooltips-part1\/1-border-image-coloration-clip-path-polygon.png\">Large preview<\/a>)<br \/>\n <\/figcaption><\/figure>\n<p>We can do the exact same thing in more intuitive ways, like defining a background and then border (or padding) to create space for the tail:<\/p>\n<pre><code class=\"language-css\">background: #CC333F;\nborder-bottom: var(--h) solid #0000;\n<\/code><\/pre>\n<p>\u2026or using <code>box-shadow<\/code> (or <code>outline<\/code>) for the outside color:<\/p>\n<pre><code class=\"language-css\">background: #CC333F;\nbox-shadow: 0 0 0 var(--h) #CC333F;\n<\/code><\/pre>\n<p>While these approaches are indeed easier, they require an extra declaration compared to the single <code>border-image<\/code> declaration we used. Plus, we\u2019ll see later that <code>border-image<\/code> is really useful for accomplishing more complex shapes.<\/p>\n<p>Here is a demo with the different directions so you can see how easy it is to adjust the above code to change the tail\u2019s position.<\/p>\n<figure class=\"break-out\">\n<p data-height=\"480\" data-theme-id=\"light\" data-slug-hash=\"ExrEXoO\" data-user=\"t_afif\" data-default-tab=\"result\" class=\"codepen\">See the Pen [A simple Tooltip using 2 CSS properties](https:\/\/codepen.io\/smashingmag\/pen\/ExrEXoO) by <a href=\"https:\/\/codepen.io\/t_afif\">Temani Afif<\/a>.<\/p><figcaption>See the Pen <a href=\"https:\/\/codepen.io\/smashingmag\/pen\/ExrEXoO\">A simple Tooltip using 2 CSS properties<\/a> by <a href=\"https:\/\/codepen.io\/t_afif\">Temani Afif<\/a>.<\/figcaption><\/figure>\n<p>Next, we\u2019re going to study shapes that include the tail at the bottom, but you can easily find the other variations in <a href=\"https:\/\/css-generators.com\/tooltip-speech-bubble\/\">my online collection<\/a>.<\/p>\n<h2 id=\"adjusting-the-tail-position\">Adjusting The Tail Position<\/h2>\n<p>Let\u2019s add a third variable, <code>--p<\/code>, that we can use to control the tooltip\u2019s tail position. In the last example, we used <code>50%<\/code> in the <code>clip-path<\/code>, which positions the tail directly in the horizontal center along the bottom of the tooltip\u2019s rectangular shape. If we assign a variable to it, we can easily change the direction of the tooltip to face left or right by updating <code>50%<\/code> to a smaller or larger value, respectively.<\/p>\n<pre><code class=\"language-css\">.tooltip {\n \/* tail dimension *\/\n --b: 2em; \/* base *\/\n --h: 1em; \/* height*\/\n --p: 50%; \/* tail position *\/ \n\n border-image: fill 0 \/\/ var(--h)\n conic-gradient(#CC333F 0 0); \/* the color *\/\n clip-path: \n polygon(0 100%, 0 0, 100% 0, 100% 100%,\n calc(var(--p) + var(--b) \/ 2) 100%,\n var(--p) calc(100% + var(--h)),\n calc(var(--p) - var(--b) \/ 2) 100%);\n}\n<\/code><\/pre>\n<p>The <code>--p<\/code> variable can go from <code>0%<\/code> to <code>100%<\/code>, where <code>0%<\/code> is aligned with the left side of the tooltip and <code>100%<\/code> is aligned with the right side. Here is an interactive demo where you can update the variable using a range slider:<\/p>\n<figure class=\"break-out\">\n<p data-height=\"480\" data-theme-id=\"light\" data-slug-hash=\"mdoLOGJ\" data-user=\"t_afif\" data-default-tab=\"result\" class=\"codepen\">See the Pen [Updating the tail position](https:\/\/codepen.io\/smashingmag\/pen\/mdoLOGJ) by <a href=\"https:\/\/codepen.io\/t_afif\">Temani Afif<\/a>.<\/p><figcaption>See the Pen <a href=\"https:\/\/codepen.io\/smashingmag\/pen\/mdoLOGJ\">Updating the tail position<\/a> by <a href=\"https:\/\/codepen.io\/t_afif\">Temani Afif<\/a>.<\/figcaption><\/figure>\n<p>Nice, right?! It\u2019s definitely cool, but there\u2019s a glitch. When the tail\u2019s position is set to the extremes, it appears to slide right off the edge of the bubble. Go ahead and toggle the range slider in the demo between <code>0%<\/code> and <code>100%<\/code> to see the issue.<\/p>\n<figure class=\"\n \n break-out article__image\n \n \n \"><\/p>\n<p> <a href=\"https:\/\/files.smashing.media\/articles\/modern-css-tooltips-part1\/2-rectangle-tooltip.png\"><\/p>\n<p> <img decoding=\"async\" loading=\"lazy\" width=\"800\" height=\"223\" src=\"https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_80\/w_400\/https:\/\/files.smashing.media\/articles\/modern-css-tooltips-part1\/2-rectangle-tooltip.png\" alt=\"Red rectangle tooltip where the tail of the tooltip is overflowing the container.\" \/><\/p>\n<p> <\/a><figcaption class=\"op-vertical-bottom\">\n The tooltip’s tail is allowed to overflow its container at the extremes. (<a href=\"https:\/\/files.smashing.media\/articles\/modern-css-tooltips-part1\/2-rectangle-tooltip.png\">Large preview<\/a>)<br \/>\n <\/figcaption><\/figure>\n<p>We can fix this by setting limits to some values so the tail never falls outside the container. Two points of the polygon are concerned with the fix.<\/p>\n<p>This:<\/p>\n<pre><code class=\"language-css\">calc(var(--p) + var(--b) \/ 2) 100%\n<\/code><\/pre>\n<p>\u2026and this:<\/p>\n<pre><code class=\"language-css\">calc(var(--p) - var(--b) \/ 2) 100%\n<\/code><\/pre>\n<p>The first <code>calc()<\/code> needs to be clamped to <code>100%<\/code> to avoid the overflow from the right side, and the second one needs to be clamped to <code>0%<\/code> to avoid the overflow from the left side. We can use the <code>min()<\/code> and <code>max()<\/code> functions to establish the range limits:<\/p>\n<pre><code class=\"language-css\">clip-path: \n polygon(0 100%, 0 0, 100% 0, 100% 100%,<\/code>\n <code style=\"font-weight: bold\">min(100%, var(--p) + var(--b) \/ 2) 100%,<\/code>\n <code class=\"language-css\">var(--p) calc(100% + var(--h)),<\/code>\n <code style=\"font-weight: bold\">max(0%, var(--p) - var(--b) \/ 2) 100%);\n<\/code><\/pre>\n<figure class=\"break-out\">\n<p data-height=\"480\" data-theme-id=\"light\" data-slug-hash=\"mdoLRVr\" data-user=\"t_afif\" data-default-tab=\"result\" class=\"codepen\">See the Pen [Fixing the overflow issue](https:\/\/codepen.io\/smashingmag\/pen\/mdoLRVr) by <a href=\"https:\/\/codepen.io\/t_afif\">Temani Afif<\/a>.<\/p><figcaption>See the Pen <a href=\"https:\/\/codepen.io\/smashingmag\/pen\/mdoLRVr\">Fixing the overflow issue<\/a> by <a href=\"https:\/\/codepen.io\/t_afif\">Temani Afif<\/a>.<\/figcaption><\/figure>\n<p><em>Tada!<\/em> We\u2019ve fixed the edge cases, and now the tail gets a different shape instead of overflowing!<\/p>\n<figure class=\"\n \n break-out article__image\n \n \n \"><\/p>\n<p> <a href=\"https:\/\/files.smashing.media\/articles\/modern-css-tooltips-part1\/3-tail-left-right-edges-tooltip.png\"><\/p>\n<p> <img decoding=\"async\" loading=\"lazy\" width=\"800\" height=\"218\" src=\"https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_80\/w_400\/https:\/\/files.smashing.media\/articles\/modern-css-tooltips-part1\/3-tail-left-right-edges-tooltip.png\" alt=\"Illustrating the tail\u2019s at the left and right edges of the tooltip\" \/><\/p>\n<p> <\/a><figcaption class=\"op-vertical-bottom\">\n (<a href=\"https:\/\/files.smashing.media\/articles\/modern-css-tooltips-part1\/3-tail-left-right-edges-tooltip.png\">Large preview<\/a>)<br \/>\n <\/figcaption><\/figure>\n<div class=\"partners__lead-place\"><\/div>\n<h2 id=\"adjusting-the-tail-shape\">Adjusting The Tail Shape<\/h2>\n<p>Let\u2019s integrate another variable, <code>--x<\/code>, into the <code>clip-path()<\/code> and use it to adjust the shape of the tail:<\/p>\n<pre><code class=\"language-css\">.tooltip {\n \/* tail dimension *\/\n --b: 2em; \/* base *\/\n --h: 1em; \/* height*\/\n\n --p: 50%; \/* tail position *\/<\/code>\n <code style=\"font-weight: bold\">--x: -2em; \/* tail shape *\/<\/code>\n\n <code class=\"language-css\">border-image: fill 0 \/\/ 9999px\n conic-gradient(#CC333F 0 0); \/* the color *\/\n clip-path: \n polygon(0 100%, 0 0, 100% 0, 100% 100%,\n min(100%, var(--p) + var(--b) \/ 2) 100%,<\/code>\n <code style=\"font-weight: bold\">calc(var(--p) + var(--x)) calc(100% + var(--h)),<\/code>\n <code class=\"language-css\">max(0%, var(--p) - var(--b) \/ 2) 100%);\n}\n<\/code><\/pre>\n<p>The <code>--x<\/code> variable can be either positive or negative (using whatever unit you want, including percentages). What we\u2019re doing is adding the variable that establishes the tail\u2019s shape, <code>--x<\/code>, to the tail\u2019s position, <code>--p<\/code>. In other words, we\u2019ve updated this:<\/p>\n<pre><code class=\"language-css\">var(--p) calc(100% + var(--h))\n<\/code><\/pre>\n<p>\u2026to this:<\/p>\n<pre><code class=\"language-css\">calc(var(--p) + var(--x)) calc(100% + var(--h))\n<\/code><\/pre>\n<p>And here is the outcome:<\/p>\n<figure class=\"\n \n break-out article__image\n \n \n \"><\/p>\n<p> <a href=\"https:\/\/files.smashing.media\/articles\/modern-css-tooltips-part1\/4-variations-same-red-rectangular-tooltip.png\"><\/p>\n<p> <img decoding=\"async\" loading=\"lazy\" width=\"800\" height=\"203\" src=\"https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_80\/w_400\/https:\/\/files.smashing.media\/articles\/modern-css-tooltips-part1\/4-variations-same-red-rectangular-tooltip.png\" alt=\"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.\" \/><\/p>\n<p> <\/a><figcaption class=\"op-vertical-bottom\">\n (<a href=\"https:\/\/files.smashing.media\/articles\/modern-css-tooltips-part1\/4-variations-same-red-rectangular-tooltip.png\">Large preview<\/a>)<br \/>\n <\/figcaption><\/figure>\n<p>The tooltip\u2019s tail points in either the right or left direction, depending on whether <code>--x<\/code> is a positive or negative value. Go ahead and use the range sliders in the following demo to see how the tooltip\u2019s tail is re-positioned (<code>--p<\/code>) and re-shaped (<code>--x<\/code>) when adjusting two variables.<\/p>\n<figure class=\"break-out\">\n<p data-height=\"480\" data-theme-id=\"light\" data-slug-hash=\"ExMLZZB\" data-user=\"t_afif\" data-default-tab=\"result\" class=\"codepen\">See the Pen [Updating the tail shape](https:\/\/codepen.io\/smashingmag\/pen\/ExMLZZB) by <a href=\"https:\/\/codepen.io\/t_afif\">Temani Afif<\/a>.<\/p><figcaption>See the Pen <a href=\"https:\/\/codepen.io\/smashingmag\/pen\/ExMLZZB\">Updating the tail shape<\/a> by <a href=\"https:\/\/codepen.io\/t_afif\">Temani Afif<\/a>.<\/figcaption><\/figure>\n<p>Cool, right? If you\u2019ve ever attempted tooltips on your own, I\u2019m sure you will appreciate the way this approach eliminates the need to use magic numbers to tweak the tooltip\u2019s appearance. That\u2019s one significant headache we no longer have to worry about!<\/p>\n<p>And did you notice how the tail, when stretched, is allowed to overflow the container? That\u2019s perfect! Using <code>min()<\/code> and <code>max()<\/code>, we\u2019re correctly fixing the overflow issue while allowing the tail to stretch further away from the container.<\/p>\n<figure class=\"\n \n break-out article__image\n \n \n \"><\/p>\n<p> <a href=\"https:\/\/files.smashing.media\/articles\/modern-css-tooltips-part1\/5-rectangular-tooltip-different-tale-positions.png\"><\/p>\n<p> <img decoding=\"async\" loading=\"lazy\" width=\"800\" height=\"206\" src=\"https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_80\/w_400\/https:\/\/files.smashing.media\/articles\/modern-css-tooltips-part1\/5-rectangular-tooltip-different-tale-positions.png\" alt=\"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.\" \/><\/p>\n<p> <\/a><figcaption class=\"op-vertical-bottom\">\n (<a href=\"https:\/\/files.smashing.media\/articles\/modern-css-tooltips-part1\/5-rectangular-tooltip-different-tale-positions.png\">Large preview<\/a>)<br \/>\n <\/figcaption><\/figure>\n<p>Note that I have updated the <code>border-image<\/code> outset to an impractically large value (<code>9999px<\/code>) instead of using the <code>--h<\/code> variable. The shape of the tail can be any type of triangle and can take a bigger area. Since there\u2019s no way for us to know the exact value of the outset, we use that big value to make sure we have enough room to fill the tail in with color, no matter its shape.<\/p>\n<p>Does the outset concept look strange to you? I know that working with <code>border-image<\/code> isn\u2019t something many of us do all that often, so if this approach is tough to wrap your head around, definitely go check out <a href=\"https:\/\/www.smashingmagazine.com\/2024\/01\/css-border-image-property\/\">my <code>border-image<\/code> article<\/a> for a thorough demonstration of how it works.<\/p>\n<h2 id=\"working-with-gradients\">Working With Gradients<\/h2>\n<p>Most of the trouble starts when we want to color the tooltip with a gradient instead of a flat color. Applying one color is simple \u2014 even with older techniques \u2014 but when it comes to gradients, it\u2019s not easy to make the tail color flow smoothly into the container\u2019s color.<\/p>\n<p>But guess what? That\u2019s no problem for us because we are already using a gradient in our <code>border-image<\/code> declaration!<\/p>\n<pre><code class=\"language-css\">border-image: fill 0 \/\/ var(--h)\n conic-gradient(#CC333F 0 0);\n<\/code><\/pre>\n<p><code>border-image<\/code> only accepts gradients or images, so to produce a solid color, I had to use a gradient consisting of just one color. But if you change it into a \u201creal\u201d gradient that transitions between two or more colors, then you get your tooltip gradient. That\u2019s all!<\/p>\n<figure class=\"break-out\">\n<p data-height=\"480\" data-theme-id=\"light\" data-slug-hash=\"GRedryE\" data-user=\"t_afif\" data-default-tab=\"result\" class=\"codepen\">See the Pen [Adding gradient coloration](https:\/\/codepen.io\/smashingmag\/pen\/GRedryE) by <a href=\"https:\/\/codepen.io\/t_afif\">Temani Afif<\/a>.<\/p><figcaption>See the Pen <a href=\"https:\/\/codepen.io\/smashingmag\/pen\/GRedryE\">Adding gradient coloration<\/a> by <a href=\"https:\/\/codepen.io\/t_afif\">Temani Afif<\/a>.<\/figcaption><\/figure>\n<p>The only thing we need to pay attention to is the outset value. When using one color, we don\u2019t really care what the outset value is; it just needs to be as big as possible to cover the <code>clip-path<\/code> area, as we did when setting it to <code>9999px<\/code>. However, when working with multiple colors, we should not use too big of a value so that we avoid clipping the gradient by accident.<\/p>\n<p>In the last demo, you will notice I am using a value equal to <code>0 0 var(--h) 0<\/code>, which means that we are setting only a bottom outset; the tail is at the bottom, and the gradient will not extend in all the directions as it did in the other examples. I don\u2019t want to get into all of the various edge cases that could come up, but if you have trouble working with the gradient\u2019s color, it\u2019s usually the <code>border-image<\/code>\u2019s outset value that you need to check.<\/p>\n<h2 id=\"working-with-rounded-corners\">Working With Rounded Corners<\/h2>\n<p>If we try to add a <code>border-radius<\/code> to the previous examples, nothing happens. That\u2019s because the <code>border-radius<\/code> and <code>border-image<\/code> properties aren\u2019t really all that good of friends. We need to tweak <code>border-image<\/code> and combine it with <code>background<\/code> to get things working right.<\/p>\n<figure class=\"\n \n break-out article__image\n \n \n \"><\/p>\n<p> <a href=\"https:\/\/files.smashing.media\/articles\/modern-css-tooltips-part1\/6-steps-create-rounded-tooltip-corners-sequential-order.png\"><\/p>\n<p> <img decoding=\"async\" loading=\"lazy\" width=\"800\" height=\"278\" src=\"https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_80\/w_400\/https:\/\/files.smashing.media\/articles\/modern-css-tooltips-part1\/6-steps-create-rounded-tooltip-corners-sequential-order.png\" alt=\"Illustrating the three steps needed to create rounded tooltip corners in sequential order.\" \/><\/p>\n<p> <\/a><figcaption class=\"op-vertical-bottom\">\n (<a href=\"https:\/\/files.smashing.media\/articles\/modern-css-tooltips-part1\/6-steps-create-rounded-tooltip-corners-sequential-order.png\">Large preview<\/a>)<br \/>\n <\/figcaption><\/figure>\n<p>We start by declaring a <code>background<\/code> and <code>border-radius<\/code> on the <code>.tooltip<\/code>. Nothing fancy. Then, we move to the <code>border-image<\/code> property so that we can add a bar (highlighted in red in the last figure) that slightly overflows the container from the bottom. This part is a bit tricky, and here I invite you to read <a href=\"https:\/\/www.smashingmagazine.com\/2024\/01\/css-border-image-property\/\">my previous article about <code>border-image<\/code><\/a> to understand this bit of CSS magic. From there, we add the <code>clip-path<\/code> and get our final shape.<\/p>\n<div class=\"break-out\">\n<pre><code class=\"language-css\">.tooltip {\n \/* triangle dimension *\/\n --b: 2em; \/* base *\/\n --h: 1em; \/* height *\/\n\n--p: 50%; \/* position *\/\n--r: 1.2em; \/* the radius *\/\n--c: #4ECDC4;\n\nborder-radius: var(--r);\nclip-path: polygon(0 100%, 0 0, 100% 0, 100% 100%,\nmin(100%, var(--p) + var(--b) \/ 2) 100%,\nvar(--p) calc(100% + var(--h)),\nmax(0%, var(--p) - var(--b) \/ 2) 100%);\nbackground: var(--c);\nborder-image: conic-gradient(var(--c) 0 0) fill 0\/\nvar(--r) calc(100% - var(--p) - var(--b) \/ 2) 0 calc(var(--p) - var(--b) \/ 2)\/\n0 0 var(--h) 0;\n} <\/code><\/pre>\n<\/div>\n<figure class=\"break-out\">\n<p data-height=\"480\" data-theme-id=\"light\" data-slug-hash=\"MWxGvYg\" data-user=\"t_afif\" data-default-tab=\"result\" class=\"codepen\">See the Pen [Adding border radius](https:\/\/codepen.io\/smashingmag\/pen\/MWxGvYg) by <a href=\"https:\/\/codepen.io\/t_afif\">Temani Afif<\/a>.<\/p><figcaption>See the Pen <a href=\"https:\/\/codepen.io\/smashingmag\/pen\/MWxGvYg\">Adding border radius<\/a> by <a href=\"https:\/\/codepen.io\/t_afif\">Temani Afif<\/a>.<\/figcaption><\/figure>\n<p>We are good but still have a tiny issue when the tail gets close to the extreme edges.<\/p>\n<figure class=\"\n \n break-out article__image\n \n \n \"><\/p>\n<p> <a href=\"https:\/\/files.smashing.media\/articles\/modern-css-tooltips-part1\/7-jagged-edge-tail-tooltip.png\"><\/p>\n<p> <img decoding=\"async\" loading=\"lazy\" width=\"800\" height=\"198\" src=\"https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_80\/w_400\/https:\/\/files.smashing.media\/articles\/modern-css-tooltips-part1\/7-jagged-edge-tail-tooltip.png\" alt=\"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.\" \/><\/p>\n<p> <\/a><figcaption class=\"op-vertical-bottom\">\n (<a href=\"https:\/\/files.smashing.media\/articles\/modern-css-tooltips-part1\/7-jagged-edge-tail-tooltip.png\">Large preview<\/a>)<br \/>\n <\/figcaption><\/figure>\n<p>This visual glitch happens when the <code>border-image<\/code> overlaps with the rounded corners. To fix this, we need to adjust the <code>border-radius<\/code> value based on the tail\u2019s position (<code>--p<\/code>).<\/p>\n<p>We are not going to update all the radii, only the bottom ones and, more precisely, the horizontal values. I want to remind you that <code>border-radius<\/code> accepts up to eight values \u2014 each corner takes two values that set the horizontal and vertical directions \u2014 and in our case, we will update the horizontal value of the bottom-left and bottom-right corners:<\/p>\n<div class=\"break-out\">\n<pre><code class=\"language-css\">border-radius:\n \/* horizontal values *\/\n var(--r) \n var(--r) \n min(var(--r),100% - var(--p) - var(--b)\/2) \/* horizontal bottom-right *\/\n min(var(--r),var(--p) - var(--b)\/2) \/* horizontal bottom-left *\/\n \/\n \/* vertical values *\/\n var(--r)\n var(--r)\n var(--r)\n var(--r)\n<\/code><\/pre>\n<\/div>\n<p>All the corner values are equal to <code>--r<\/code>, except for the bottom-left and bottom-right corners. Notice the forward slash (<code>\/<\/code>), as it is part of the syntax that separates the horizontal and vertical radii values.<\/p>\n<p>Now, let\u2019s dig in and understand what is happening here. For the bottom-left corner, when the position of the tail is on the right, the position (<code>--p<\/code>) variable value will be big in order to keep the radius equal to the radius (<code>--r<\/code>), which serves as the minimum value. But when the position gets closer to the left, the value of <code>--p<\/code> decreases and, at some point, becomes smaller than the value of <code>--r<\/code>. The result is the value of the radius slowly decreasing until it reaches <code>0<\/code>. It adjusts as the position updates!<\/p>\n<p>I know that\u2019s a lot to process, and a visual aid usually helps. Try slowly updating the tail\u2019s position in the following demo to get a clearer picture of what\u2019s happening.<\/p>\n<figure class=\"break-out\">\n<p data-height=\"480\" data-theme-id=\"light\" data-slug-hash=\"ZEPoJpG\" data-user=\"t_afif\" data-default-tab=\"result\" class=\"codepen\">See the Pen [Fixing the edge cases](https:\/\/codepen.io\/smashingmag\/pen\/ZEPoJpG) by <a href=\"https:\/\/codepen.io\/t_afif\">Temani Afif<\/a>.<\/p><figcaption>See the Pen <a href=\"https:\/\/codepen.io\/smashingmag\/pen\/ZEPoJpG\">Fixing the edge cases<\/a> by <a href=\"https:\/\/codepen.io\/t_afif\">Temani Afif<\/a>.<\/figcaption><\/figure>\n<p>What about instances when we want a custom shape for the tail? The technique we just used will only work when the tail has two equal sides \u2014 you know, an isosceles triangle. We need to adjust the <code>border-image<\/code> value and consider another trick to get things working correctly again.<\/p>\n<figure class=\"\n \n break-out article__image\n \n \n \"><\/p>\n<p> <a href=\"https:\/\/files.smashing.media\/articles\/modern-css-tooltips-part1\/8-steps-correcting-tooltip-overflow.png\"><\/p>\n<p> <img decoding=\"async\" loading=\"lazy\" width=\"800\" height=\"275\" src=\"https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_80\/w_400\/https:\/\/files.smashing.media\/articles\/modern-css-tooltips-part1\/8-steps-correcting-tooltip-overflow.png\" alt=\"Illustrating three steps for correcting the tooltip\u2019s overflow when the tail is a custom shape.\" \/><\/p>\n<p> <\/a><figcaption class=\"op-vertical-bottom\">\n (<a href=\"https:\/\/files.smashing.media\/articles\/modern-css-tooltips-part1\/8-steps-correcting-tooltip-overflow.png\">Large preview<\/a>)<br \/>\n <\/figcaption><\/figure>\n<p>This time, the border image creates a horizontal bar along the bottom that is positioned directly under the element and extends outside of its boundary so that we have enough color for the tail when it\u2019s closer to the edge.<\/p>\n<div class=\"break-out\">\n<pre><code class=\"language-css\">.tooltip {\n \/* tail dimension *\/\n --b: 2em; \/* base *\/\n --h: 1.5em; \/* height *\/\n\n--p: 50%; \/* position *\/\n--x: 1.8em; \/* tail position *\/\n--r: 1.2em; \/* the radius *\/\n--c: #4ECDC4;\n\nborder-radius: var(--r) var(--r) min(var(--r), 100% - var(--p) - var(--b) \/ 2) min(var(--r), var(--p) - var(--b) \/ 2) \/ var(--r);\nclip-path: polygon(0 100%, 0 0, 100% 0, 100% 100%,\nmin(100%, var(--p) + var(--b) \/ 2) 100%,\ncalc(var(--p) + var(--x)) calc(100% + var(--h)),\nmax(0%, var(--p) - var(--b) \/ 2) 100%);\nbackground: var(--c);\nborder-image: conic-gradient(var(--c) 0 0) 0 0 1 0 \/ 0 0 var(--h) 0 \/ 0 999px var(--h) 999px;\n} <\/code><\/pre>\n<\/div>\n<figure class=\"break-out\">\n<p data-height=\"480\" data-theme-id=\"light\" data-slug-hash=\"MWxGEpv\" data-user=\"t_afif\" data-default-tab=\"result\" class=\"codepen\">See the Pen [Custom tail with border radius](https:\/\/codepen.io\/smashingmag\/pen\/MWxGEpv) by <a href=\"https:\/\/codepen.io\/t_afif\">Temani Afif<\/a>.<\/p><figcaption>See the Pen <a href=\"https:\/\/codepen.io\/smashingmag\/pen\/MWxGEpv\">Custom tail with border radius<\/a> by <a href=\"https:\/\/codepen.io\/t_afif\">Temani Afif<\/a>.<\/figcaption><\/figure>\n<p>Again, the <code>border-image<\/code> declaration looks strange and difficult because, well, it is! Please do yourself a favor and check <a href=\"https:\/\/www.smashingmagazine.com\/2024\/01\/css-border-image-property\/\">my previous article<\/a> if you want to dig deeper into this approach \u2014 you definitely won\u2019t regret it.<\/p>\n<p>\u201cWhy not use this approach for the first example we looked at?\u201d you might ask. You are right that we can use this same approach for the first example, even if we don\u2019t have the <code>--x<\/code> variable. That said, the reason we\u2019re not going in that direction is that there is a tiny drawback to it in some particular cases, as you can see in the figure below.<\/p>\n<figure class=\"\n \n break-out article__image\n \n \n \"><\/p>\n<p> <a href=\"https:\/\/files.smashing.media\/articles\/modern-css-tooltips-part1\/9-visual-imperfections-tooltip.png\"><\/p>\n<p> <img decoding=\"async\" loading=\"lazy\" width=\"800\" height=\"300\" src=\"https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_80\/w_400\/https:\/\/files.smashing.media\/articles\/modern-css-tooltips-part1\/9-visual-imperfections-tooltip.png\" alt=\"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.\" \/><\/p>\n<p> <\/a><figcaption class=\"op-vertical-bottom\">\n (<a href=\"https:\/\/files.smashing.media\/articles\/modern-css-tooltips-part1\/9-visual-imperfections-tooltip.png\">Large preview<\/a>)<br \/>\n <\/figcaption><\/figure>\n<p>That\u2019s why I do not use this approach when working with a simple isosceles triangle. This said, the method is perfectly fine, and in most cases, you may not see any visual glitches.<\/p>\n<div class=\"partners__lead-place\"><\/div>\n<h2 id=\"putting-everything-together\">Putting Everything Together<\/h2>\n<p>We\u2019ve looked at tooltips with tails that have equal sides, ones with tails that change shape, ones where the tail changes position and direction, ones with rounded corners, and ones that are filled in with gradients. What would it look like if we combined all of these examples into one mega-demo?<\/p>\n<p>We can do it, but not by combining the approaches we\u2019ve covered. We need another method, this time using a pseudo-element. No <code>border-image<\/code> for this one, I promise!<\/p>\n<div class=\"break-out\">\n<pre><code class=\"language-css\">.tooltip {\n \/* triangle dimension *\/\n --b: 2em; \/* base *\/\n --h: 1em; \/* height *\/\n\n--p: 50%; \/* position *\/\n--r: 1.2em; \/* the radius *\/\n\nborder-radius: var(--r) var(--r) min(var(--r), 100% - var(--p) - var(--b) \/ 2) min(var(--r), var(--p) - var(--b) \/ 2) \/ var(--r);\nbackground: 0 0 \/ 100% calc(100% + var(--h))\nlinear-gradient(60deg, #CC333F, #4ECDC4); \/* the gradient *\/\nposition: relative;\nz-index: 0;\n}\n.tooltip:before {\ncontent: \"\";\nposition: absolute;\nz-index: -1;\ninset: 0 0 calc(-1*var(--h));\nbackground-image: inherit;\nclip-path:\npolygon(50% 50%,\nmin(100%, var(--p) + var(--b) \/ 2) calc(100% - var(--h)),\nvar(--p) 100%,\nmax(0%, var(--p) - var(--b) \/ 2) calc(100% - var(--h)));\n} <\/code><\/pre>\n<\/div>\n<p>The pseudo-element is used to create the tail at the bottom and notice how it inherits the gradient from the main element to simulate a continuous gradient that covers the entire shape.<\/p>\n<figure class=\"\n \n break-out article__image\n \n \n \"><\/p>\n<p> <a href=\"https:\/\/files.smashing.media\/articles\/modern-css-tooltips-part1\/10-continuous-gradient.png\"><\/p>\n<p> <img decoding=\"async\" loading=\"lazy\" width=\"800\" height=\"138\" src=\"https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_80\/w_400\/https:\/\/files.smashing.media\/articles\/modern-css-tooltips-part1\/10-continuous-gradient.png\" alt=\"Showing the tail at bottom that inherits the gradient from the main element\" \/><\/p>\n<p> <\/a><figcaption class=\"op-vertical-bottom\">\n (<a href=\"https:\/\/files.smashing.media\/articles\/modern-css-tooltips-part1\/10-continuous-gradient.png\">Large preview<\/a>)<br \/>\n <\/figcaption><\/figure>\n<p>Another important thing to note is the <code>background-size<\/code> declared in the <code>.tooltip<\/code>. The pseudo-element is covering a bigger area due to the negative bottom value, so we have to increase the height of the gradient so it covers the same area.<\/p>\n<figure class=\"break-out\">\n<p data-height=\"480\" data-theme-id=\"light\" data-slug-hash=\"ZEPoayw\" data-user=\"t_afif\" data-default-tab=\"result\" class=\"codepen\">See the Pen [Gradient and border radius](https:\/\/codepen.io\/smashingmag\/pen\/ZEPoayw) by <a href=\"https:\/\/codepen.io\/t_afif\">Temani Afif<\/a>.<\/p><figcaption>See the Pen <a href=\"https:\/\/codepen.io\/smashingmag\/pen\/ZEPoayw\">Gradient and border radius<\/a> by <a href=\"https:\/\/codepen.io\/t_afif\">Temani Afif<\/a>.<\/figcaption><\/figure>\n<p>For the custom tail shape, we have to update the code slightly to consider the overflow on the left and right sides of the tooltip. The idea is to increase the gradient\u2019s area when the tail is about to leave the container.<\/p>\n<div class=\"break-out\">\n<pre><code class=\"language-css\">.tooltip {\n --p: 50%; \/* position *\/\n --x: -2em; \/* tail shape and direction *\/\n\n--_e: max(0%, -1 * var(--x) - var(--p), var(--x) + var(--p) - 100%);\n\nbackground:\n50% 0 \/ calc(100% + 2*var(--_e)) calc(100% + var(--h))\nlinear-gradient(60deg, #CC333F, #4ECDC4); \/* the gradient *\/\n}\n.tooltip:before {\ninset: 0 calc(-1 * var(--_e)) calc(-1 * var(--h));\npadding-inline: var(--_e);\n} <\/code><\/pre>\n<\/div>\n<p>Alongside the <code>--x<\/code> variable that controls the tail\u2019s shape and direction, I have introduced a new variable, <code>--_e<\/code>, that defines the gradient\u2019s width for covering the <code>.tooltip<\/code> as well as the pseudo-element\u2019s inline padding and its left and right values. It may look like a complex configuration, but the idea is that <code>--_e<\/code> will, in most cases, be equal to <code>0<\/code>, which gives us the same code as the last example we made. But when the tail overflows the <code>.tooltip<\/code> container, the <code>--_e<\/code> value increases, which increases the area of the gradient as well in order to cover the overflow.<\/p>\n<p>Play with the position and shape of the tail in the following demo and notice how the gradient changes when the tail overflows the sides.<\/p>\n<figure class=\"break-out\">\n<p data-height=\"480\" data-theme-id=\"light\" data-slug-hash=\"RwdyExJ\" data-user=\"t_afif\" data-default-tab=\"result\" class=\"codepen\">See the Pen [Custom tail with border radius and gradient](https:\/\/codepen.io\/smashingmag\/pen\/RwdyExJ) by <a href=\"https:\/\/codepen.io\/t_afif\">Temani Afif<\/a>.<\/p><figcaption>See the Pen <a href=\"https:\/\/codepen.io\/smashingmag\/pen\/RwdyExJ\">Custom tail with border radius and gradient<\/a> by <a href=\"https:\/\/codepen.io\/t_afif\">Temani Afif<\/a>.<\/figcaption><\/figure>\n<p>I know this last code may look complex (same for some of the previous ones), and for this reason, I created <a href=\"https:\/\/css-generators.com\/tooltip-speech-bubble\/\">an online collection of tooltips<\/a> from where you can easily grab the code. I\u2019ve tried to cover as many cases as possible, even the ones you will probably never need. That said, it\u2019s good to have an idea of how to build various tooltip shapes.<\/p>\n<h2 id=\"one-last-thought\">One Last Thought<\/h2>\n<p>If we do the count, we have made 32 different tooltip shapes. That\u2019s two types of color (solid or gradient), two types of corners (sharp or rounded) that produce four more variations, and two types of tail shapes (isosceles triangle and custom) for two additional variations, and four different tail positions (top, bottom, left, and right) which brings the final tally to 32 tooltip variations.<\/p>\n<p>The last example we studied can be used to produce all the shapes simply by adjusting the different variables.<\/p>\n<p>I know what you\u2019re thinking: Why didn\u2019t I simply share the last snippet and call it a day? Did this article really have to be so long when we could have jumped straight into the solution?<\/p>\n<p>Sure, we could have done that, but If you compare the first example with only two CSS properties with the last example, the code for the last example is far too complex to create what can otherwise be accomplished in fewer lines. We started with a basic tooltip shape and embarked on a journey to make it account for more complex types of tooltips. Plus, we have learned a lot of tricks that can be useful in other situations and not necessarily for creating tooltips.<\/p>\n<h2 id=\"conclusion\">Conclusion<\/h2>\n<p>That\u2019s all for Part 1 of this brief two-part series. We still have many more shapes to cover in <a href=\"\/2024\/03\/modern-css-tooltips-speech-bubbles-part2\/\">Part 2<\/a>, so take the time to digest what we covered in Part 1 before jumping ahead. In fact, here\u2019s a little homework to help prepare you for Part 2: try creating the following tooltips using the CSS tricks you learned from this article.<\/p>\n<figure class=\"\n \n break-out article__image\n \n \n \"><\/p>\n<p> <a href=\"https:\/\/files.smashing.media\/articles\/modern-css-tooltips-part1\/11-different-tooltip-shapes.png\"><\/p>\n<p> <img decoding=\"async\" loading=\"lazy\" width=\"800\" height=\"347\" src=\"https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_80\/w_400\/https:\/\/files.smashing.media\/articles\/modern-css-tooltips-part1\/11-different-tooltip-shapes.png\" alt=\"Showing four different tooltip shapes\" \/><\/p>\n<p> <\/a><figcaption class=\"op-vertical-bottom\">\n (<a href=\"https:\/\/files.smashing.media\/articles\/modern-css-tooltips-part1\/11-different-tooltip-shapes.png\">Large preview<\/a>)<br \/>\n <\/figcaption><\/figure>\n<p>Can you figure it out? The code for all of them is included in <a href=\"https:\/\/css-generators.com\/tooltip-speech-bubble\/\">my tooltip collection<\/a> if you need a reference, but do try to make them yourself \u2014 it\u2019s good exercise! Maybe you will find a different (or perhaps better) approach than mine.<\/p>\n<div class=\"signature\">\n <img decoding=\"async\" src=\"https:\/\/www.smashingmagazine.com\/images\/logo\/logo--red.png\" alt=\"Smashing Editorial\" width=\"35\" height=\"46\" loading=\"lazy\" \/><br \/>\n <span>(gg, yk)<\/span>\n<\/div>\n<\/article>\n","protected":false},"excerpt":{"rendered":"<p>Modern CSS Tooltips And Speech Bubbles (Part 1) Modern CSS Tooltips And Speech Bubbles (Part 1) Temani Afif 2024-03-01T12:00:00+00:00 2024-06-12T20:05:40+00:00 In a previous article, we explored ribbon shapes and different<\/p>\n<p class=\"more-link\"><a href=\"http:\/\/sobre-portugal.com\/index.php\/2024\/03\/01\/modern-css-tooltips-and-speech-bubbles-part-1\/\" class=\"readmore\">Continue reading<svg class=\"icon icon-arrow-right\" aria-hidden=\"true\" role=\"img\"> <use href=\"#icon-arrow-right\" xlink:href=\"#icon-arrow-right\"><\/use> <\/svg><span class=\"screen-reader-text\">Modern CSS Tooltips And Speech Bubbles (Part 1)<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8],"tags":[],"class_list":["post-363","post","type-post","status-publish","format-standard","hentry","category-css"],"_links":{"self":[{"href":"http:\/\/sobre-portugal.com\/index.php\/wp-json\/wp\/v2\/posts\/363","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/sobre-portugal.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/sobre-portugal.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/sobre-portugal.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/sobre-portugal.com\/index.php\/wp-json\/wp\/v2\/comments?post=363"}],"version-history":[{"count":1,"href":"http:\/\/sobre-portugal.com\/index.php\/wp-json\/wp\/v2\/posts\/363\/revisions"}],"predecessor-version":[{"id":364,"href":"http:\/\/sobre-portugal.com\/index.php\/wp-json\/wp\/v2\/posts\/363\/revisions\/364"}],"wp:attachment":[{"href":"http:\/\/sobre-portugal.com\/index.php\/wp-json\/wp\/v2\/media?parent=363"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/sobre-portugal.com\/index.php\/wp-json\/wp\/v2\/categories?post=363"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/sobre-portugal.com\/index.php\/wp-json\/wp\/v2\/tags?post=363"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}