Skip to content

Making a hexagonal profile with SVG and CSS Mask

I used to work on a web3-related community service at my previous job. When users set their profile image as NFT, they had to display it as a hexagon, and at first I used SVG, which can handle shapes freely. However, there was an issue that SVG was displayed as a square box when the web viewer's processing increased on iPhone, so I solved it by using CSS Mask feature.

In this article, I will introduce how to make a hexagonal profile using SVG and CSS Mask. You can also use these features to make different shapes.

Making a hexagonal profile with SVG

html
<svg 
  xmlns="http://www.w3.org/2000/svg" 
  width="2.25rem"
  height="2.25rem"
  viewBox="0 0 36 36">
  <clipPath id="hexagon-clip-path">
   <use href="#hexagon-path"/>
  </clipPath>
  <path 
   id="hexagon-path"
    style="fill: #000"
    d="M15.5 0.65470053837926a4 4 0 0 1 4 0l11.58845726812 6.6905989232415a4 4 0 0 1 2 3.4641016151378l0 13.381197846483a4 4 0 0 1 -2 3.4641016151378l-11.58845726812 6.6905989232415a4 4 0 0 1 -4 0l-11.58845726812 -6.6905989232415a4 4 0 0 1 -2 -3.4641016151378l0 -13.381197846483a4 4 0 0 1 2 -3.4641016151378"
  />
  <image
   clip-path="url(#hexagon-clip-path)"
    width="100%"
    height="100%"
    href="https://user-images.githubusercontent.com/17817719/258330341-480ae4d2-8071-4bf7-b8b6-7cac9b86c1a1.jpg"
  ></image>
</svg>

1. Make a hexagonal shape with path tag

Create a basic svg tag and make a hexagonal shape path inside the svg tag.

svg
<svg 
  xmlns="http://www.w3.org/2000/svg" 
  width="2.25rem"
  height="2.25rem"
  viewBox="0 0 36 36">
  <path 
    style="fill: #000"
    d="M15.5 0.65470053837926a4 4 0 0 1 4 0l11.58845726812 6.6905989232415a4 4 0 0 1 2 3.4641016151378l0 13.381197846483a4 4 0 0 1 -2 3.4641016151378l-11.58845726812 6.6905989232415a4 4 0 0 1 -4 0l-11.58845726812 -6.6905989232415a4 4 0 0 1 -2 -3.4641016151378l0 -13.381197846483a4 4 0 0 1 2 -3.4641016151378"
  />
</svg>

2. Use image tag for profile image

svg
<svg 
  xmlns="http://www.w3.org/2000/svg" 
  width="2.25rem"
  height="2.25rem"
  viewBox="0 0 36 36">
  <path 
    style="fill: #000"
    d="M15.5 0.65470053837926a4 4 0 0 1 4 0l11.58845726812 6.6905989232415a4 4 0 0 1 2 3.4641016151378l0 13.381197846483a4 4 0 0 1 -2 3.4641016151378l-11.58845726812 6.6905989232415a4 4 0 0 1 -4 0l-11.58845726812 -6.6905989232415a4 4 0 0 1 -2 -3.4641016151378l0 -13.381197846483a4 4 0 0 1 2 -3.4641016151378"
  />
  <image
    width="100%"
    height="100%"
    href="https://user-images.githubusercontent.com/17817719/258330341-480ae4d2-8071-4bf7-b8b6-7cac9b86c1a1.jpg"
  ></image>
</svg>

3. Cut out the outside area of the path with clipPath

svg
<svg 
  xmlns="http://www.w3.org/2000/svg" 
  width="2.25rem"
  height="2.25rem"
  viewBox="0 0 36 36">
  <clipPath id="hexagon-clip-path">
    <use href="#hexagon-path"/>
  </clipPath>
  <path 
    id="hexagon-path"
    style="fill: #000"
    d="M15.5 0.65470053837926a4 4 0 0 1 4 0l11.58845726812 6.6905989232415a4 4 0 0 1 2 3.4641016151378l0 13.381197846483a4 4 0 0 1 -2 3.4641016151378l-11.58845726812 6.6905989232415a4 4 0 0 1 -4 0l-11.58845726812 -6.6905989232415a4 4 0 0 1 -2 -3.4641016151378l0 -13.381197846483a4 4 0 0 1 2 -3.4641016151378"
  />
  <image
    clip-path="url(#hexagon-clip-path)"
    width="100%"
    height="100%"
    href="https://user-images.githubusercontent.com/17817719/258330341-480ae4d2-8071-4bf7-b8b6-7cac9b86c1a1.jpg"
  ></image>
</svg>

Making a hexagonal profile with CSS Mask

See demo

CSS Mask demo

1. Load the profile image with img tag and set the size

html
<!DOCTYPE html>
<html>
<head>
  <style>
    .profile {
      width: 6rem;
      height: 6rem;
    }
  </style>
</head>
<body>
  <div class="profile">
    <img 
      width="100%" 
      height="100%" 
      alt="profile image"
      src="./profile.jpg" />
  </div>
</body>
</html>

2. Mask with hexagonal image

Use images from the same domain because images loaded with CSS are affected by CORS.

html
<!DOCTYPE html>
<html>
<head>
  <style>
    .profile {
      width: 6rem;
      height: 6rem;
      
      mask-image: url('./hexagon.png');
      mask-repeat: no-repeat;
      mask-size: contain;
      mask-position: center center;
      
      -webkit-mask-image: url('./hexagon.png');
      -webkit-mask-repeat: no-repeat;
      -webkit-mask-size: contain;
      -webkit-mask-position: center center;
    }
  </style>
</head>
<body>
  <div class="profile">
    <img 
      width="100%" 
      height="100%" 
      alt="profile image"
      src="./profile.jpg" />
  </div>
</body>
</html>