Search code examples
csshoveroverlayshapestriangle

Triangles (CSS) that Grow with the Inside Text?


So my client is interested in creating a hover effect for captions/links as shown in the below mockup:

enter image description here

The problem with CSS triangles (as I know it) is that it doesn't grow with the text. While it is a great decorative element for evergreen (non-changing) elements, I don't think it is the best for this purpose. My client would be very limited in the amount of characters that can be put within it and this character number would change. Also, the images in the gallery are set in a masonry type of layout which does further complicate things with the fixed appearance of the triangle.

This is what I have so far:

.triangle {
width: 0px;
height: 0px;
border-style: solid;
border-width: 0 0 173px 200px;
border-color: transparent transparent #362FFF transparent;
bottom: 0;
right: 0;
position: relative;
}

.triangle p {
text-align: center;
white-space: pre-wrap;
transform: none;
text-align: center;
top: 75px;
left: -100px;
position: relative;
width: 93px;
height: 93px;
margin: 0px;
font-size: 18px;
}

Does anyone know of a way to create triangles with the ability to get taller or change shape with the text?

Thanks!


Solution

  • Using a linear gradient background to simulate a triangle could be a workable solution. That way the element can scale to any size and the triangle will scale too.

    .triangle {
      display: inline-flex;
      justify-content: end;
      align-items: end;
      color: white;
      box-sizing: border-box;
      padding: 0 1em 0.5em 7em;
      aspect-ratio: 3/1;
      background: gold linear-gradient(to bottom right, #0000 50%, blue 50%);
    }
    <p>
      <span class="triangle">some text</span>
    </p>
    
    <p>
      <span class="triangle">some somewhat longer text</span>
    </p>

    Note that the box is scaling automatically to fit the text, but because of the angle we want some space between the left edge and the start of the text, so you need to add some extra left padding so that the text stays in the blue area.

    Now here is a more complete snippet to demonstrate how this works with images with text overlays of various sizes. After running it, use the full page link to see it all properly.

    :root {
      --cap-bg: rgb(0 0 255 / 0.7);
    }
    
    figure {
      margin: 0;
      display: inline-block;
      position: relative;
      overflow: hidden;
    }
    
    figure>img {
      display: block;
    }
    
    figure>figcaption {
      position: absolute;
      right: 0;
      bottom: 0;
      background: var(--cap-bg);
      color: white;
      padding: 0.5em 1em;
      border-top-left-radius: 0.5em;
      text-align: right;
    }
    
    figure.triangle>figcaption {
      background: linear-gradient(to bottom right, #0000 50%, var(--cap-bg) 50%);
      display: flex;
      justify-content: end;
      align-items: end;
      padding-left: 7em;
      aspect-ratio: 3/1;
      box-sizing: border-box;
    }
    
    figure.offset {
      overflow: visible;
    }
    
    figure.offset>figcaption {
      margin-right: -0.5em;
      margin-bottom: -0.5em;
    }
    <div>
      <figure>
        <img src="http://picsum.photos/500/100">
        <figcaption>one</figcaption>
      </figure>
    </div>
    
    <div>
      <figure>
        <img src="http://picsum.photos/500/100">
        <figcaption>one two three four</figcaption>
      </figure>
    </div>
    
    <div>
      <figure class="triangle">
        <img src="http://picsum.photos/500/100">
        <figcaption>one</figcaption>
      </figure>
    </div>
    
    <div>
      <figure class="triangle">
        <img src="http://picsum.photos/500/100">
        <figcaption>one two three four</figcaption>
      </figure>
    </div>
    
    <div>
      <figure class="triangle">
        <img src="http://picsum.photos/500/100">
        <figcaption>one two three<br>four five six seven eight</figcaption>
      </figure>
    </div>
    
    <div>
      <figure class="triangle">
        <img src="http://picsum.photos/500/100">
        <figcaption>one two three four five six seven eight</figcaption>
      </figure>
    </div>
    
    <div>
      <figure class="triangle offset">
        <img src="http://picsum.photos/500/200">
        <figcaption>Lorem ipsum<br>dolor sit amet, consectetur<br>adipiscing elit. Maecenas tempor nunc<br>mauris, sit amet placerat tortor lobortis dapibus.</figcaption>
      </figure>
    </div>