Reducing Repaints and Reflows
- CSS Basics
- Selectors & Specificity
- Box Model & Units
- Typography & Text Styling
- Colors & Color Spaces
- Positioning & Stacking Context
- Flexbox
- Grid
- Grid Advanced
- Responsive Design
- Container Queries
- Pseudo-classes & Pseudo-elements
- Modern Selectors
- CSS Custom Properties
- CSS Functions
- Transitions & Animations
- Transforms
- Forms & Input Styling
- CSS Architecture & Methodologies
- Accessibility in CSS
- Performance & Optimization
- View Transitions & Modern APIs
- Cascade Layers & Scope
Reflow vs Repaint: Two Different Costs
A reflow (also called layout) happens when the browser recalculates the position and size of elements - expensive, and it can cascade to affect many other elements on the page. A repaint happens when visual appearance changes (like a color) without affecting layout - cheaper, but still not free, especially over large areas.
Common Causes of Reflow
- Changing
width,height,margin, orpadding. - Adding or removing an element from the DOM.
- Changing text content, which can alter how much space it needs.
- Reading certain layout properties in JavaScript (like
offsetHeight) immediately after making a style change, which can force a synchronous reflow.
Preferring transform and opacity
/* Triggers reflow on every frame */
.box { left: 100px; }
/* GPU-accelerated, no reflow */
.box { transform: translateX(100px); }As covered in the animation performance note in this project, transform and opacity can typically be changed without triggering a layout recalculation at all, which is why they are the preferred properties for anything that animates frequently.
A JavaScript-Adjacent Tip: Batch Reads and Writes
Repeatedly reading a layout property and then writing a style change, over and over in a loop, can force the browser to recalculate layout on every single iteration instead of once at the end - a pattern sometimes called "layout thrashing." Grouping all reads together, then all writes together, avoids this.
How CSS Containment Helps Here Too
Using contain: layout (covered in the previous note) limits how far a reflow can propagate - a change inside a contained element cannot force the browser to recheck layout for the whole page, only within that isolated boundary.