26 CSS Dividers06 / 26

Pure CSSMIT licensed

Zigzag Torn Paper Cut Divider CSS

Sawtooth and torn-paper edges without a single image, using a conic-gradient mask instead of the old stacked-triangle background hack. One --tooth token sets the pitch; the same recipe cuts a full-width section seam, both edges of a receipt, and a perforated ticket stub. Because it is a mask, the teeth cut through photographs and gradients alike — backgrounds show through the notches instead of faking them with a matching colour.

Published

Live Demo
Try it

The code

<section class="div-06" aria-label="Zigzag torn paper divider demo">
  <div class="div-06__top">
    <p class="div-06__eyebrow">conic-gradient() mask</p>
    <h2 class="div-06__title">Tear the section, don't fake it</h2>
    <p class="div-06__sub">The teeth are cut out of this panel, so the photograph below shows through them.</p>
  </div>
  <div class="div-06__bottom">
    <div class="div-06__receipt">
      <p class="div-06__rhead">CODEFRONTS · RECEIPT</p>
      <dl class="div-06__line"><dt>Divider pitch</dt><dd>22px</dd></dl>
      <dl class="div-06__line"><dt>Tooth depth</dt><dd>11px</dd></dl>
      <dl class="div-06__line"><dt>Images used</dt><dd>0</dd></dl>
      <dl class="div-06__line div-06__line--tot"><dt>Total</dt><dd>1 mask</dd></dl>
    </div>
    <p class="div-06__chip">mask-composite:add · two conic layers · --tooth pitch</p>
  </div>
</section>
.div-06 {
  width: 100%;
  min-height: 100vh;
  min-height: 100svh;
  display: block;
  background: var(--div-06-bg);
  --div-06-bg: oklch(0.22 0.02 285);
  --div-06-paper: oklch(0.97 0.014 85);
  --div-06-ink: oklch(0.25 0.02 60);
  --div-06-mut: oklch(0.55 0.02 60);
  --div-06-acc: oklch(0.66 0.19 25);
  --div-06-tooth: 22px;
  font-family: 'Segoe UI',system-ui,-apple-system,sans-serif;
  position: relative;
  isolation: isolate;
}

.div-06 *,
.div-06 *::before,
.div-06 *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.div-06::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(180deg,oklch(0.24 0.03 290/.2),oklch(0.18 0.02 285/.9)),url("https://images.unsplash.com/photo-1618005182384-a83a8bd57fbe?q=80&w=1600&auto=format&fit=crop") center/cover no-repeat;
}

.div-06__top {
  --m: conic-gradient(from -45deg at bottom,#0000,#000 1deg 89deg,#0000 90deg) 50%/var(--div-06-tooth) 100%;
  -webkit-mask: var(--m);
  mask: var(--m);
  background: linear-gradient(140deg,var(--div-06-paper),oklch(0.93 0.02 80));
  color: var(--div-06-ink);
  min-height: 52svh;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 13px;
  text-align: center;
  padding: clamp(34px,7vw,78px) clamp(20px,5vw,56px) calc(var(--div-06-tooth)/2 + clamp(30px,5vw,60px));
}

.div-06__eyebrow {
  font-family: ui-monospace,Menlo,Consolas,monospace;
  font-size: 11.5px;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--div-06-acc);
}

.div-06__title {
  font-size: clamp(28px,5vw,52px);
  line-height: 1.05;
  letter-spacing: -.03em;
  font-weight: 700;
  max-width: 18ch;
  text-wrap: balance;
}

.div-06__sub {
  max-width: 46ch;
  font-size: clamp(14px,1.7vw,17px);
  line-height: 1.6;
  color: var(--div-06-mut);
  text-wrap: pretty;
}

.div-06__bottom {
  min-height: 48svh;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 22px;
  padding: clamp(34px,6vw,64px) clamp(20px,5vw,56px);
}

