The arrival of shape(): Moving to an era of pure CSS shapes
Historically, rendering complex shapes on the web primarily relied on SVG <path> elements or CSS clip-path: path(). However, SVG path syntax (M 0 0 L 100 50 ...) is notoriously difficult for humans to read and write, and creating responsive designs proved challenging.
In 2026, the shape() function, defined in the CSS Shapes Module Level 2, became supported across all major browsers. Developers can now draw responsive shapes natively in CSS using units like %, rem, and calc().
Browser support
Having reached Baseline 2026 in February 2026, it is supported across all major modern browsers.
| Browser | Supported version |
|---|---|
| Chrome / Edge | 135 or higher |
| Firefox | 148 or higher |
| Safari | 18.4 or higher |
It is also designated as a key focus area in Interop 2026, driving stable cross-browser implementation.
Basic syntax
shape( [<fill-rule>]? from <起点>, <コマンド>[, ...] )
Used within the clip-path or offset-path property.
.element {
clip-path: shape(from 0% 0%, line to 100% 0%, line to 100% 100%, close);
}
List of shape commands
| Command | Features | Examples |
|---|---|---|
line to/by | Draw straight lines | line to 100% 50% |
hline to/by | Horizontal line | hline to 80% |
vline to/by | Vertical line | vline to 100% |
curve to/by ... with | Bézier curve | curve to 100% 50% with 50% 0% |
smooth to/by | Smooth continuous curve | smooth to 80% 60% |
arc to/by ... of | Elliptical arc | arc to 50% 80% of 30% |
move to/by | Move without drawing | move to 20% 20% |
close | Close path | close |
A major advantage is the ability to toggle between to (absolute coordinates) and by (relative coordinates). Using relative coordinates lets you define shapes based on offsets from a reference point.
Key differences from path()
| Features | shape() | path() |
|---|---|---|
| Units | px, %, rem, calc(), etc. | px only |
| Responsiveness | Supported | Not supported |
| CSS math functions | Supports calc(), max(), abs() | Not supported |
| Syntax | Standard CSS syntax, highly readable | SVG path syntax (difficult to read) |
| Animations | Straightforward with custom properties | Limited |
The single greatest difference is responsive support. Because path() only accepts pixel values, shapes could not dynamically scale with screen size changes. In contrast, shape() supports units like % and vw, enabling flexible shapes that adapt naturally to their parent containers.
Implementation examples
Wave clipping
.wave-section {
clip-path: shape(
from 0% 20%,
curve to 100% 20% with 25% 0% / 75% 40%,
vline to 100%,
hline to 0%,
close
);
}
A pattern for turning header and section borders into waves. Adjusting the control points of the curve command is all it takes to alter the wave curvature.
Heart shape
.heart {
clip-path: shape(
from 50% 30%,
arc to 25% 25% of 25% cw,
arc to 50% 60% of 40% cw,
arc to 75% 25% of 40% cw,
arc to 50% 30% of 25% cw,
close
);
background: #e74c3c;
width: 200px;
aspect-ratio: 1;
}
Constructs a heart shape by combining circular arcs with the arc command. Because it is defined using %, modifying width automatically scales the entire shape.
Speech bubble
.speech-bubble {
clip-path: shape(
from 0% 0%,
hline to 100%,
vline to 70%,
line to 20% 70%,
line to 10% 100%,
line to 15% 70%,
hline to 0%,
close
);
background: #f0f0f0;
padding: 1.5rem;
padding-bottom: 3rem;
}
Draws a triangular pointer tail using the line command. Useful for chat user interfaces and tooltip designs.
Fallback strategies
Fallbacks for unsupported legacy browsers can be detected using @supports.
/* 対応ブラウザ向け */
@supports (clip-path: shape(from 0 0, move to 0 0)) {
.element {
clip-path: shape(from 0% 0%, /* ... */);
}
}
/* 未対応ブラウザ向け */
@supports not (clip-path: shape(from 0 0, move to 0 0)) {
.element {
border-radius: 50%;
}
}
As of April 2026, the feature has achieved Baseline 2026 status, meaning it works reliably across modern browser versions. However, if you need to support legacy browser versions, prepare appropriate fallbacks.
Combining with animations
Combining shape() with CSS custom properties makes it possible to animate shapes dynamically.
@property --wave-height {
syntax: '<percentage>';
inherits: false;
initial-value: 20%;
}
.animated-wave {
clip-path: shape(
from 0% var(--wave-height),
curve to 100% var(--wave-height) with 25% 0% / 75% 40%,
vline to 100%,
hline to 0%,
close
);
transition: --wave-height 0.5s ease;
}
.animated-wave:hover {
--wave-height: 10%;
}
Conclusion
CSS shape() represents a major paradigm shift in how shapes are rendered on the web.
- No SVG expertise needed: Define complex shapes using standard CSS syntax
- Responsive by default: Seamlessly adapts to screen dimensions using
%,rem, andcalc() - Reached Baseline 2026: Available across all major modern browsers
- Animation-ready: Create dynamic shapes when combined with CSS custom properties
When implementing bespoke shapes from design mockups, you may no longer need to open an SVG editor. Start experimenting with basic shapes using clip-path: shape(...) today.
To keep pace with evolving web standards, review our Web Accessibility Implementation Guide to balance decorative flair with accessible design.









