CSS Zigzag Border with a Textured Background
Asked Answered
T

4

15

I've been working on a header with a zigzag border. One way to do this is to use images to make the zigzag effect.

(1) Is there any way to create a practical cross-browser zigzag border in CSS without the use of images?

I am also trying to put a textured background on this header that extends to the zigzags. However, the vertical size of the header may change and I am unable to implement the header as a single image.

If I try to add a texture to both the zigzag edges and the header element, chances are, the texture will be off sync.

(2) Any ideas on implementing a textured background that extends onto the zigzags without being off sync?

My [old] code (along with a texture) is here on jsFiddle.

body {
  padding: 20px;
}

header {
  width: 240px;
  background-color: #BCED91;
}

header:after {
  content: " ";
  display: block;
  position: relative;
  width: 240px;
  bottom: -15px;
  height: 15px;
  background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAPCAYAAACWV43jAAAAw0lEQVRIx83RsQ3CMBCF4T83AZKLVOmyBa1HSIlXwKySGaDOBClZAToWQIpETQONyxAS+2J4pe9knd5X9EP7QicPYAsUwBnYaHwqSsd1QGmNv1rjL0AZ3pJTKDTorPGnsUE/tDvg+KsG70D96TiAMKvDbtYDO6Cyxt++LYadKpY8hthNtTaVGHLRJJ3R5mJy0SbVJp9D7FJaSyWXNUk1yGVt0lTyMWK3ZmtLySUnaQy55CZdSi7AHmis8U/+JOGWBji8AaYPVy6VELZvAAAAAElFTkSuQmCC) repeat-x;
}

img {
  margin-top: 50px;
}
<header>
  <br />
  <br />
  <br />
  <br />
</header>

<img src="http://i.imgur.com/qKsVr.png" />

Edit #1:

Thank you Ana for the code. I took it and improved upon it.

http://dabblet.com/gist/3401493

I don't think that a consistent background will be possible.

Twitch answered 20/8, 2012 at 1:23 Comment(1)
Your dabbet link is dead, can you please copy code here?Cinelli
O
21

If you are going to use border-image, then it's not a cross-browser solution because IE doesn't support it.

Also, even though every current browser version except IE9 supports both CSS gradients (which would allow you to get a zig-zag pattern) and border-image, last time I checked (which was quite a few months ago, so better test this again), using gradients for border-image only worked in WebKit. Plus, I don't think that even in WebKit this works with more than one gradient (as you can only set one border image and one gradient is one image) and you need two gradients for the zig-zag pattern.

The code for the CSS zig-zag pattern is:

