How to Create a Zig-Zag Box Using CSS

Written by Web Developer

December 18, 2024
How to Create a Zig-Zag Box Using CSS

In this article, we will decorate elements with fancy Zig-Zag borders (or spiky borders if you want a different name). You will probably not use such shapes but it’s a good exercise to practice with some modern CSS.

Here is an overview of what we will create

CSS-only Zig-Zag boxes

You can already get the code of both shapes from my online collection but stay with me to learn the secret behind creating them.

The HTML code

Like most of the CSS Shapes I create, the HTML code is nothing but a single element. You can have an image:

<img src="" alt="" class="zig-zag-box">

Or any other element with content inside it

<div class="zig-zag-box">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi quam sem, tincidunt a enim sed, suscipit feugiat diam. Cras mollis ligula orci, a rhoncus dolor volutpat eget.</div>

That’s it! No complex code structure so let’s move to the CSS part.

Creating the first Zig-Zag box

I will start with a figure that explains how I reached the final shape, and then we will write some code.

Overview of the gradient layers

We start with a basic pattern that we correctly place and size to get the first result as illustrated in (1). It’s the first layer that we can create using one gradient. Then we place a second layer (illustrated in (2)) to fill the inner part and leave the border part visible.

We are done! Two layers each one made with one gradient and we get the first Zig-Zag box. When talking about gradients, it means background and the code will be as follows:

.zig-zag-box {
  --s: 60px;

  width: 360px; 
  aspect-ratio: 1;
  background:
    /* (2) */
    conic-gradient(#774F38 0 0) 
     50%/calc(100% - var(--s)) calc(100% - var(--s)) no-repeat,
    /* (1) */
    repeating-conic-gradient(from 45deg,#774F38 0 25%,#0000 0 50%) 
     calc(var(--s)/2) 0/var(--s) var(--s);
}

The variable --s will control the size of the pattern (layer 1) and will also be used to size layer (2) as well. As for the positions, the top layer needs to be placed at the center as illustrated in the figure (using 50%) and the pattern needs to be shifted to the left to be correctly placed (using calc(var(--s)/2) 0).

Here is a more friendly syntax to better understand each value

.zig-zag-box {
  --s: 60px;

  width: 360px; 
  aspect-ratio: 1;
  background-image:
    conic-gradient(#774F38 0 0),
    repeating-conic-gradient(from 45deg,#774F38 0 25%,#0000 0 50%);
  background-position:
    center,
    calc(var(--s)/2) 0;
  background-size:
    calc(100% - var(--s)) calc(100% - var(--s)),
    var(--s) var(--s);
  background-repeat:
    no-repeat,
    repeat;
}

It should also be noted that the width needs to be a multiplier of the variable --s so to make it easy to adjust we can express it like below:

.zig-zag-box {
  --n: 6;

  width: calc(var(--n)*var(--s));
}

The variable --n is an integer you adjust to control the size.

You can also use the round() function and the browser will make sure the width is rounded to be a multiplier of --s.

.zig-zag-box {
  --s: 60px;
  --w: 350px;

  width: round(var(--w),var(--s));
}

Another update we can make is changing background with mask. The use of mask allows us to have any background coloration and apply the shape to images for example.

.zig-zag-box {
  --s: 60px;
  --w: 350px;

  width: round(var(--w),var(--s));
  aspect-ratio: 1;
  background: linear-gradient(#8C2318,#774F38);
  mask:
    conic-gradient(#000 0 0) 
     50%/calc(100% - var(--s)) calc(100% - var(--s)) no-repeat,
    repeating-conic-gradient(from 45deg,#000 0 25%,#0000 0 50%) 
     calc(var(--s)/2) 0/var(--s) var(--s);
}

The mask property uses the same gradient configuration and now the background is controlling the coloration.

Here is a demo with the shape applied to different elements:

In case you are unfamiliar with gradients here are a few articles that might help you better understand before moving to the next shape:

Creating the second Zig-Zag box

For the second shape, I will use the same technique and same number of gradient layers. Here is a figure to illustrate the first layer.

Overview of the first layer

The starting point is a shape similar to the one used with the first Zig-Zag box that we create using conic-gradient(). From that, we update it a little to get the result you see in (1). Then we increase the element size so that (1) can repeat horizontally as many times as possible to get the result in (2). We are dealing with two repetitions but you can have as many as you want.

From (2) to (3) we offset the gradient vertically so that the top part becomes visible at the bottom and we can already see a Zig-Zag at the top and the bottom. The last step is an horizontal offset to get the final result as illustrated in (4).

Our first gradient is creating the top and bottom parts of the Zig-Zag so logically our second gradient will do the same for the left and right part. Then we combine both to get the final shape.

Combining both CSS gradient layers

Now the question is: “How does the combination create the final shape?” If we put both layers on top of each other, all we can see is a square since the second layer will hide the Zig-Zag part of the first layer and vice-versa.

To achieve this, I am relying on mask-composite. By default, if we specify nothing, we have an add composition but here I am going to use intersect. To make it easy, intersect will keep only the parts that are in common between both layers and will remove the rest.

Here is another figure to better understand:

Overview of the intersect mask composition

And the full code:

.zig-zag-box {
  --s: 38px; 
  --w: 350px; 

  width: round(var(--w),4*var(--s)); 
  aspect-ratio: 1;
  background: linear-gradient(#0B486B,#C5E0DC);
  --_m:#0000 0 calc(2*atan(.5)),#000 0 50%;
  mask:
    repeating-conic-gradient(from atan(2) at 50% var(--s),var(--_m))
     calc(2*var(--s)) calc(-1*var(--s))/calc(4*var(--s)) 100% intersect,
    repeating-conic-gradient(from atan(-.5) at var(--s),var(--_m))
     calc(-1*var(--s)) calc(2*var(--s))/100% calc(4*var(--s));
}

We have the same code structure as the first shape except this time the gradient configuration is a bit more complex with more math but you don’t have to bother yourself with that part because all you have to do is to update the variables to control the shape.

And here is a demo with the shape applied to different elements

Conclusion

Now, you know the secret behind creating those fancy Zig-Zag boxes and here is a final demo where I am creating an image gallery of Zig-Zag images!

Can you do the same with the other shape? Take it as a small homework to practice with you have learned so far.

Don’t forget to bookmark my collection of CSS Shapes and check my previous articles if you want to learn how to create more CSS shapes:

Discount

Enter Discount Code MOVEME During The SIGN UP Process To Get 90% Off Your First Month

with the discount code

MOVEME

Use Code Now
Jivo Live Chat