Background Bleed: The Subpixel Rendering Bug
Why border-radius sometimes leaves a gap between background and border, and how background-clip fixes it
You've likely seen it: a button or card with a border and a background color, where a faint, ghostly line of the background color "bleeds" outside the border's curve. It looks like a sloppy mistake, but it's actually a collision between vector math and pixel grids.
The Subpixel Rendering Conflict
Browsers calculate layout using high-precision floating-point numbers, but they must eventually paint to a grid of integer pixels. When you use border-radius, you're asking the browser to draw a curve that cuts through pixels.
The problem arises from how different parts of the element are anti-aliased:
- The Border: The browser draws the border curve and applies anti-aliasing to smooth the edges.
- The Background: By default (
background-clip: border-box), the background extends to the outer edge of the border.
If the anti-aliasing algorithms for the border's outer edge and the background's clipping don't perfectly align—which often happens at the subpixel level—pixels that should be fully covered by the border might show a sliver of the background color underneath.
The Fix: background-clip
The most robust solution is to stop the background from extending under the border in the first place. By changing the clipping region, you ensure the background geometry stays strictly inside the border geometry.
.element {
border: 1px solid #000;
border-radius: 8px;
background-color: #f0f0f0;
/* The Fix */
background-clip: padding-box;
}With background-clip: padding-box, the background stops at the inner edge of the border (the padding edge). This eliminates the possibility of the background bleeding out, because it's no longer even trying to paint in that subpixel danger zone.
When This Fails
Note that background-clip: padding-box prevents the background from showing under the border. If your border is semi-transparent (e.g., rgba(0,0,0,0.5)), you will see the parent's background through the border instead of the element's background. In those rare cases, you might need to use nested elements or box-shadow to fake the border.
Advertisement
Explore these curated resources to deepen your understanding
Advertisement