.div-06__receipt {
  --m1: conic-gradient(from -45deg at bottom,#0000,#000 1deg 89deg,#0000 90deg) 50% 100%/var(--div-06-tooth) 50% repeat-x;
  --m2: conic-gradient(from 135deg at top,#0000,#000 1deg 89deg,#0000 90deg) 50% 0/var(--div-06-tooth) 50% repeat-x;
  -webkit-mask: var(--m1),var(--m2);
  mask: var(--m1),var(--m2);
  width: min(88vw,340px);
  background: var(--div-06-paper);
  color: var(--div-06-ink);
  padding: calc(var(--div-06-tooth)/2 + 20px) 26px;
  filter: drop-shadow(0 16px 28px oklch(0 0 0/.42));
  font-family: ui-monospace,Menlo,Consolas,monospace;
}

.div-06__rhead {
  font-size: 11.5px;
  letter-spacing: .2em;
  text-align: center;
  padding-bottom: 12px;
  border-bottom: 1.5px dashed oklch(0.25 0.02 60/.3);
  margin-bottom: 12px;
}

.div-06__line {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  font-size: 12.5px;
  padding: 5px 0;
  color: var(--div-06-mut);
}

.div-06__line dd {
  color: var(--div-06-ink);
  font-weight: 600;
}

.div-06__line--tot {
  border-top: 1.5px dashed oklch(0.25 0.02 60/.3);
  margin-top: 8px;
  padding-top: 11px;
  font-size: 14px;
}

.div-06__line--tot dt,
.div-06__line--tot dd {
  color: var(--div-06-acc);
  font-weight: 700;
}

.div-06__chip {
  font-family: ui-monospace,Menlo,Consolas,monospace;
  font-size: 11.5px;
  color: oklch(0.9 0.01 285/.75);
  padding: 8px 14px;
  border: 1px solid oklch(1 0 0/.18);
  border-radius: 99px;
  text-align: center;
}
Paste this into ChatGPT, Claude, Cursor, or any coding assistant. The block below is pre-framed with everything the AI needs to integrate this demo into your project — markup, styles, scoping notes, and the source URL. Hit Copy and paste straight into your chat.
Here's a working CSS Divider from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Zigzag Torn Paper Cut Divider CSS
Source: https://codefronts.com/snippets/css-dividers/zigzag-torn-paper-cut-divider-css/

Sawtooth and torn-paper edges without a single image, using a conic-gradient mask instead of the old stacked-triangle background hack. One --tooth token sets the pitch; the same recipe cuts a full-width section seam, both edges of a receipt, and a perforated ticket stub. Because it is a mask, the teeth cut through photographs and gradients alike — backgrounds show through the notches instead of faking them with a matching colour.
## HTML
```html
<section class="div-06" aria-label="Zigzag torn paper divider demo">
  <div class="div-06__top">
    <p class="div-06__eyebrow">conic-gradient() mask</p>
    <h2 class="div-06__title">Tear the section, don't fake it</h2>
    <p class="div-06__sub">The teeth are cut out of this panel, so the photograph below shows through them.</p>
  </div>
  <div class="div-06__bottom">
    <div class="div-06__receipt">
      <p class="div-06__rhead">CODEFRONTS · RECEIPT</p>
      <dl class="div-06__line"><dt>Divider pitch</dt><dd>22px</dd></dl>
      <dl class="div-06__line"><dt>Tooth depth</dt><dd>11px</dd></dl>
      <dl class="div-06__line"><dt>Images used</dt><dd>0</dd></dl>
      <dl class="div-06__line div-06__line--tot"><dt>Total</dt><dd>1 mask</dd></dl>
    </div>
    <p class="div-06__chip">mask-composite:add · two conic layers · --tooth pitch</p>
  </div>
</section>
```
## CSS
```css
.div-06 {
  width: 100%;
  min-height: 100vh;
  min-height: 100svh;
  display: block;
  background: var(--div-06-bg);
  --div-06-bg: oklch(0.22 0.02 285);
  --div-06-paper: oklch(0.97 0.014 85);
  --div-06-ink: oklch(0.25 0.02 60);
  --div-06-mut: oklch(0.55 0.02 60);
  --div-06-acc: oklch(0.66 0.19 25);
  --div-06-tooth: 22px;
  font-family: 'Segoe UI',system-ui,-apple-system,sans-serif;
  position: relative;
  isolation: isolate;
}

.div-06 *,
.div-06 *::before,
.div-06 *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.div-06::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(180deg,oklch(0.24 0.03 290/.2),oklch(0.18 0.02 285/.9)),url("https://images.unsplash.com/photo-1618005182384-a83a8bd57fbe?q=80&w=1600&auto=format&fit=crop") center/cover no-repeat;
}

.div-06__top {
  --m: conic-gradient(from -45deg at bottom,#0000,#000 1deg 89deg,#0000 90deg) 50%/var(--div-06-tooth) 100%;
  -webkit-mask: var(--m);
  mask: var(--m);
  background: linear-gradient(140deg,var(--div-06-paper),oklch(0.93 0.02 80));
  color: var(--div-06-ink);
  min-height: 52svh;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 13px;
  text-align: center;
  padding: clamp(34px,7vw,78px) clamp(20px,5vw,56px) calc(var(--div-06-tooth)/2 + clamp(30px,5vw,60px));
}

.div-06__eyebrow {
  font-family: ui-monospace,Menlo,Consolas,monospace;
  font-size: 11.5px;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--div-06-acc);
}

.div-06__title {
  font-size: clamp(28px,5vw,52px);
  line-height: 1.05;
  letter-spacing: -.03em;
  font-weight: 700;
  max-width: 18ch;
  text-wrap: balance;
}

.div-06__sub {
  max-width: 46ch;
  font-size: clamp(14px,1.7vw,17px);
  line-height: 1.6;
  color: var(--div-06-mut);
  text-wrap: pretty;
}

.div-06__bottom {
  min-height: 48svh;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 22px;
  padding: clamp(34px,6vw,64px) clamp(20px,5vw,56px);
}

.div-06__receipt {
  --m1: conic-gradient(from -45deg at bottom,#0000,#000 1deg 89deg,#0000 90deg) 50% 100%/var(--div-06-tooth) 50% repeat-x;
  --m2: conic-gradient(from 135deg at top,#0000,#000 1deg 89deg,#0000 90deg) 50% 0/var(--div-06-tooth) 50% repeat-x;
  -webkit-mask: var(--m1),var(--m2);
  mask: var(--m1),var(--m2);
  width: min(88vw,340px);
  background: var(--div-06-paper);
  color: var(--div-06-ink);
  padding: calc(var(--div-06-tooth)/2 + 20px) 26px;
  filter: drop-shadow(0 16px 28px oklch(0 0 0/.42));
  font-family: ui-monospace,Menlo,Consolas,monospace;
}

.div-06__rhead {
  font-size: 11.5px;
  letter-spacing: .2em;
  text-align: center;
  padding-bottom: 12px;
  border-bottom: 1.5px dashed oklch(0.25 0.02 60/.3);
  margin-bottom: 12px;
}

.div-06__line {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  font-size: 12.5px;
  padding: 5px 0;
  color: var(--div-06-mut);
}

.div-06__line dd {
  color: var(--div-06-ink);
  font-weight: 600;
}

.div-06__line--tot {
  border-top: 1.5px dashed oklch(0.25 0.02 60/.3);
  margin-top: 8px;
  padding-top: 11px;
  font-size: 14px;
}

.div-06__line--tot dt,
.div-06__line--tot dd {
  color: var(--div-06-acc);
  font-weight: 700;
}

.div-06__chip {
  font-family: ui-monospace,Menlo,Consolas,monospace;
  font-size: 11.5px;
  color: oklch(0.9 0.01 285/.75);
  padding: 8px 14px;
  border: 1px solid oklch(1 0 0/.18);
  border-radius: 99px;
  text-align: center;
}
```

How this works

The modern one-liner. A conic gradient centred on the bottom edge of each tile carves a 90° wedge, and tiling it horizontally produces perfect teeth:

.torn{ --tooth:22px;
  --m:conic-gradient(from -45deg at bottom, #0000, #000 1deg 89deg, #0000 90deg)
      50%/var(--tooth) 100%;
  -webkit-mask:var(--m); mask:var(--m);
  padding-bottom:calc(var(--tooth)/2 + 2rem); }

Read the gradient geometrically: the cone opens upward from the bottom-centre of every tile at ±45°, so each tile keeps a triangle and loses its two bottom corners. Neighbouring tiles' lost corners meet to form a V. Pitch is the tile width; depth is always half the pitch, which is what keeps the teeth at a constant 45° whatever the size.

Two masks compose for a receipt. Give one layer 50% 100%/var(--tooth) 50% and a mirrored from 135deg at top layer 50% 0/var(--tooth) 50%; the default mask-composite:add unions them, so the card is toothed top and bottom and solid through the middle.

Why mask rather than the classic pair of stacked linear-gradient triangles painted in the next section's colour? Because a mask actually removes pixels. The old trick only works when the divider's fill exactly matches the background beneath it — put a photo behind it and the illusion collapses.

Make it yours

  • Pitch and depth: --tooth:12px gives a fine perforation (great for coupons), 44px gives a bold paper-tear. Depth follows automatically.
  • Softer tear: change the wedge to #000 12deg 78deg for blunted teeth, or add filter:url(#roughen) with an feTurbulence displacement for a genuinely ragged rip.
  • Ticket notch: swap the conic gradient for radial-gradient(circle at 50% 0, #0000 8px, #000 8.5px) tiled at 20px for the semicircular perforation used on boarding passes.
  • Vertical teeth: rotate the tile — from 45deg at left with a size of 100% var(--tooth) — for a torn right-hand column edge.

Gotchas — read before shipping

  • Always ship the -webkit-mask duplicate. Safari below 15.4 and every WebKit-based in-app browser need it, and an unprefixed-only mask silently does nothing there.
  • Mask hides overflow but does NOT clip box-shadow drawn outside the element — a drop shadow will be visible in the notches. Use filter:drop-shadow() instead, which follows the masked silhouette.
  • Add padding equal to at least half the pitch on the toothed side or the teeth bite into your last line of text.
  • Antialiasing on angled mask edges can leave a faint fringe at fractional zoom. Nudging the wedge to 1deg 89deg instead of 0deg 90deg removes the seam artefact.

Browser support

ChromeSafariFirefoxEdge
120+15.4+113+120+

Unprefixed mask shorthand: Chrome 120, Safari 15.4, Firefox 53. With the -webkit- duplicate included, coverage goes back to Chrome 4 / Safari 4 era for the basic effect.

Techniques used in this demo

Search CodeFronts

Loading…