cssmaskcss-shapespseudo-element

CSS arrow on an image (without using borders)


I'm trying to figure out a way to use attach an arrow to the bottom of a masthead image, like this. I've seen a number of methods on how to create arrows with CSS3, but I've found they almost always use the border property to achieve it. Usually something like this:

#demo {
   width: 100px;
   height: 100px;
   background-color: #ccc;
   position: relative;
   border: 4px solid #333;
 }

#demo:after {
   border-width: 9px;
   border-left-color: #ccc;
   top: 15px;
 }

I'm trying to find a way to create that sort of mask shape without any images other than the main art. Has anyone achieved this? If anyone has any ideas it would be much appreciated.


Solution

  • DEMO

    2024 answer

    Nowadays, this can be just a simple clip-path on an img element.

    <img src='aurora.jpg' alt='aurora' class='arrow-tip-img'>
    

    and

    $arrow-h: Min(4em, 15%);
    $arrow-w: 3em;
    
    .arrow-tip-img {
        clip-path: 
            polygon(0 0, 100% 0, 
                100% calc(100% - #{$arrow-h}), 
                calc(50% + #{$arrow-w}) calc(100% - #{$arrow-h}), 
                50% 100%, 
                calc(50% - #{$arrow-w}) calc(100% - #{$arrow-h}), 
                0 calc(100% - #{$arrow-h}))
    }
    

    Live snippet:

    .arrow-tip-img {
      clip-path: 
        polygon(0 0, 100% 0, /* top points */
          100% calc(100% - min(4em, 15%)), /* right bottom */
          calc(50% + 3em) calc(100% - min(4em, 15%)), /* right arrow base */
          50% 100%, /* arrow tip */
          calc(50% - 3em) calc(100% - min(4em, 15%)), /* left arrow base */
          0 calc(100% - min(4em, 15%)))  /* left bottom */
    }
    <img src='https://images.unsplash.com/photo-1566345984367-fa2ba5cedc17?w=280' 
         alt='aurora' class='arrow-tip-img'>

    2013 answer, preserved for web history

    If you're looking for an arrow that resizes with the image, then yes, it can be done.

    HTML:

    <div class='head'></div>
    <div class='arrow'></div>
    

    CSS:

    .head {
      margin: 0 auto;
      width: 0; height: 0;
      /* take into account ratio of the image but with 20% less for the height */
      padding: 12.5% 30%;
      background: url(background.jpg);
      background-size: cover;
    }
    .arrow {
      overflow: hidden;
      position: relative;
      margin: -4.9% auto;
      padding: 4.42%; /* 25% of head's padding * sqrt(2) */
      width: 0;
      transform: rotate(45deg);
      background: red;
    }
    .arrow:after {
      position: absolute;
      bottom: 50%; left: 50%;
      margin: -70.71%; /* half of the width or height */
      width: 141.42%; height: 141.42%; /* sqrt(2)*141.42% */
      transform: rotate(-45deg);
      background: url(background.jpg) 50% 100%;
      background-size: 480% 250%; /* take into account ratio of the image */
      content: '';
    }