Back to BlogDesign Fundamentals

SVG Masks and Shape Dividers: Create Stunning Section Transitions in CSS

SVG Genie Team11 min read

Flat, horizontal lines between sections are boring. They're the web design equivalent of a plain white wall.

SVG masks and shape dividers transform those transitions into visual opportunities—waves that flow, curves that guide the eye, angles that create energy. And they do it without images, with perfect scalability, and minimal performance impact.

In this guide, you'll learn how to create and implement SVG shape dividers that make your layouts feel dynamic and polished.

What Are SVG Shape Dividers?

Shape dividers are SVG elements positioned between content sections to create non-rectangular transitions. Instead of Section A ending and Section B starting with a hard horizontal line, you get organic shapes that blend the two together.

Common shapes include:

  • Waves (single or layered)
  • Curves and arcs
  • Diagonal angles
  • Mountains and peaks
  • Custom organic blobs

Why SVGs are perfect for this:

  • Scale infinitely without quality loss
  • Tiny file sizes (often under 1KB)
  • Full CSS control for colors and animations
  • No HTTP requests when inlined
  • Responsive by default

Basic Implementation

Let's start with a simple wave divider.

The SVG

<svg viewBox="0 0 1200 120" preserveAspectRatio="none" class="divider">
  <path d="M0,0 C300,100 900,20 1200,100 L1200,120 L0,120 Z" fill="currentColor"/>
</svg>

Let's break down what's happening:

  • viewBox="0 0 1200 120" - Defines a 1200×120 coordinate system
  • preserveAspectRatio="none" - Allows the SVG to stretch to fill its container width
  • The <path> draws a curve from left to right, then fills down to create a solid shape

The CSS

.section-light {
  background: #f4f4f5;
  padding: 4rem 2rem;
}

.section-dark {
  background: #18181b;
  color: white;
  padding: 4rem 2rem;
}

.divider {
  display: block;
  width: 100%;
  height: 80px;
  color: #18181b; /* The color the divider transitions TO */
}

The HTML Structure

<section class="section-light">
  <h2>Light Section Content</h2>
  <p>Your content here...</p>
</section>

<svg viewBox="0 0 1200 120" preserveAspectRatio="none" class="divider">
  <path d="M0,0 C300,100 900,20 1200,100 L1200,120 L0,120 Z" fill="currentColor"/>
</svg>

<section class="section-dark">
  <h2>Dark Section Content</h2>
  <p>Your content here...</p>
</section>

The divider sits between sections, visually bridging the color change.

Essential Shape Divider Patterns

Here are the most useful divider shapes you'll need.

Simple Wave

A gentle, single-curve wave:

<svg viewBox="0 0 1200 120" preserveAspectRatio="none" class="divider wave">
  <path d="M0,60 Q300,120 600,60 T1200,60 L1200,120 L0,120 Z" fill="currentColor"/>
</svg>
.wave {
  height: 60px;
}

Multi-Layer Waves

Overlapping waves create depth:

<div class="wave-container">
  <svg viewBox="0 0 1200 120" preserveAspectRatio="none" class="wave wave-back">
    <path d="M0,40 Q300,100 600,40 T1200,40 L1200,120 L0,120 Z"/>
  </svg>
  <svg viewBox="0 0 1200 120" preserveAspectRatio="none" class="wave wave-mid">
    <path d="M0,60 Q300,120 600,60 T1200,60 L1200,120 L0,120 Z"/>
  </svg>
  <svg viewBox="0 0 1200 120" preserveAspectRatio="none" class="wave wave-front">
    <path d="M0,80 Q300,100 600,80 T1200,80 L1200,120 L0,120 Z"/>
  </svg>
</div>
.wave-container {
  position: relative;
  height: 120px;
}

.wave {
  position: absolute;
  bottom: 0;
  width: 100%;
  height: 100%;
}

