EdgeCases Logo
Dec 2025
CSS
Deep
6 min read

Background Bleed: The Subpixel Rendering Bug

Why border-radius sometimes leaves a gap between background and border, and how background-clip fixes it

css
border-radius
subpixel-rendering
background-clip
edge-case

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

Advertisement