Need a hexagon? You can make one with CSS. Not surprising, considering the far crazier things CSS can pull off. This article will show you how to make a CSS hexagon and how Sass can help with all the math involved.

Sassy CSS Hexagons

The Approach

There are several ways to do this, but the “1 rectangle + 2 rhombuses” approach worked best for me. This is best explained visually, so here’s an animation for it.

See the Pen CSS Hexagon Visualized by Will Boyd (@lonekorean) on CodePen.

We’ll need 3 HTML elements, one for each shape. To keep the markup light, we can use a single <div> with its ::before and ::after pseudo-elements. Block elements are rectangular by default, so the rectangle part is easy. The rhombuses are achieved by applying a transform style to the rectangular pseudo-elements, flattening with scaleY() and rotating with rotate().

Time for Math

With the general shapes accounted for, it’s time to take on some math. There’s a bit of trigonometry involved to figure out the measurements. Various widths, heights, and offsets need to be precisely calculated so elements line up to form a perfect hexagon.

I’m not going to step through the math here, because honestly, that’d be boring. I will mention how Sass helped me tremendously, though. With Sass, you can use variables and set their values via formulas, like this.

$side-length: ($width / 2) / cos(30deg);

In this example, I’m defining the length of a side of the hexagon in terms of the width of the hexagon. This means I don’t have to crunch the numbers manually. Even better, if I decide to change $width, $side-length will be automatically updated.

So I can create a bunch of little formulas in Sass to calculate all the numbers I need, all based off whatever width I want for the hexagon. Side note: I’m using Compass to gain access to helper functions like cos() and sqrt().

// tweak this
$width: 200px;

// automatically computed
$side-length: ($width / 2) / cos(30deg);
$cap-y-scale: tan(30deg);
$cap-height: ($width / 2) * $cap-y-scale;
$cap-unscaled-side-length: $width / sqrt(2);

This also helps make the Sass more self-documenting, since I have descriptive variable names instead of crazy pixel values all over the place.

div {
  position: relative;
  width: $width;
  height: $side-length;
  margin-top: $cap-height;
  background-color: #666;

  &::before, &::after {
    content: '';
    display: block;
    position: absolute;
    width: $cap-unscaled-side-length;
    height: $cap-unscaled-side-length;
    background-color: inherit;
    transform-origin: 0 0;
    transform: scaleY($cap-y-scale) rotate(-45deg);
  }

  &::before {
    top: 0;
  }

  &::after {
    top: $side-length;
  }
}

And there you have it, a perfect hexagon in CSS.

Keep Playing

The CSS hexagon I’ve shown you is very tweakable. It’s all just CSS, so go nuts. Tiling CSS hexagons together can also produce some neat effects.

See the Pen CSS Hexagons by Will Boyd (@lonekorean) on CodePen.

Thanks for reading!