Close Menu
    DevStackTipsDevStackTips
    • Home
    • News & Updates
      1. Tech & Work
      2. View All

      Sunshine And March Vibes (2025 Wallpapers Edition)

      May 16, 2025

      The Case For Minimal WordPress Setups: A Contrarian View On Theme Frameworks

      May 16, 2025

      How To Fix Largest Contentful Paint Issues With Subpart Analysis

      May 16, 2025

      How To Prevent WordPress SQL Injection Attacks

      May 16, 2025

      Microsoft has closed its “Experience Center” store in Sydney, Australia — as it ramps up a continued digital growth campaign

      May 16, 2025

      Bing Search APIs to be “decommissioned completely” as Microsoft urges developers to use its Azure agentic AI alternative

      May 16, 2025

      Microsoft might kill the Surface Laptop Studio as production is quietly halted

      May 16, 2025

      Minecraft licensing robbed us of this controversial NFL schedule release video

      May 16, 2025
    • Development
      1. Algorithms & Data Structures
      2. Artificial Intelligence
      3. Back-End Development
      4. Databases
      5. Front-End Development
      6. Libraries & Frameworks
      7. Machine Learning
      8. Security
      9. Software Engineering
      10. Tools & IDEs
      11. Web Design
      12. Web Development
      13. Web Security
      14. Programming Languages
        • PHP
        • JavaScript
      Featured

      The power of generators

      May 16, 2025
      Recent

      The power of generators

      May 16, 2025

      Simplify Factory Associations with Laravel’s UseFactory Attribute

      May 16, 2025

      This Week in Laravel: React Native, PhpStorm Junie, and more

      May 16, 2025
    • Operating Systems
      1. Windows
      2. Linux
      3. macOS
      Featured

      Microsoft has closed its “Experience Center” store in Sydney, Australia — as it ramps up a continued digital growth campaign

      May 16, 2025
      Recent

      Microsoft has closed its “Experience Center” store in Sydney, Australia — as it ramps up a continued digital growth campaign

      May 16, 2025

      Bing Search APIs to be “decommissioned completely” as Microsoft urges developers to use its Azure agentic AI alternative

      May 16, 2025

      Microsoft might kill the Surface Laptop Studio as production is quietly halted

      May 16, 2025
    • Learning Resources
      • Books
      • Cheatsheets
      • Tutorials & Guides
    Home»Development»The Little Triangle in the Tooltip

    The Little Triangle in the Tooltip

    December 20, 2024

    Tooltips are like homemade food: everyone uses them and everyone has their own recipe to make them. If you don’t remember a particular recipe, you will search for one, follow it, and go on with your day. This “many ways to do the same thing” concept is general to web development and programming (and life!), but it’s something that especially rings true with tooltips. There isn’t a specialized way to make them — and at this point, it isn’t needed — so people come up with different ways to fill those gaps.

    Today, I want to focus on just one step of the recipe, which due to lack of a better name, I’ll just call the little triangle in the tooltip. It’s one of those things that receives minimal attention (admittedly, I didn’t know much before writing this) but it amazes you how many ways there are to make them. Let’s start with the simplest and make our way up to the not-so-simple.

    Ideally, the tooltip is just one element. We want to avoid polluting our markup just for that little triangle:

    <span class="tooltip">I am a tooltip</span>

    Clever border

    Before running, we have to learn to walk. And before connecting that little triangle we have to learn to make a triangle. Maybe the most widespread recipe for a triangle is the border trick, one that can be found in Stack Overflow issues from 2010 or even here by Chris in 2016.

    In a nutshell, borders meet each other at 45° angles, so if an element has a border but no width and height, the borders will make four perfect triangles. What’s left is to set three border colors to transparent and only one triangle will show! You can find an animated version on this CodePen by Chris Coyier

    CodePen Embed Fallback

    Usually, our little triangle will be a pseudo-element of the tooltip, so we need to set its dimensions to 0px (which is something ::before and ::after already do) and only set one of the borders to a solid color. We can control the size of the triangle base by making the other borders wider, and the height by making the visible border larger.

    .tooltip {
      &::before {
        content: "";
    
        border-width: var(--triangle-base);
        border-style: solid;
        border-color: transparent;
    
        border-top: var(--triangle-height) solid red;
      }
    }

    Attaching the triangle to its tooltip is an art in itself, so I am going with the basics and setting the little triangle’s position to absolute and the .tooltip to relative, then playing with its inset properties to place it where we want. The only thing to notice is that we will have to translate the little triangle to account for its width, -50% if we are setting its position with the left property, and 50% if we are using right.

    .tooltip {
      position: relative;
    
      &::before {
        /* ... */
        position: absolute;
        top: var(--triangle-top);
        left: var(--triangle-left);
    
        transform: translateX(-50%);
      }
    }

    However, we could even use the new Anchor Positioning properties for the task. Whichever method you choose, we should now have that little triangle attached to the tooltip:

    CodePen Embed Fallback

    Rotated square

    One drawback from that last example is that we are blocking the border property so that if we need it for something else, we are out of luck. However, there is another old-school method to make that little triangle: we rotate a square by 45° degrees and hide half of it behind the tooltip’s body. This way, only the corner shows in the shape of a triangle. We can make the square out of a pseudo-element:

    .tooltip {
      &::before {
        content: "";
    
        display: block;
        height: var(--triangle-size);
        width: var(--triangle-size);
    
        background-color: red;
      }
    }

    Then, position it behind the tooltip’s body. In this case, such that only one-half shows. Since the square is rotated, the transformation will be on both axes.

    .tooltip {
      position: relative;
    
      &::before {
        /* ... */
        position: absolute;
        top: 75%;
        left: 50%;
        z-index: -1; /* So it's behind the tooltip's body */
    
        transform: translateX(-50%);
        transform: rotate(45deg) translateY(25%) translateX(-50%);
      }
    }
    CodePen Embed Fallback

    I also found that this method works better with Anchor Positioning since we don’t have to change the little triangle’s styles whenever we move it around. Unlike the border method, in which the visible border changes depending on the direction.

    CodePen Embed Fallback

    Trimming the square with clip-path

    Although I didn’t mention it before, you may have noticed some problems with that last approach. First off, it isn’t exactly a triangle, so it isn’t the most bulletproof take; if the tooltip is too short, the square could sneak out on the top, and moving the false triangle to the sides reveals its true square nature. We can solve both issues using the clip-path property.

    The clip-path property allows us to select a region of an element to display while clipping the rest. It works by providing the path we want to trim through, and since we want a triangle out of a square, we can use the polygon() function. It takes points in the element and trims through them in straight lines. The points can be written as percentages from the origin (i.e., top-left corner), and in this case, we want to trim through three points 0% 0% (top-left corner), 100% 0% (top-right corner) and 50% 100% (bottom-center point).

    Path to trim an isosceles triangle

    So, the clip-path value would be the polygon() function with those three points in a comma-separated list:

    .tooltip {
      &::before {
        content: "";
    
        width: var(--triangle-base);
        height: var(--triangle-height);
    
        clip-path: polygon(0% 0%, 100% 0%, 50% 100%);
        transform: translate(-50%);
    
        background-color: red;
      }
    }

    This time, we will set the top and left properties using CSS variables, which will come in handy later.

    .tooltip {
      position: relative;
    
      &::before {
        /* ... */
        position: absolute;
        top: var(--triangle-top); /* 100% */
        left: var(--triangle-left); /* 50% */
    
        transform: translate(-50%);
      }
    }

    And now we should have a true little triangle attached to the tooltip:

    CodePen Embed Fallback

    However, if we take the little triangle to the far end of any side, we can still see how it slips out of the tooltip’s body. Luckily, the clip-path property gives us better control of the triangle’s shape. In this case, we can change the points the trim goes through depending on the horizontal position of the little triangle. For the top-left corner, we want its horizontal value to approach 50% when the tooltip’s position approaches 0%, while the top-right corner should approach 50% when the tooltip position approaches 100%.

    Path to trim right triangles

    The following min() + max() combo does exactly that:

    .tooltip {
      clip-path: polygon(
        max(50% - var(--triangle-left), 0%) 0,
        min(150% - var(--triangle-left), 100%) 0%,
        50% 100%
      );
    }

    The calc() function isn’t necessary inside math functions like min() and max().

    Try to move the tooltip around and see how its shape changes depending on where it is on the horizontal axis:

    CodePen Embed Fallback

    Using the border-image property

    It may look like our last little triangle is the ultimate triangle. However, imagine a situation where you have already used both pseudo-elements and can’t spare one for the little triangle, or simply put, you want a more elegant way of doing it without any pseudo-elements. The task may seem impossible, but we can use two properties for the job: the already-seen clip-path and the border-image property.

    Using the clip-path property, we could trim the shape of a tooltip — with the little triangle included! — directly out of the element. The problem is that the element’s background isn’t big enough to account for the little triangle. However, we can use the border-image property to make an overgrown background. The syntax is a bit complex, so I recommend reading this full dive into border-image by Temani Afif. In short, it allows us to use an image or CSS gradient as the border of an element. In this case, we are making a border as wide as the triangle height and with a solid color.

    .tooltip {
      border-image: fill 0 // var(--triangle-height) conic-gradient(red 0 0);;
    }

    The trim this time will be a little more complex, since we will also trim the little triangle, so more points are needed. Exactly, the following seven points:

    The clip-path trim the shape of a tooltip body and little triangle

    This translates to the following clip-path value:

    .tooltip {
      /* ... */
      clip-path: polygon(
        0% 100%,
        0% 0%,
        100% 0%,
        100% 100%,
        calc(50% + var(--triangle-base) / 2) 100%,
        50% calc(100% + var(--triangle-height)),
        calc(50% - var(--triangle-base) / 2) 100%
      );
    }

    We can turn it smart by also capping the little triangle bottom point whenever it gets past any side of the tooltip:

    .tooltip {
      /* ... */
      clip-path: polygon(
        0% 100%,
        0% 0%,
        100% 0%,
        100% 100%,
        min(var(--triangle-left) + var(--triangle-base) / 2, 100%) 100%,
        var(--triangle-left) calc(100% + var(--triangle-height)),
        max(var(--triangle-left) - var(--triangle-base) / 2, 0%) 100%
      ;
    }

    And now we have our final little triangle of the tooltip, one that is part of the main body and only uses one element!

    CodePen Embed Fallback

    More information

    • The Complex But Awesome CSS border-image Property (Temani Afif)
    • Transforming Borders into Cool CSS Triangles (Optimistic Web)

    Related tricks!

    Snippet

    on

    Sep 29, 2016


    CSS Triangle

    tooltip


    Chris Coyier

    Article

    on

    Oct 29, 2024


    Tooltip Best Practices

    tooltip


    Zell Liew

    Article

    on

    Jun 17, 2021


    Perfect Tooltips With CSS Clipping and Masking

    tooltip


    Louis Hoebregts


    The Little Triangle in the Tooltip originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

    Source: Read More 

    Facebook Twitter Reddit Email Copy Link
    Previous ArticleDeLinuxCo Workstation – Manjaro spin
    Next Article OpenAI’s latest o1 model now available in GitHub Copilot and GitHub Models

    Related Posts

    Machine Learning

    LLMs Struggle with Real Conversations: Microsoft and Salesforce Researchers Reveal a 39% Performance Drop in Multi-Turn Underspecified Tasks

    May 17, 2025
    Machine Learning

    This AI paper from DeepSeek-AI Explores How DeepSeek-V3 Delivers High-Performance Language Modeling by Minimizing Hardware Overhead and Maximizing Computational Efficiency

    May 17, 2025
    Leave A Reply Cancel Reply

    Continue Reading

    DistroWatch Weekly, Issue 1114

    News & Updates

    Windows 11 search replacement PowerToys Run is becoming modern like Apple Spotlight

    Development

    Modena Mobilia

    Web Development

    OpenAI’s Sora generates 10 videos per second and here are the top 5 cities

    News & Updates

    Highlights

    How to Fix ERROR_DBG_PRINTEXCEPTION_C

    February 13, 2025

    The ERROR_DBG_PRINTEXCEPTION_C (0x2B6 or 694) is a debugging exception error that typically occurs when a…

    AWS DMS homogenous migration from PostgreSQL to Amazon Aurora PostgreSQL

    July 1, 2024

    How to fix Atomfall’s annoying Xbox audio bug

    March 30, 2025

    CVE-2024-30147 – “Oracle HCL Leap Client-Side Script Injection Vulnerability”

    April 24, 2025
    © DevStackTips 2025. All rights reserved.
    • Contact
    • Privacy Policy

    Type above and press Enter to search. Press Esc to cancel.