Search code examples
htmlcsssvg

Is there a way to add a white border inside this div?


Is there a way to add a white border inside this div like in the picture below?

enter image description here

The code below was from https://stackoverflow.com/a/65504158.

I just refactored it a bit.

.hexagon {
  width: 200px;
  display: inline-block;
  margin: 0 5px;
  color: orange;
  filter: url("#goo");
}

.mask {
  display: block;
  background: currentColor;
  padding-top: 115%; /* 100%/cos(30)  */
  clip-path: polygon(0% 25%, 0% 75%, 50% 100%, 100% 75%, 100% 25%, 50% 0%);
}

img {
    position: absolute;
    top:0; 
    bottom: 0;
    left: 0; 
    right:0;
    width: 100%;
    height: 100%;
}
<div class="hexagon">
  <div class="mask">
    <img src="https://images.unsplash.com/photo-1724884564497-f5024b7e2f93?q=80&w=257" />
  </div>
</div>

<svg style="visibility: hidden; position: absolute;" width="0" height="0" xmlns="http://www.w3.org/2000/svg" version="1.1">
  <defs>
    <filter id="goo">
      <feGaussianBlur in="SourceGraphic" stdDeviation="8" result="blur" />
      <feColorMatrix in="blur" mode="matrix" values="1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 19 -9" result="goo" />
      <feComposite in="SourceGraphic" in2="goo" operator="atop" />
    </filter>
  </defs>
</svg>

I tried to add the border property to the hexagon but it wouldn't show.


Solution

  • SVG to the rescue

    As commented by Paulie_D – CSS polygons can at best approximate rounded corners (e.g by adding many vertices to emulate a smooth curve). A workaround could be adding a SVG element of a rounded hexagon as an overlay

    :root {
      --hexfront: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 86.6 100'><path fill='none' stroke='white' stroke-width='3' transform='scale(0.75)' transform-origin='50%' d='M38.97 2.5q4.33-2.5 8.66 0l34.64 20q4.33 2.5 4.33 7.5l0 40q0 5-4.33 7.5l-34.64 20q-4.33 2.5-8.66 0l-34.64-20q-4.33-2.5-4.33-7.5l0-40q0-5 4.33-7.5l34.64-20z'/></svg>");
    }
    
    .hexagon {
      width: 200px;
      display: inline-block;
      margin: 0 5px;
      line-height: 0;
      filter: url("#goo");
    }
    
    img {
      aspect-ratio: 1/1.15;
      width: 100%;
      height: 100%;
    }
    
    .mask {
      position: relative;
      display: block;
      clip-path: polygon(0% 25%, 0% 75%, 50% 100%, 100% 75%, 100% 25%, 50% 0%);
    }
    
    .mask:after {
      content: "";
      display: block;
      position: absolute;
      inset: 0%;
      height: 100%;
      width: 100%;
      background-image: var(--hexfront);
    }
    <div class="hexagon">
      <div class="mask">
        <img src="https://images.unsplash.com/photo-1724884564497-f5024b7e2f93?q=80&w=257" />
      </div>
    </div>
    
    <h3>SVG Overlay</h3>
    <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 86.6 100'><path fill='none' stroke='black' stroke-width='3' transform='scale(0.75)' transform-origin='50%' d='M38.97 2.5q4.33-2.5 8.66 0l34.64 20q4.33 2.5 4.33 7.5l0 40q0 5-4.33 7.5l-34.64 20q-4.33 2.5-8.66 0l-34.64-20q-4.33-2.5-4.33-7.5l0-40q0-5 4.33-7.5l34.64-20z'/></svg>
    
    <svg style="height:0;width:0; position: absolute;" width="0" height="0" xmlns="http://www.w3.org/2000/svg" version="1.1">
      <defs>
        <filter id="goo">
          <feGaussianBlur in="SourceGraphic" stdDeviation="8" result="blur" />
          <feColorMatrix in="blur" mode="matrix" values="1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 19 -9" result="goo" />
          <feComposite in="SourceGraphic" in2="goo" operator="atop" />
        </filter>
    </defs>
    </svg>

    I've created the hex path with this customized version of Varun Vachhar's "SVG Polygon Generator" (no support for rounded corners).

    Replace CSS-clip path with a mask

    When we already have a "proper" <path> element we can as well replace the filtered hexagon with a <mask> to avoid some cross-browser (... safari) issues related to the goo filter.

    :root{
      --mask : url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 86.6 100'><defs><path id='hex' d='M38.97 2.5q4.33-2.5 8.66 0l34.64 20q4.33 2.5 4.33 7.5l0 40q0 5-4.33 7.5l-34.64 20q-4.33 2.5-8.66 0l-34.64-20q-4.33-2.5-4.33-7.5l0-40q0-5 4.33-7.5l34.64-20z'/></defs><rect width='100%' height='100%'/><use href='%23hex' fill='white' stroke='black'/></svg>");
    
      --hexfront : url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 86.6 100'><path fill='none' stroke='white' stroke-width='3' transform='scale(0.75)' transform-origin='50%' d='M38.97 2.5q4.33-2.5 8.66 0l34.64 20q4.33 2.5 4.33 7.5l0 40q0 5-4.33 7.5l-34.64 20q-4.33 2.5-8.66 0l-34.64-20q-4.33-2.5-4.33-7.5l0-40q0-5 4.33-7.5l34.64-20z'/></svg>");
      
    }
    
    
    .hexagon {
      width: 200px;
      display: inline-block;
      margin: 0 5px;
      position:relative;
      line-height:0;
    }
    
    img {
      aspect-ratio:1/1.15;
      width: 100%;
      height:100%;
    }
    
    
    
    .mask{
      mask-image: var(--mask);
      mask-mode: luminance;
      mask-size: contain;
      mask-repeat: no-repeat;
    }
    
    
    .mask:after {
      content: "";
      display: block;
      position: absolute;
      inset:0%;
      height: 100%;
      width: 100%;
      background-image: var(--hexfront);
    }
    <div class="hexagon">
      <div class="mask">
        <img src="https://images.unsplash.com/photo-1724884564497-f5024b7e2f93?q=80&w=257" />
      </div>
    </div>