background: linear-gradient(#BCED91 49%, transparent 49%),
        linear-gradient(-45deg, white 33%, transparent 33%) 0 50%,
        white linear-gradient(45deg, white 33%, #BCED91 33%) 0 50%;
    background-repeat: repeat-x;
    background-size: 1px 100%, 40px 40px, 40px 40px;

If you want a texture below this that is in sync with this one, then you have to make sure it repeats at the same intervals (40px, but you could also go for 20px).


Edit: regarding polyfills, you could try one of the ones listed here: CSS3 PIE or cssSandpaper

Onwards answered 20/8, 2012 at 2:21 Comment(4)
Nice ingenious way of using css3 to create this zigzag! However, it seems like an image can't be used for the background (first linear-gradient). I guess it is just not feasible of making a continuous texture unless the item's height is constant and predictable. Also, is there a JS polyfill to make this work in IE8 and IE9?Twitch
You could remove the first linear gradient and play with having images or other gradients behind the zig-zag - like this dabblet.com/gist/3401443 . There are al lot of things that could be done with it. Regarding polyfills, you could check the ones listed here css3clickchart.com/#linear-gradient (bottom left of page)Onwards
I'll try CSS Pie and cssSandpaper tomorrow. But as for the background, I wanted to put it on the green part itself, but it seems that with the linear gradients, it's a lost cause. Nevertheless, this is a great way of doing it. Thanks!Twitch
@Onwards how do you do a top and bottom zigzag?Obumbrate
P
8

(In modern browsers) you can use SVGs to create simple drawings, and use them as CSS background images embedded as data URI.

Here is what the SVGs look like:

body {
  background: #888;
}
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="8px" height="4px">
  <polygon points="0,4 4,0 8,4" fill="#CC0000" />
</svg>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="8px" height="4px">
  <polygon points="0,0 4,4 8,0" fill="#CC0000" />
</svg>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="8px" height="4px">
  <polygon points="0,0 4,4 8,0" fill="#FFFFFF" />
</svg>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="8px" height="4px">
  <polygon points="0,4 4,0 8,4" fill="#FFFFFF" />
</svg>

Example 1:

.zigzag-outside {
  position: relative;
  margin-top: 4px;
  margin-bottom: 4px;
  background-color: #CC0000;
  /* example content */
  padding: 1em;
  font: bold medium sans-serif;
  color: #FFFFFF;
}
.zigzag-outside:before {
  content: "";
  position: absolute;
  top: -4px;
  left: 0;
  right: 0;
  height: 4px;
  /* red up pointing triangle */
  background-image: url("data:image/svg+xml,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228px%22%20height%3D%224px%22%3E%3Cpolygon%20points%3D%220%2C4%204%2C0%208%2C4%22%20fill%3D%22%23CC0000%22%2F%3E%3C%2Fsvg%3E");
}
.zigzag-outside:after {
  content: "";
  position: absolute;
  bottom: -4px;
  left: 0;
  right: 0;
  height: 4px;
  /* red down pointing triangle */
  background-image: url("data:image/svg+xml,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228px%22%20height%3D%224px%22%3E%3Cpolygon%20points%3D%220%2C0%204%2C4%208%2C0%22%20fill%3D%22%23CC0000%22%2F%3E%3C%2Fsvg%3E");
}
<div class="zigzag-outside">Example 1</div>

Example 2:

.zigzag-inside {
  position: relative;
  /* example content */
  width: 600px;
  height: 100px;
  background-image: url(https://i.sstatic.net/uOVfl.jpg);
}
.zigzag-inside:before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 4px;
  /* white down pointing triangle */
  background-image: url("data:image/svg+xml,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228px%22%20height%3D%224px%22%3E%3Cpolygon%20points%3D%220%2C0%204%2C4%208%2C0%22%20fill%3D%22%23FFFFFF%22%2F%3E%3C%2Fsvg%3E");
}
.zigzag-inside:after {
  content: "";
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  height: 4px;
  /* white up pointing triangle */
  background-image: url("data:image/svg+xml,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228px%22%20height%3D%224px%22%3E%3Cpolygon%20points%3D%220%2C4%204%2C0%208%2C4%22%20fill%3D%22%23FFFFFF%22%2F%3E%3C%2Fsvg%3E");
}
<div class="zigzag-inside"></div>
Proud answered 8/12, 2014 at 10:38 Comment(0)
C
5

Improved minimal CSS:

div {
  background: #1ba1e2;
  position: relative;
}

div:after {
  content: "";
  display: block;
  position: absolute;
  width: 100%;
  height: 30px;
  background: linear-gradient(-45deg, transparent 75%, #1ba1e2 0) 0 50%,
              linear-gradient(45deg, transparent 75%, #1ba1e2 0) 0 50%;
  background-size: 30px 30px;
}

/* Styles just for demo */
h1 {
  color: #fff;
  text-align: center;
  margin: 0;
  padding: 0.5em;
}
<div>
  <h1>Zig Zag Borders</h1>
</div>

If you want to remove duplicate values you can use CSS variables AKA Custom properties. They are working everywhere except IE.

:root {
  --background-color: #1ba1e2;
  --zigzag-item-size: 30px;
}

div {
  background: var(--background-color);
  position: relative;
}

div:after {
  content: "";
  display: block;
  position: absolute;
  width: 100%;
  height: var(--zigzag-item-size);
  background: linear-gradient(-45deg, transparent 75%, var(--background-color) 0) 0 50%,
              linear-gradient(45deg, transparent 75%, var(--background-color) 0) 0 50%;
  background-size: var(--zigzag-item-size) var(--zigzag-item-size);
}

/* Styles just for demo */
h1 {
  color: #fff;
  text-align: center;
  margin: 0;
  padding: 0.5em;
}
<div>
  <h1>Zig Zag Borders</h1>
</div>

Small note:

I use zero 0 in gradient color-stops to avoid duplicating previous values because according to the CSS3 images specs color-stop position can't be less than previous one.

If a color-stop has a position that is less than the specified position of any color-stop before it in the list, set its position to be equal to the largest specified position of any color-stop before it.

Cinelli answered 21/6, 2017 at 11:15 Comment(2)
This code works great, but I wish there was a way to add a shadow below the zigzag border.Torn
@Torn Can you please ask separate question and send the link here?Cinelli
S
0

Now using mask and one gradient you can do it. Check this online generator to get the code: https://css-generators.com/custom-borders/. You can find all the directions and combination of Zig-Zag

body {
  padding: 20px;
}

header {
  min-height: 200px;
  background-color: #BCED91;
}

img {
  margin-top: 50px;
}

.zig-zag {
  --mask: conic-gradient(from -45deg at bottom,#0000,#000 1deg 90deg,#0000 91deg) 50% / 60px 100%;
  -webkit-mask: var(--mask);
          mask: var(--mask);
}
<header class="zig-zag">

</header>

<img src="http://i.imgur.com/qKsVr.png" class="zig-zag">
Sequoia answered 13/8, 2022 at 19:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.