.wave-back { fill: rgba(99, 102, 241, 0.3); }
.wave-mid { fill: rgba(99, 102, 241, 0.5); }
.wave-front { fill: #6366f1; }

Diagonal Angle

Clean, modern diagonal cut:

<svg viewBox="0 0 1200 120" preserveAspectRatio="none" class="divider angle">
  <polygon points="0,0 1200,120 0,120" fill="currentColor"/>
</svg>

For a steeper angle, adjust the polygon points:

<!-- Steeper angle -->
<polygon points="0,0 1200,80 0,120"/>

<!-- Shallow angle -->
<polygon points="0,60 1200,120 0,120"/>

Curved Arc

Smooth arc transition:

<svg viewBox="0 0 1200 120" preserveAspectRatio="none" class="divider curve">
  <path d="M0,120 Q600,0 1200,120 Z" fill="currentColor"/>
</svg>

Flip it by changing the curve direction:

<!-- Curve up into next section -->
<path d="M0,0 Q600,120 1200,0 L1200,120 L0,120 Z"/>

Triangle/Arrow

Points toward content:

<svg viewBox="0 0 1200 120" preserveAspectRatio="none" class="divider arrow">
  <polygon points="0,0 600,120 1200,0 1200,120 0,120" fill="currentColor"/>
</svg>

Mountains/Peaks

Multiple peaks for a dramatic effect:

<svg viewBox="0 0 1200 120" preserveAspectRatio="none" class="divider peaks">
  <polygon points="0,120 200,40 400,80 600,20 800,60 1000,30 1200,80 1200,120" fill="currentColor"/>
</svg>

Organic Blob

Irregular, natural shape:

<svg viewBox="0 0 1200 120" preserveAspectRatio="none" class="divider blob">
  <path d="M0,60 C150,120 300,0 450,60 C600,120 750,30 900,80 C1050,130 1150,40 1200,70 L1200,120 L0,120 Z" fill="currentColor"/>
</svg>

Positioning Dividers

Dividers can appear at the top, bottom, or both edges of a section.

Bottom Divider (Most Common)

<section class="section with-bottom-divider">
  <div class="content">...</div>
  <svg class="divider divider-bottom" viewBox="0 0 1200 120" preserveAspectRatio="none">
    <path d="..." fill="currentColor"/>
  </svg>
</section>
.section {
  position: relative;
}

.divider-bottom {
  position: absolute;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 80px;
  color: #18181b; /* Color of NEXT section */
}

Top Divider

.divider-top {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 80px;
  color: #f4f4f5; /* Color of PREVIOUS section */
  transform: rotate(180deg);
}

Both Top and Bottom

<section class="section">
  <svg class="divider divider-top">...</svg>
  <div class="content">...</div>
  <svg class="divider divider-bottom">...</svg>
</section>
.section {
  position: relative;
  padding: 120px 2rem; /* Extra padding for dividers */
}

Flipping and Mirroring

Reuse the same divider shape in different orientations.

Horizontal Flip

.divider-flip-x {
  transform: scaleX(-1);
}

Vertical Flip

.divider-flip-y {
  transform: scaleY(-1);
}

/* Or use rotation */
.divider-flip-y {
  transform: rotate(180deg);
}

Both Axes

.divider-flip-both {
  transform: scale(-1, -1);
}

Responsive Divider Heights

Dividers should scale appropriately on different screen sizes.

.divider {
  height: 40px;
}

@media (min-width: 640px) {
  .divider {
    height: 60px;
  }
}

@media (min-width: 1024px) {
  .divider {
    height: 80px;
  }
}

@media (min-width: 1280px) {
  .divider {
    height: 120px;
  }
}

Alternatively, use viewport units:

.divider {
  height: clamp(40px, 8vw, 120px);
}

Animated Dividers

Add subtle motion to make dividers more dynamic.

Gentle Wave Motion

<svg viewBox="0 0 1200 120" preserveAspectRatio="none" class="divider animated-wave">
  <path d="M0,60 Q300,120 600,60 T1200,60 L1200,120 L0,120 Z">
    <animate
      attributeName="d"
      dur="10s"
      repeatCount="indefinite"
      values="
        M0,60 Q300,120 600,60 T1200,60 L1200,120 L0,120 Z;
        M0,80 Q300,40 600,80 T1200,80 L1200,120 L0,120 Z;
        M0,60 Q300,120 600,60 T1200,60 L1200,120 L0,120 Z
      "
    />
  </path>
</svg>

CSS Animation Alternative

.animated-wave {
  animation: wave-drift 8s ease-in-out infinite;
}

@keyframes wave-drift {
  0%, 100% {
    transform: translateX(0);
  }
  50% {
    transform: translateX(-2%);
  }
}

Parallax Layered Waves

.wave-back {
  animation: wave-slow 12s ease-in-out infinite;
}

.wave-mid {
  animation: wave-medium 8s ease-in-out infinite;
}

.wave-front {
  animation: wave-fast 6s ease-in-out infinite;
}

@keyframes wave-slow {
  0%, 100% { transform: translateX(0); }
  50% { transform: translateX(-3%); }
}

@keyframes wave-medium {
  0%, 100% { transform: translateX(0); }
  50% { transform: translateX(-2%); }
}

@keyframes wave-fast {
  0%, 100% { transform: translateX(0); }
  50% { transform: translateX(-1%); }
}

Respect Motion Preferences

Always disable animations for users who prefer reduced motion:

@media (prefers-reduced-motion: reduce) {
  .divider,
  .wave-back,
  .wave-mid,
  .wave-front {
    animation: none;
  }
}

SVG Masks for Advanced Effects

Beyond simple dividers, SVG masks enable complex clipping effects.

Basic Mask Syntax

.masked-section {
  -webkit-mask-image: url('mask.svg');
  mask-image: url('mask.svg');
  -webkit-mask-size: 100% auto;
  mask-size: 100% auto;
  -webkit-mask-position: bottom;
  mask-position: bottom;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
}

Inline SVG Mask

.masked-section {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 1200 120' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M0,0 L1200,0 L1200,60 Q900,120 600,60 T0,60 Z' fill='white'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 1200 120' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M0,0 L1200,0 L1200,60 Q900,120 600,60 T0,60 Z' fill='white'/%3E%3C/svg%3E");
}

Gradient Fade with Mask

Combine SVG mask with CSS gradient:

<section class="hero masked-fade">
  <div class="content">Hero Content</div>
</section>
.masked-fade {
  position: relative;
}

.masked-fade::after {
  content: '';
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  height: 200px;
  background: linear-gradient(to bottom, transparent, #18181b);
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 1200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M0,0 Q300,100 600,50 T1200,100 L1200,200 L0,200 Z' fill='white'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 1200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M0,0 Q300,100 600,50 T1200,100 L1200,200 L0,200 Z' fill='white'/%3E%3C/svg%3E");
}

Creating Custom Shapes

Understanding SVG Path Commands

The d attribute in <path> uses these commands:

| Command | Meaning | Example | |---------|---------|---------| | M | Move to | M0,0 (start at 0,0) | | L | Line to | L100,50 (line to 100,50) | | Q | Quadratic curve | Q50,100 100,50 (curve with control point) | | C | Cubic curve | C20,80 80,80 100,50 (two control points) | | T | Smooth quadratic | T200,50 (continues previous curve) | | Z | Close path | Z (line back to start) |

Wave Generator Formula

Here's a JavaScript function to generate wave paths:

function generateWave(width, height, waves, amplitude) {
  const points = [];
  const step = width / (waves * 2);

  points.push(`M0,${height / 2}`);

  for (let i = 0; i <= waves * 2; i++) {
    const x = i * step;
    const y = i % 2 === 0
      ? height / 2 - amplitude
      : height / 2 + amplitude;
    points.push(`Q${x - step / 2},${y} ${x},${height / 2}`);
  }

  points.push(`L${width},${height} L0,${height} Z`);

  return points.join(' ');
}

// Usage: generateWave(1200, 120, 3, 40)
// Creates a 1200x120 wave with 3 peaks and 40px amplitude

Design Tools

For complex custom shapes:

  1. Design in Figma/Illustrator - Draw your shape with pen tools
  2. Export as SVG - Copy the path data
  3. Optimize - Use SVG Minify to clean up
  4. Test - Use SVG Playground to preview

Or use our AI SVG Generator to create unique organic shapes and export them for use as dividers.

Performance Tips

Keep Paths Simple

Complex paths with hundreds of points render slower:

<!-- Avoid: Over-complicated path -->
<path d="M0,0 C1,2 3,4 5,6 C7,8 9,10 11,12..." /> <!-- 500+ points -->

<!-- Better: Simplified path -->
<path d="M0,60 Q300,120 600,60 T1200,60 L1200,120 L0,120 Z"/>

Use will-change for Animated Dividers

.animated-wave {
  will-change: transform;
}

Lazy Load Below-the-Fold Dividers

For pages with many sections, consider lazy loading dividers that aren't immediately visible:

<svg class="divider" data-lazy-svg>
  <!-- Path loaded via JavaScript when in viewport -->
</svg>

Browser Support

SVG dividers work in all modern browsers:

  • Chrome 4+
  • Firefox 3+
  • Safari 3.2+
  • Edge 12+
  • Opera 10+

CSS masks have slightly less support:

  • Requires -webkit- prefix for Safari and older Chrome
  • IE11 doesn't support CSS masks (use positioned SVGs instead)

Common Mistakes to Avoid

Mistake 1: Forgetting preserveAspectRatio="none"

Without this, your SVG won't stretch to full width:

<!-- Won't stretch properly -->
<svg viewBox="0 0 1200 120">

<!-- Will stretch to fill container -->
<svg viewBox="0 0 1200 120" preserveAspectRatio="none">

Mistake 2: Wrong Color Direction

Remember: the divider color should match where you're transitioning TO, not from:

/* Transitioning FROM light TO dark */
.divider {
  color: #18181b; /* The dark color, not the light one */
}

Mistake 3: Z-Index Issues

Dividers can get hidden behind content:

.section {
  position: relative;
  z-index: 1;
}

.divider {
  position: relative;
  z-index: 2;
}

Mistake 4: Not Accounting for Divider Height

Sections need padding to prevent content overlap:

.section-with-divider {
  padding-bottom: calc(4rem + 80px); /* Regular padding + divider height */
}

Complete Example

Here's a full implementation:

<!DOCTYPE html>
<html>
<head>
  <style>
    * { margin: 0; box-sizing: border-box; }

    .section {
      position: relative;
      padding: 6rem 2rem;
    }

    .section-hero {
      background: linear-gradient(135deg, #6366f1, #8b5cf6);
      color: white;
      min-height: 60vh;
      display: flex;
      align-items: center;
      justify-content: center;
    }

    .section-features {
      background: #fafafa;
    }

    .section-cta {
      background: #18181b;
      color: white;
    }

    .divider {
      position: absolute;
      left: 0;
      width: 100%;
      height: clamp(40px, 8vw, 100px);
      display: block;
    }

    .divider-bottom {
      bottom: 0;
    }

    .divider-top {
      top: 0;
      transform: rotate(180deg);
    }

    @media (prefers-reduced-motion: reduce) {
      .divider { animation: none; }
    }
  </style>
</head>
<body>

  <section class="section section-hero">
    <h1>Welcome to Our Site</h1>
    <svg class="divider divider-bottom" viewBox="0 0 1200 120" preserveAspectRatio="none">
      <path d="M0,0 C300,120 900,0 1200,100 L1200,120 L0,120 Z" fill="#fafafa"/>
    </svg>
  </section>

  <section class="section section-features">
    <h2>Features</h2>
    <svg class="divider divider-bottom" viewBox="0 0 1200 120" preserveAspectRatio="none">
      <path d="M0,60 L600,120 L1200,60 L1200,120 L0,120 Z" fill="#18181b"/>
    </svg>
  </section>

  <section class="section section-cta">
    <h2>Get Started Today</h2>
  </section>

</body>
</html>

Tools for Creating Shape Dividers

Design

Optimization

Conversion

Key Takeaways

  1. SVGs are ideal for dividers - Infinitely scalable, tiny file sizes, full CSS control
  2. preserveAspectRatio="none" is essential - Without it, dividers won't stretch properly
  3. Match colors to the destination - The divider takes the color of the section it transitions INTO
  4. Account for height in padding - Prevent content from overlapping dividers
  5. Animate with care - Subtle motion adds polish; excessive animation distracts
  6. Respect accessibility - Always support prefers-reduced-motion

Shape dividers are one of those details that separate amateur layouts from professional ones. They're simple to implement but make a significant visual impact.


Related Articles:

Ready to create your own vectors?

Start designing with AI-powered precision today.

Get Started Free