14 CSS Wave Section Dividers05 / 14
CSS wave section divider footer transition
The seamless hand-off into a dark footer: a curved cutout at the top of the footer scoops the page content into it, so the footer feels like the bottom of a single continuous surface instead of a bolted-on slab.
Published
The code
<div class="wsd-05-group">
<section class="wsd-05a">
<div class="wsd-05a__page"><p class="wsd-05a__copy">Last content section of the page.</p></div>
<footer class="wsd-05a__footer">
<svg class="wsd-05a__wave" viewBox="0 0 1440 120" preserveAspectRatio="none" aria-hidden="true" focusable="false">
<path d="M0,64 C240,120 480,8 720,40 C960,72 1200,120 1440,72 L1440,0 L0,0 Z"></path>
</svg>
<nav class="wsd-05a__cols" aria-label="Footer">
<div><h3 class="wsd-05a__h">Product</h3><a href="#0">Features</a><a href="#0">Pricing</a><a href="#0">Changelog</a></div>
<div><h3 class="wsd-05a__h">Resources</h3><a href="#0">Docs</a><a href="#0">Snippets</a><a href="#0">Support</a></div>
<div><h3 class="wsd-05a__h">Company</h3><a href="#0">About</a><a href="#0">Careers</a><a href="#0">Contact</a></div>
</nav>
<p class="wsd-05a__fine">© 2027 codefronts.com — wave divider snippets.</p>
</footer>
</section>
<section class="wsd-05b">
<div class="wsd-05b__page"><p class="wsd-05b__copy">Newsletter, testimonials, whatever sits above your footer.</p></div>
<footer class="wsd-05b__footer">
<p class="wsd-05b__brand">codefronts</p>
<p class="wsd-05b__fine">Scallops read friendlier than a single deep curve — good for consumer and education sites.</p>
</footer>
</section>
</div><div class="wsd-05-group">
<section class="wsd-05a">
<div class="wsd-05a__page"><p class="wsd-05a__copy">Last content section of the page.</p></div>
<footer class="wsd-05a__footer">
<svg class="wsd-05a__wave" viewBox="0 0 1440 120" preserveAspectRatio="none" aria-hidden="true" focusable="false">
<path d="M0,64 C240,120 480,8 720,40 C960,72 1200,120 1440,72 L1440,0 L0,0 Z"></path>
</svg>
<nav class="wsd-05a__cols" aria-label="Footer">
<div><h3 class="wsd-05a__h">Product</h3><a href="#0">Features</a><a href="#0">Pricing</a><a href="#0">Changelog</a></div>
<div><h3 class="wsd-05a__h">Resources</h3><a href="#0">Docs</a><a href="#0">Snippets</a><a href="#0">Support</a></div>
<div><h3 class="wsd-05a__h">Company</h3><a href="#0">About</a><a href="#0">Careers</a><a href="#0">Contact</a></div>
</nav>
<p class="wsd-05a__fine">© 2027 codefronts.com — wave divider snippets.</p>
</footer>
</section>
<section class="wsd-05b">
<div class="wsd-05b__page"><p class="wsd-05b__copy">Newsletter, testimonials, whatever sits above your footer.</p></div>
<footer class="wsd-05b__footer">
<p class="wsd-05b__brand">codefronts</p>
<p class="wsd-05b__fine">Scallops read friendlier than a single deep curve — good for consumer and education sites.</p>
</footer>
</section>
</div>.wsd-05-group {
width: 100%;
min-height: 100vh;
display: flex;
flex-direction: column;
gap: 0;
}
.wsd-05-group > section {
width: 100%;
}
.wsd-05a,
.wsd-05a *,
.wsd-05a *::before,
.wsd-05a *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.wsd-05a {
--page: oklch(0.96 0.01 250);
--footer: oklch(0.2 0.03 250);
--accent: oklch(0.78 0.14 180);
font-family: 'Segoe UI',system-ui,sans-serif;
}
.wsd-05a__page {
background: var(--page);
color: oklch(0.34 0.03 250);
padding: 56px 24px 40px;
text-align: center;
}
.wsd-05a__copy {
font-size: 15px;
opacity: .72;
}
.wsd-05a__footer {
position: relative;
overflow: hidden;
background: var(--footer);
color: #fff;
padding: clamp(100px,14vw,160px) 24px 30px;
}
.wsd-05a__wave {
position: absolute;
left: 0;
right: 0;
top: -1px;
display: block;
width: 100%;
height: clamp(56px,9vw,110px);
color: var(--page);
pointer-events: none;
}
.wsd-05a__wave path {
fill: currentColor;
}
.wsd-05a__cols {
display: grid;
grid-template-columns: repeat(auto-fit,minmax(140px,1fr));
gap: 26px;
max-width: 760px;
margin: 0 auto;
}
.wsd-05a__cols div {
display: flex;
flex-direction: column;
gap: 9px;
}
.wsd-05a__h {
font-size: 12px;
letter-spacing: .14em;
text-transform: uppercase;
color: var(--accent);
}
.wsd-05a__cols a {
font-size: 14.5px;
color: rgba(255,255,255,.86);
text-decoration: none;
width: fit-content;
}
.wsd-05a__cols a:hover {
color: #fff;
text-decoration: underline;
text-underline-offset: 4px;
}
.wsd-05a__cols a:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 3px;
border-radius: 3px;
}
.wsd-05a__fine {
margin-top: 30px;
text-align: center;
font-size: 12.5px;
color: rgba(255,255,255,.6);
}
.wsd-05b,
.wsd-05b *,
.wsd-05b *::before,
.wsd-05b *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.wsd-05b {
--page: oklch(0.97 0.02 60);
--footer: oklch(0.26 0.06 22);
font-family: 'Segoe UI',system-ui,sans-serif;
}
.wsd-05b__page {
background: var(--page);
color: oklch(0.34 0.05 30);
padding: 54px 24px 34px;
text-align: center;
}
.wsd-05b__copy {
font-size: 15px;
opacity: .74;
}
.wsd-05b__footer {
position: relative;
background: var(--footer);
color: #fff;
padding: 78px 24px 44px;
text-align: center;
}
.wsd-05b__footer::before {
content: "";
position: absolute;
left: 0;
right: 0;
top: -1px;
height: 34px;
background: var(--page);
-webkit-mask: radial-gradient(28px at 50% 100%,transparent 98%,#000) repeat-x 0 0/56px 34px;
mask: radial-gradient(28px at 50% 100%,transparent 98%,#000) repeat-x 0 0/56px 34px;
pointer-events: none;
}
.wsd-05b__brand {
font-size: clamp(22px,3.4vw,32px);
font-weight: 800;
letter-spacing: -.02em;
margin-bottom: 8px;
}
.wsd-05b__fine {
font-size: 14px;
color: rgba(255,255,255,.72);
max-width: 52ch;
margin: 0 auto;
}.wsd-05-group {
width: 100%;
min-height: 100vh;
display: flex;
flex-direction: column;
gap: 0;
}
.wsd-05-group > section {
width: 100%;
}
.wsd-05a,
.wsd-05a *,
.wsd-05a *::before,
.wsd-05a *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.wsd-05a {
--page: oklch(0.96 0.01 250);
--footer: oklch(0.2 0.03 250);
--accent: oklch(0.78 0.14 180);
font-family: 'Segoe UI',system-ui,sans-serif;
}
.wsd-05a__page {
background: var(--page);
color: oklch(0.34 0.03 250);
padding: 56px 24px 40px;
text-align: center;
}
.wsd-05a__copy {
font-size: 15px;
opacity: .72;
}
.wsd-05a__footer {
position: relative;
overflow: hidden;
background: var(--footer);
color: #fff;
padding: clamp(100px,14vw,160px) 24px 30px;
}
.wsd-05a__wave {
position: absolute;
left: 0;
right: 0;
top: -1px;
display: block;
width: 100%;
height: clamp(56px,9vw,110px);
color: var(--page);
pointer-events: none;
}
.wsd-05a__wave path {
fill: currentColor;
}
.wsd-05a__cols {
display: grid;
grid-template-columns: repeat(auto-fit,minmax(140px,1fr));
gap: 26px;
max-width: 760px;
margin: 0 auto;
}
.wsd-05a__cols div {
display: flex;
flex-direction: column;
gap: 9px;
}
.wsd-05a__h {
font-size: 12px;
letter-spacing: .14em;
text-transform: uppercase;
color: var(--accent);
}
.wsd-05a__cols a {
font-size: 14.5px;
color: rgba(255,255,255,.86);
text-decoration: none;
width: fit-content;
}
.wsd-05a__cols a:hover {
color: #fff;
text-decoration: underline;
text-underline-offset: 4px;
}
.wsd-05a__cols a:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 3px;
border-radius: 3px;
}
.wsd-05a__fine {
margin-top: 30px;
text-align: center;
font-size: 12.5px;
color: rgba(255,255,255,.6);
}
.wsd-05b,
.wsd-05b *,
.wsd-05b *::before,
.wsd-05b *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.wsd-05b {
--page: oklch(0.97 0.02 60);
--footer: oklch(0.26 0.06 22);
font-family: 'Segoe UI',system-ui,sans-serif;
}
.wsd-05b__page {
background: var(--page);
color: oklch(0.34 0.05 30);
padding: 54px 24px 34px;
text-align: center;
}
.wsd-05b__copy {
font-size: 15px;
opacity: .74;
}
.wsd-05b__footer {
position: relative;
background: var(--footer);
color: #fff;
padding: 78px 24px 44px;
text-align: center;
}
.wsd-05b__footer::before {
content: "";
position: absolute;
left: 0;
right: 0;
top: -1px;
height: 34px;
background: var(--page);
-webkit-mask: radial-gradient(28px at 50% 100%,transparent 98%,#000) repeat-x 0 0/56px 34px;
mask: radial-gradient(28px at 50% 100%,transparent 98%,#000) repeat-x 0 0/56px 34px;
pointer-events: none;
}
.wsd-05b__brand {
font-size: clamp(22px,3.4vw,32px);
font-weight: 800;
letter-spacing: -.02em;
margin-bottom: 8px;
}
.wsd-05b__fine {
font-size: 14px;
color: rgba(255,255,255,.72);
max-width: 52ch;
margin: 0 auto;
}/* No JavaScript — the wave is pinned to the footer's top edge and filled with the page colour, so it cuts into the dark footer. */ /* No JavaScript — a repeating radial-gradient mask carves scallops out of a page-coloured strip on the footer's top edge (no SVG at all). */
/* No JavaScript — the wave is pinned to the footer's top edge and filled with the page colour, so it cuts into the dark footer. */
/* No JavaScript — a repeating radial-gradient mask carves scallops out of a page-coloured strip on the footer's top edge (no SVG at all). */Here's a working CSS Wave Section 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: CSS wave section divider footer transition
Source: https://codefronts.com/layouts/css-wave-section-dividers/css-wave-section-divider-footer-transition/
The seamless hand-off into a dark footer: a curved cutout at the top of the footer scoops the page content into it, so the footer feels like the bottom of a single continuous surface instead of a bolted-on slab.
## HTML
```html
<div class="wsd-05-group">
<section class="wsd-05a">
<div class="wsd-05a__page"><p class="wsd-05a__copy">Last content section of the page.</p></div>
<footer class="wsd-05a__footer">
<svg class="wsd-05a__wave" viewBox="0 0 1440 120" preserveAspectRatio="none" aria-hidden="true" focusable="false">
<path d="M0,64 C240,120 480,8 720,40 C960,72 1200,120 1440,72 L1440,0 L0,0 Z"></path>
</svg>
<nav class="wsd-05a__cols" aria-label="Footer">
<div><h3 class="wsd-05a__h">Product</h3><a href="#0">Features</a><a href="#0">Pricing</a><a href="#0">Changelog</a></div>
<div><h3 class="wsd-05a__h">Resources</h3><a href="#0">Docs</a><a href="#0">Snippets</a><a href="#0">Support</a></div>
<div><h3 class="wsd-05a__h">Company</h3><a href="#0">About</a><a href="#0">Careers</a><a href="#0">Contact</a></div>
</nav>
<p class="wsd-05a__fine">© 2027 codefronts.com — wave divider snippets.</p>
</footer>
</section>
<section class="wsd-05b">
<div class="wsd-05b__page"><p class="wsd-05b__copy">Newsletter, testimonials, whatever sits above your footer.</p></div>
<footer class="wsd-05b__footer">
<p class="wsd-05b__brand">codefronts</p>
<p class="wsd-05b__fine">Scallops read friendlier than a single deep curve — good for consumer and education sites.</p>
</footer>
</section>
</div>
```
## CSS
```css
.wsd-05-group {
width: 100%;
min-height: 100vh;
display: flex;
flex-direction: column;
gap: 0;
}
.wsd-05-group > section {
width: 100%;
}
.wsd-05a,
.wsd-05a *,
.wsd-05a *::before,
.wsd-05a *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.wsd-05a {
--page: oklch(0.96 0.01 250);
--footer: oklch(0.2 0.03 250);
--accent: oklch(0.78 0.14 180);
font-family: 'Segoe UI',system-ui,sans-serif;
}
.wsd-05a__page {
background: var(--page);
color: oklch(0.34 0.03 250);
padding: 56px 24px 40px;
text-align: center;
}
.wsd-05a__copy {
font-size: 15px;
opacity: .72;
}
.wsd-05a__footer {
position: relative;
overflow: hidden;
background: var(--footer);
color: #fff;
padding: clamp(100px,14vw,160px) 24px 30px;
}
.wsd-05a__wave {
position: absolute;
left: 0;
right: 0;
top: -1px;
display: block;
width: 100%;
height: clamp(56px,9vw,110px);
color: var(--page);
pointer-events: none;
}
.wsd-05a__wave path {
fill: currentColor;
}
.wsd-05a__cols {
display: grid;
grid-template-columns: repeat(auto-fit,minmax(140px,1fr));
gap: 26px;
max-width: 760px;
margin: 0 auto;
}
.wsd-05a__cols div {
display: flex;
flex-direction: column;
gap: 9px;
}
.wsd-05a__h {
font-size: 12px;
letter-spacing: .14em;
text-transform: uppercase;
color: var(--accent);
}
.wsd-05a__cols a {
font-size: 14.5px;
color: rgba(255,255,255,.86);
text-decoration: none;
width: fit-content;
}
.wsd-05a__cols a:hover {
color: #fff;
text-decoration: underline;
text-underline-offset: 4px;
}
.wsd-05a__cols a:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 3px;
border-radius: 3px;
}
.wsd-05a__fine {
margin-top: 30px;
text-align: center;
font-size: 12.5px;
color: rgba(255,255,255,.6);
}
.wsd-05b,
.wsd-05b *,
.wsd-05b *::before,
.wsd-05b *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.wsd-05b {
--page: oklch(0.97 0.02 60);
--footer: oklch(0.26 0.06 22);
font-family: 'Segoe UI',system-ui,sans-serif;
}
.wsd-05b__page {
background: var(--page);
color: oklch(0.34 0.05 30);
padding: 54px 24px 34px;
text-align: center;
}
.wsd-05b__copy {
font-size: 15px;
opacity: .74;
}
.wsd-05b__footer {
position: relative;
background: var(--footer);
color: #fff;
padding: 78px 24px 44px;
text-align: center;
}
.wsd-05b__footer::before {
content: "";
position: absolute;
left: 0;
right: 0;
top: -1px;
height: 34px;
background: var(--page);
-webkit-mask: radial-gradient(28px at 50% 100%,transparent 98%,#000) repeat-x 0 0/56px 34px;
mask: radial-gradient(28px at 50% 100%,transparent 98%,#000) repeat-x 0 0/56px 34px;
pointer-events: none;
}
.wsd-05b__brand {
font-size: clamp(22px,3.4vw,32px);
font-weight: 800;
letter-spacing: -.02em;
margin-bottom: 8px;
}
.wsd-05b__fine {
font-size: 14px;
color: rgba(255,255,255,.72);
max-width: 52ch;
margin: 0 auto;
}
```
## JavaScript
```js
/* No JavaScript — the wave is pinned to the footer's top edge and filled with the page colour, so it cuts into the dark footer. */
/* No JavaScript — a repeating radial-gradient mask carves scallops out of a page-coloured strip on the footer's top edge (no SVG at all). */
```Here's a working CSS Wave Section 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: CSS wave section divider footer transition
Source: https://codefronts.com/layouts/css-wave-section-dividers/css-wave-section-divider-footer-transition/
The seamless hand-off into a dark footer: a curved cutout at the top of the footer scoops the page content into it, so the footer feels like the bottom of a single continuous surface instead of a bolted-on slab.
## HTML
```html
<div class="wsd-05-group">
<section class="wsd-05a">
<div class="wsd-05a__page"><p class="wsd-05a__copy">Last content section of the page.</p></div>
<footer class="wsd-05a__footer">
<svg class="wsd-05a__wave" viewBox="0 0 1440 120" preserveAspectRatio="none" aria-hidden="true" focusable="false">
<path d="M0,64 C240,120 480,8 720,40 C960,72 1200,120 1440,72 L1440,0 L0,0 Z"></path>
</svg>
<nav class="wsd-05a__cols" aria-label="Footer">
<div><h3 class="wsd-05a__h">Product</h3><a href="#0">Features</a><a href="#0">Pricing</a><a href="#0">Changelog</a></div>
<div><h3 class="wsd-05a__h">Resources</h3><a href="#0">Docs</a><a href="#0">Snippets</a><a href="#0">Support</a></div>
<div><h3 class="wsd-05a__h">Company</h3><a href="#0">About</a><a href="#0">Careers</a><a href="#0">Contact</a></div>
</nav>
<p class="wsd-05a__fine">© 2027 codefronts.com — wave divider snippets.</p>
</footer>
</section>
<section class="wsd-05b">
<div class="wsd-05b__page"><p class="wsd-05b__copy">Newsletter, testimonials, whatever sits above your footer.</p></div>
<footer class="wsd-05b__footer">
<p class="wsd-05b__brand">codefronts</p>
<p class="wsd-05b__fine">Scallops read friendlier than a single deep curve — good for consumer and education sites.</p>
</footer>
</section>
</div>
```
## CSS
```css
.wsd-05-group {
width: 100%;
min-height: 100vh;
display: flex;
flex-direction: column;
gap: 0;
}
.wsd-05-group > section {
width: 100%;
}
.wsd-05a,
.wsd-05a *,
.wsd-05a *::before,
.wsd-05a *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.wsd-05a {
--page: oklch(0.96 0.01 250);
--footer: oklch(0.2 0.03 250);
--accent: oklch(0.78 0.14 180);
font-family: 'Segoe UI',system-ui,sans-serif;
}
.wsd-05a__page {
background: var(--page);
color: oklch(0.34 0.03 250);
padding: 56px 24px 40px;
text-align: center;
}
.wsd-05a__copy {
font-size: 15px;
opacity: .72;
}
.wsd-05a__footer {
position: relative;
overflow: hidden;
background: var(--footer);
color: #fff;
padding: clamp(100px,14vw,160px) 24px 30px;
}
.wsd-05a__wave {
position: absolute;
left: 0;
right: 0;
top: -1px;
display: block;
width: 100%;
height: clamp(56px,9vw,110px);
color: var(--page);
pointer-events: none;
}
.wsd-05a__wave path {
fill: currentColor;
}
.wsd-05a__cols {
display: grid;
grid-template-columns: repeat(auto-fit,minmax(140px,1fr));
gap: 26px;
max-width: 760px;
margin: 0 auto;
}
.wsd-05a__cols div {
display: flex;
flex-direction: column;
gap: 9px;
}
.wsd-05a__h {
font-size: 12px;
letter-spacing: .14em;
text-transform: uppercase;
color: var(--accent);
}
.wsd-05a__cols a {
font-size: 14.5px;
color: rgba(255,255,255,.86);
text-decoration: none;
width: fit-content;
}
.wsd-05a__cols a:hover {
color: #fff;
text-decoration: underline;
text-underline-offset: 4px;
}
.wsd-05a__cols a:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 3px;
border-radius: 3px;
}
.wsd-05a__fine {
margin-top: 30px;
text-align: center;
font-size: 12.5px;
color: rgba(255,255,255,.6);
}
.wsd-05b,
.wsd-05b *,
.wsd-05b *::before,
.wsd-05b *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.wsd-05b {
--page: oklch(0.97 0.02 60);
--footer: oklch(0.26 0.06 22);
font-family: 'Segoe UI',system-ui,sans-serif;
}
.wsd-05b__page {
background: var(--page);
color: oklch(0.34 0.05 30);
padding: 54px 24px 34px;
text-align: center;
}
.wsd-05b__copy {
font-size: 15px;
opacity: .74;
}
.wsd-05b__footer {
position: relative;
background: var(--footer);
color: #fff;
padding: 78px 24px 44px;
text-align: center;
}
.wsd-05b__footer::before {
content: "";
position: absolute;
left: 0;
right: 0;
top: -1px;
height: 34px;
background: var(--page);
-webkit-mask: radial-gradient(28px at 50% 100%,transparent 98%,#000) repeat-x 0 0/56px 34px;
mask: radial-gradient(28px at 50% 100%,transparent 98%,#000) repeat-x 0 0/56px 34px;
pointer-events: none;
}
.wsd-05b__brand {
font-size: clamp(22px,3.4vw,32px);
font-weight: 800;
letter-spacing: -.02em;
margin-bottom: 8px;
}
.wsd-05b__fine {
font-size: 14px;
color: rgba(255,255,255,.72);
max-width: 52ch;
margin: 0 auto;
}
```
## JavaScript
```js
/* No JavaScript — the wave is pinned to the footer's top edge and filled with the page colour, so it cuts into the dark footer. */
/* No JavaScript — a repeating radial-gradient mask carves scallops out of a page-coloured strip on the footer's top edge (no SVG at all). */
```How this works
The footer gets position:relative and a wave pinned to its top edge, filled with the page colour — an inverted use of the pattern from topic 01. Since the footer is the last block, the wave is drawn rotate(180deg) or authored upside-down so the curve bites into the footer.
.footer{position:relative;margin-top:0;padding-top:clamp(96px,13vw,150px)}
.footer__wave{position:absolute;top:-1px;width:100%;transform:scaleY(-1)}Extra padding-top on the footer keeps the first row of links clear of the deepest point of the curve — the one detail most page-builder dividers get wrong.
Make it yours
- Deepen the scoop by increasing wave height and footer padding-top together.
- Use a scallop path for a friendlier, consumer-app feel.
- Add a 1px top border in the accent colour along the curve using a second stroked path.
- Match the wave fill to whatever section precedes the footer, not to white by default.
Gotchas — read before shipping
- Increase footer padding-top or the curve will crash into your link columns.
- Fill the wave with the preceding section's colour, not white, or you get a visible band.
- Set
overflow:hiddenon the footer so a tall curve cannot create a scrollbar. - Keep footer text contrast ≥ 4.5:1 — dark footers with 60% opacity links routinely fail WCAG.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 15.4+ | 113+ | 111+ |
Floor set by oklch() as this demo is written. The core technique itself goes back further — Chrome 36+.
Inline SVG + transform; works everywhere. Nothing to polyfill.