You've built a scalloped (wavy) edge using a repeating radial-gradient on a pseudo-element. It looks perfect in Firefox. You open Chrome, and there's a faint dark line running along the entire edge.
This is a Chrome sub-pixel rendering bug, and it comes down to one thing: what transparent actually means in CSS.
The Setup
A typical scalloped edge uses a repeating radial gradient to punch semi-circular cutouts into a solid strip:
.element::after {
content: '';
position: absolute;
width: 14px;
height: 100%;
background: radial-gradient(
ellipse 10px 8px at 0 50%,
transparent 99%,
#1a3a2a 100%
);
background-size: 14px 20px;
background-repeat: repeat-y;
}
The center of each ellipse is transparent (the cutout), the outside is your solid color. The 99% → 100% creates a near-hard stop with just enough room for anti-aliasing.
Why Chrome Shows a Line
transparent in CSS is rgba(0, 0, 0, 0) — transparent black.
When Chrome interpolates between transparent and your color at that gradient boundary, it mixes through black. Even though the transition space is tiny, Chrome renders a visible sub-pixel line of the intermediate color:
transparent = rgba(0, 0, 0, 0) ← black at zero alpha
your color = rgba(26, 58, 42, 1)
Chrome blends through that black → dark line artifact
Firefox handles this boundary more gracefully — no visible artifact.
What Didn't Work: color-mix()
The intuitive fix is to replace transparent with a zero-opacity version of your actual color so Chrome blends between the same hue:
background: radial-gradient(
ellipse 10px 8px at 0 50%,
color-mix(in srgb, #1a3a2a 0%, transparent) 99%,
#1a3a2a 100%
);
In theory, this eliminates the black-channel bleed. In practice, the line persisted — Chrome's sub-pixel rendering still produced a visible artifact at the gradient boundary.
What Works: CSS Masks
The fix is to separate color from shape. Instead of using the gradient for both, make the background a flat solid color and move the shape into a mask-image.
Option 1: Gradient Mask
The quickest change — move the same gradient from background to mask-image:
.element::after {
content: '';
position: absolute;
width: 14px;
height: 100%;
/* Flat color — nothing to interpolate */
background: #1a3a2a;
/* Shape defined by mask alpha channel only */
mask-image: radial-gradient(
ellipse 10px 8px at 0 50%,
transparent 99%,
#000 100%
);
mask-size: 14px 20px;
mask-repeat: repeat-y;
}
CSS masks only read the alpha channel. The gradient transitions from alpha 0 to alpha 1 — a pure opacity operation with no color data for Chrome to mix through. No color mixing → no dark line.
Option 2: SVG Mask (More Control)
If you need precise control over scallop shape — like elongated bumps or specific aspect ratios — an inline SVG mask gives you that:
.element::after {
content: '';
position: absolute;
width: 20px;
height: 100%;
background-color: inherit;
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'
width='20' height='28'%3E%3Cdefs%3E%3Cmask id='m'%3E%3Crect width='20'
height='28' fill='white'/%3E%3Cellipse cx='0' cy='14' rx='10' ry='12'
fill='black'/%3E%3C/mask%3E%3C/defs%3E%3Crect width='20' height='28'
mask='url(%23m)' fill='white'/%3E%3C/svg%3E");
mask-size: 20px 28px;
mask-repeat: repeat-y;
}
Here's the decoded SVG for clarity:
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="28">
<defs>
<mask id="m">
<rect width="20" height="28" fill="white"/>
<ellipse cx="0" cy="14" rx="10" ry="12" fill="black"/>
</mask>
</defs>
<rect width="20" height="28" mask="url(#m)" fill="white"/>
</svg>
White areas are visible, the black ellipse is cut out. You can tweak rx and ry independently to control scallop width and height, or swap in a <path> for non-circular shapes. Both approaches fix the Chrome line for the same reason: flat background color + mask handles shape through alpha only.
Summary
| Approach | Result in Chrome |
|---|---|
transparent keyword in gradient |
Dark line (blends through black) |
color-mix() to 0% opacity |
Still a line (sub-pixel rendering) |
mask-image (gradient or SVG) with solid background |
Clean |
If you have a radial-gradient scalloped edge showing a line in Chrome, move the shape to mask-image and set background to your solid color. Use a gradient mask for a quick fix, or an SVG mask when you need precise control over the scallop shape. Either way, masks eliminate color interpolation entirely — which is the root cause.


Top comments (0)