border-radius and Background Animation Costs
Part of Hardware-Accelerated Properties in Core CSS Animation Fundamentals.
The problem
A search field expands and its corners soften from 8px to a pill shape. A hero image slowly pans with an animated background-position — a “Ken Burns” effect. An avatar morphs from a circle to a rounded square on hover. A card with rounded corners and overflow: hidden contains a carousel whose slides are animated with transform.
The first three animate paint properties directly. The fourth animates only a transform, but still stutters. Rounded corners and backgrounds have costs that are easy to miss because they do not look like “layout” properties.
Root cause analysis: shape and background are raster work
border-radius changes the geometry of the box’s background, border and shadow. Every frame, the browser re-rasterises those with the new curve. For a small button that is trivial; for a large panel with a shadow, the shadow blur has to be recomputed around the new shape too.
background-position and background-size change which image pixels land where. There is no pre-rasterised texture to slide — the background is re-painted every frame, including decoding-cache lookups and scaling for large images. A slow pan on a full-width hero repaints a full-width hero sixty times a second.
Rounded clipping is the hidden cost. An element with border-radius and overflow: hidden clips its children to a rounded rectangle. A rectangular clip is cheap for the compositor; a rounded clip generally requires a mask layer, and moving children inside it means the compositor blends through that mask every frame — in some engines forcing extra layers or even paint when children are promoted.
Borders that change colour or width repaint the element’s edges; width changes also trigger layout, as covered in the compositing tier reference.
Step-by-step resolution
Production code pattern
<section class="hero">
<img class="hero__image" src="coast.avif" alt="" width="1600" height="900">
<div class="hero__content">…</div>
</section>
/* Ken Burns pan: move and scale the image element, not the background. */
.hero {
position: relative;
overflow: clip; /* rectangular clip: cheap to composite */
aspect-ratio: 16 / 9;
}
.hero__image {
position: absolute;
inset: -4%; /* bleed so the pan never reveals an edge */
inline-size: 108%;
block-size: 108%;
object-fit: cover;
animation: drift 24s ease-in-out infinite alternate;
}
@keyframes drift {
from { translate: -2% 0; scale: 1; }
to { translate: 2% -1%; scale: 1.06; }
}
/* Avatar shape change: small enough that border-radius itself is fine. */
.avatar {
border-radius: 50%;
transition: border-radius 200ms ease-out;
}
.avatar:hover { border-radius: 22%; }
/* Rounded card with a sliding carousel: round the slides, keep the clip rectangular. */
.carousel {
overflow: clip; /* no radius on the clipping element */
}
.carousel__slide {
border-radius: 16px; /* the visual rounding lives on the slides */
}
@media (prefers-reduced-motion: reduce) {
.hero__image { animation: none; translate: none; scale: none; }
.avatar { transition: none; }
}
Rendering Impact: composite for the hero drift, small paint for the avatar. The hero image is rasterised once and moved and scaled as a texture; its decode happens before the animation starts. Moving radius off the clipping container avoids a rounded mask on every carousel frame.
Scaling the image upward over 24 seconds can soften it slightly, the raster-scale effect covered in fixing blurry text after transforms. For photographs a 6% zoom is invisible; for images with text or sharp lines, start at the larger scale and drift down.
Verification checklist
Constraints and trade-offs
- Replacing a CSS background with an
imgchanges semantics; use emptyaltfor decoration. - A bleed of a few percent is needed so translations never expose the container edge.
- Moving radius from the container to children changes how borders and shadows on the container look.
clip-pathwith roundedinset()is another rounded clip and has similar costs when animated.- Very long, slow pans keep a layer promoted for the whole time; pause them when off-screen.
Frequently asked questions
Is animating border-radius expensive?
It repaints the element each frame. On small elements such as avatars and buttons the cost is negligible; on large panels, especially with shadows, it can take several milliseconds per frame.
How do I animate background-position without repaint?
Put the image on an inner element or pseudo-element inside an overflow-clipped container and animate its translate. The texture moves on the compositor.
Why does a rounded container slow down animations inside it?
Rounded overflow clipping usually needs a mask. Children that move inside it must be blended through that mask every frame, which rectangular clips avoid.
Related
- Hardware-Accelerated Properties — the parent topic
- Animating Colours Without Repaint — cross-fading pre-painted layers
- Gradient, Shadow and Blur Repaint Costs — the other expensive decorations