Daniel Kobe Daniel Kobe - 7 months ago 9
HTML Question

Please help me to get a working CSS zigzag border

I'm trying to make a CSS zigzag vertical border. I've been looking at this Codepen for reference. My attempt simply makes diamonds and I've been playing around with it but can't seem to get it to work. Here's my Codepen.



body {
margin: 0;
padding: 0;
}
#ribbon {
background: whitesmoke;
}
#ribbon ul {
margin: 0;
padding: 0;
height: 100px;
display: flex;
list-style-type: none;
}
#ribbon ul li {
display: flex;
flex-grow: 1;
align-items: center;
justify-content: center;
cursor: pointer;
}
#ribbon ul li:not(:last-child) {
border-right: solid;
}
#ribbon .v-zigzag {
background: linear-gradient(135deg, transparent, transparent 75%, #b6b5eb 75%, #b6b5eb), linear-gradient(225deg, transparent, transparent 75%, #b6b5eb 75%, #b6b5eb), linear-gradient(45deg, transparent, transparent 75%, #b6b5eb 75%, #b6b5eb), linear-gradient(315deg, transparent, transparent 75%, #b6b5eb 75%, #b6b5eb);
background-position: right top;
background-repeat: repeat-y;
background-size: 10px 10px;
}

<section id="ribbon">
<ul>
<li class="v-zigzag">Mode 1</li>
<li>Mode 2</li>
<li>Mode 3</li>
<li>Mode 4</li>
</ul>
</section>




Answer

The sample code uses SVG images, they're encoded into the CSS. Update: No, it doesn't, sorry. But I still think it's the best solution.

It uses two zigzag patterns: One horizontal and other vertical. Then it just covers everything but the borders with an opaque element.

When you change the background alignment, the pattern just won't work anymore and you'll get these diamonds. You could think of a different pattern... or just cover the left part.

  1. Remove the :before as it's used for the horizontal lines
  2. Move the :after to the left margin and adjust its width to show only one bar

    .bordered:after { ... left: 0; width: 26em;

Alternative solution (I came up with a better one using your current markup):

<li class="v-zigzag">Test</li></ul>

.v-zigzag {
     position: relative;
     background: linear-gradient(45deg, #ccc 5px, transparent 0) 0 5px, linear-gradient(135deg, #ccc 5px, #fff 0) 0 5px;
     background-position: right top;
     background-repeat: repeat-y;
     background-size: 10px 10px;
}
.v-zigzag:before {
    content:"";
    position: absolute;
    background: linear-gradient(45deg, #fff 5px, transparent 0) 0 5px,linear-gradient(135deg, #fff 5px, transparent 0) 0 5px;
    background-color: transparent;
    background-position: right top;
    background-repeat: repeat-y;
    background-size: 10px 10px;
    width: 10px;
    right: 3px;
    top: 0;
    bottom: 0;
 }

Explanation:

The zigzag is not a border, it's actually the background of .v-zigzag. It isn't a line either, it's flat at the left side and zigzag at the right.

Then we use other background on top, like the first one but white, and we place it 3px to the right, covering most of the first background with the white zigzag. This way, the resulting zigzag line is actually the only part "visible" (not covered with white) of the background.

Instead of nested divs, we used the :before selector. The property content (even if it's an empty string) set to the :before or :after of an element, creates a "something" that behabes just like any other element, an element that is not actyally in the DOM but behaves as such. And this pseudoelement is which has the white zigzag and is floating over the gray background.