Prompt and context
A marketing card needs a curved edge that responds to its container width. The design provides a path, but the decoration must not break content, keyboard focus, or older-browser layout. Explain how to use shape() with clip-path, compare it with path() and polygon(), and provide a progressive-enhancement plan.
What the interviewer is testing
- Knowing that
shape()is a CSS basic-shape function, not an SVG path string. - Handling units, CSS math, container size, and browser support differences.
- Treating clipping as decoration while preserving semantic content, focus, and readable fallback.
Questions to clarify first
- Is the shape decoration, or does it carry information, a hit area, or reading order?
- Does the browser matrix allow a CSS Shapes Level 2 capability that is not broadly available?
- When unsupported, is a rectangle, a
polygon()approximation, or an image asset acceptable?
A 30-second answer
I would lay out the content with the normal box model and add clip-path: shape(...) as a visual enhancement. shape() accepts CSS units and math, which helps responsive geometry; path() uses an SVG path string, while polygon() is easier to fall back to but only approximates curves. I would gate the enhancement with @supports or feature detection, keep a readable rectangle, and test that clipping does not hide focus, hit targets, or semantic content.
Step-by-step deep dive
1. Separate content from clipping
Keep the heading, copy, and button in normal DOM order. clip-path changes the painted region; it should not hide content or reorder reading. Put backgrounds, edges, and illustrations in a decorative layer while the content layer remains scrollable and focusable.
2. Why choose shape()
shape() uses CSS-style commands and can combine percentages, lengths, and CSS math. Compared with an SVG path() string, it is easier to tune with container dimensions and design tokens. Compared with polygon(), it can express curves and richer path commands.
3. Write a scoped enhancement
.card {
background: var(--surface);
overflow: clip;
}
@supports (clip-path: shape(from 0 0, line to 100% 0, close)) {
.card {
clip-path: shape(
from 0 0,
line to 100% 0,
line to 100% 82%,
curve to 0 100% with 52% 88%,
close
);
}
}The fenced command is illustrative; production syntax must be checked against the target browsers and specification. The base rule provides usable color, spacing, and text, so a failed enhancement does not leave an empty card.
4. Design fallback layers
The safest fallback is a rectangle. Where polygon() is supported, it can approximate the edge. If a curve is essential, use a compressed background asset while retaining CSS color and text contrast. Do not make an untested complex path the only layout.
5. Handle responsive size and overflow
Express key points with percentages and container dimensions, then test very narrow and wide containers, landscape, and high zoom. clip-path can make the painted region smaller but does not reserve extra layout space; content still needs padding, minimum height, and a scrolling strategy.
6. Verify the accessibility boundary
Clipping does not change DOM semantics, screen-reader order, or keyboard order, but it can visually cover a focus ring, error message, or pointer target. Test keyboard navigation, zoom, screen readers, and high contrast; put focus styling on an unclipped wrapper when needed.
7. Manage motion and cost
If the shape animates, ensure it does not cause discomfort or obscure content and honor prefers-reduced-motion. Watch paint cost on low-end devices and long lists; static decoration is preferable to continuous complex redraws.
Model answer
I would let the card complete normal box-model layout first, keeping its heading, copy, and button semantic, then use clip-path only as decoration. shape() fits responsive geometry because it accepts CSS units and math; path() is closer to an SVG string, while polygon() is a conservative approximation. I would gate the enhancement with @supports, preserve a rectangle or tested approximation when it fails, and test extreme widths, zoom, keyboard focus, screen readers, high contrast, and reduced motion. The clipped edge must never hide a focus ring or hit target.
Common mistakes
- Treating
shape()as syntax that accepts an SVGpath()string unchanged. - Writing only the enhancement and no readable rectangular base style.
- Letting the clip edge cover a button, error message, or focus indicator.
- Using fixed-pixel geometry for every container width and text length.
- Claiming universal support without a target matrix and feature detection.
Follow-up questions and responses
Why not use one SVG image?
For a fixed brand asset, SVG may be more stable. Choose shape() when CSS units, container responsiveness, and theme tokens matter, then weigh support, maintenance, and performance.
What if @supports passes but the shape is wrong?
Treat feature detection as a syntax gate, not proof that every path command behaves identically. Use real-browser screenshots and interaction tests for key commands, with a simpler fallback path.
Can clipping affect the hit area?
Visual clipping can affect perceived hit behavior, so verify it in target browsers. Keep controls large and visibly focused, and move the interaction layer to an unclipped wrapper when necessary.
What if text must follow the curve?
clip-path only clips a region; it does not lay text along a path. Use a separate text-layout technique or change the content structure rather than treating clipping as a typography API.
How do you test localized content?
Test the longest translation, different weights, Arabic or CJK mixtures, and user zoom. The shape is decoration, so a short English string fitting by chance is not sufficient evidence.
When should you abandon shape()?
Use polygon(), a gradient, SVG, or a rectangle when support, animation cost, or visual consistency cannot meet the gate. State the stop condition instead of defending a new feature at all costs.