Chrome and Firefox Repaint Differently When CSS Grid Changes

Oct 20, 2026 By Yusuke Tanaka

A grid track change is not a single kind of event. Chrome's Blink and Firefox's Gecko decide what to repaint from different signals, so the same grid-template-columns edit can cost noticeably different frame time in each. The practical takeaway is narrow: profile the specific property change in both engines rather than trusting the blanket claim that grid edits repaint everything.

The Grid Repaint Assumption

The folklore goes that touching any grid property forces a full repaint of the container and its children. That is roughly true for some changes and plainly false for others. What gets invalidated depends on which internal structures the engine keeps and how finely it can describe what changed.

Blink and Gecko both avoid repainting the whole document for a track resize. They diverge in how much layout work they redo and which paint chunks they discard. A column count change on a small grid tends to land in the same order of magnitude in both. On a large grid with many positioned children, the gap widens.

The assumption survives because it is safe advice. Telling developers that grid changes are expensive discourages animating them, which is usually correct. The cost of the myth is that it hides real optimization work the engines already do, and it hides cases where one engine is meaningfully cheaper than the other.

It also hides the difference between a change that happens once and a change that happens sixty times a second. A single track resize during a breakpoint switch is cheap enough that the engine choice barely registers. The same resize driven by a pointer or a slider is a different problem, because the invalidation cost compounds across frames and any per-frame overhead the engine cannot amortize becomes visible as jank.

Invalidation in Blink and Gecko

Blink's LayoutNG pipeline tracks layout and paint separately. A change to grid track sizing marks the container's layout object dirty, and paint invalidation sets propagate to the affected descendants. Those sets are built per property, so a gap change and a template change can produce different invalidation footprints even though both are grid properties.

Gecko works through its frame tree and keeps display lists that can be reused when only part of a frame changes. A grid track adjustment invalidates the grid frame's layout, and the display list for unaffected children may survive. Reuse depends on whether the child's position and size actually moved, not merely on the parent being marked dirty.

Neither engine publishes a clean public map from CSS property to dirty bit. The behavior is visible in source and in profiling, which is why the practical advice is empirical. A related piece on this site argues that browser rendering work is shifting to platform teams, and this kind of engine-level variance is exactly the sort of thing those teams end up owning.

There is a structural reason for the divergence. Blink's invalidation sets are computed from the layout tree and carry property-specific tags, so the engine can answer the question of which descendants need repainting without walking the whole subtree in many cases. Gecko's display list reuse is a coarser bet: it keeps a retained list per frame and reuses items whose geometry did not change. Coarse reuse is cheap to maintain and forgiving when layout is stable; fine-grained invalidation is more precise when a single child moves but costs more bookkeeping per node. Neither approach dominates, which is why the same page can profile differently on each.

What Actually Triggers Repaint

Changing grid-template-columns from fixed pixels to fractional units resizes every track and forces children to re-layout. Changing grid-gap alone moves children without necessarily changing their intrinsic sizes, which can leave more of the paint work reusable. The two are not interchangeable costs.

Auto-placement is a separate axis. Adding an item that shifts subsequent auto-placed items invalidates the positions of everything downstream of the insertion point. Explicitly placing items on named lines limits the damage to the items whose line assignments changed. On a dense grid, that difference is measurable in frame time.

Subgrid changes the scope again. When a nested grid inherits track sizing from its parent, a parent track change propagates into the subgrid's layout in both engines. Support and implementation details for subgrid still vary, so test the specific nesting pattern rather than assuming parity.

Compositor layers can mask repaint cost entirely. If a grid item is promoted to its own layer, moving it may skip main-thread paint work. That is a real effect and also a trap, because layer promotion has memory and compositing costs that show up elsewhere.

A concrete way to feel the difference: build a grid of a few hundred small cells, each with a border and a background, and animate the column count by one track per frame. In Chrome the paint flashing overlay tends to light up a band along the affected tracks and their children. In Firefox the highlighted region often tracks the moved children more tightly, because the retained display list for unmoved cells survives. The frame numbers you record will vary with hardware and content, but the shape of the invalidation is usually consistent enough to recognize.

Observing the Difference in DevTools

Chrome's paint flashing overlay draws invalidation rectangles over the regions it will repaint. Firefox has a comparable overlay with different rendering and different granularity. Toggling the same class in both and comparing the highlighted area is the fastest way to see the divergence without reading engine source.

Frame timing tells the other half of the story. The paint rectangles show where work happens; the performance panel shows how long it takes. A small invalidation rectangle can still be expensive if it covers a region with heavy shadows or filters, and a large one can be cheap if the content is simple.

Layout shift is the third signal. A grid change that moves content after first paint affects cumulative layout shift regardless of repaint cost. Optimizing repaint while ignoring shift trades one user-visible problem for another. Measure both, and treat them as separate budgets.

Record the same interaction, not two different ones. It is easy to compare a Chrome trace of a hover state against a Firefox trace of a click and draw a wrong conclusion. Script the toggle, or use the same keyboard shortcut in both browsers, and capture a few seconds either side of the change so the steady state is visible alongside the transition.

Practical Implications for Developers

Animating grid-template-columns is the case most likely to disappoint. The interpolation forces layout on every frame in both engines, and the per-frame cost scales with the number of tracks and children. Animating a transform on a child is usually cheaper, though it changes the visual result.

will-change on grid items deserves restraint. It can promote an element and reduce paint work for movement, but it also pins memory and can hurt scrolling on low-end devices. Apply it to the one or two items that actually animate, not to every grid child as a precaution.

Cross-engine testing is not optional here. A change that profiles cleanly in Chrome may produce a wider invalidation region in Firefox, or the reverse. The engines are close enough that most sites never notice, and different enough that an animated dashboard will.

There is a real trade-off between precision and simplicity in how you structure the grid. Named-line placement and explicit track definitions give both engines more to work with, because the layout is more constrained and the engine can reason about which items are affected. Relying on auto-placement everywhere is simpler to write and produces wider invalidation when items shift. The choice is not free either way: explicit placement is more code to maintain, and it can make responsive reflow harder when the number of items changes at runtime.

The objection worth taking seriously: if your grid is small and changes rarely, none of this matters. The overhead of profiling and layer tuning can exceed the frame time you save, and premature optimization here is real. Reserve the effort for grids that animate or resize continuously.

Actions for Cross-Browser Consistency

Profile the exact property change in both Chrome and Firefox before shipping an animated grid. Use the paint flashing overlay and the performance panel together, and record the same interaction in each browser.

Avoid animating grid-template-columns and grid-template-rows for anything that runs continuously. If a layout must move smoothly, animate a transform on a wrapper and keep the grid structure static.

Isolate repaint-heavy grid items into their own stacking context so invalidation does not spread to siblings. A positioned wrapper with a transform does this without touching the grid definition itself.

Report engine-specific invalidation bugs with a minimal test case and a screen recording of the overlay. A reduced page with one grid and one toggled class is far more actionable than a link to a full application, and this site has argued before that long-lived build and rendering code is where these fixes tend to accumulate.

Keep a small harness page per project that toggles the grid properties you actually animate, and run it after major browser updates. Engines change invalidation behavior between releases, and a harness catches the regression before users do.

Finally, write down what you measured. A short note in the repo recording the browser versions, the grid shape, and the frame times turns a one-off profiling session into something the next person can compare against. Invalidation behavior is not a fixed contract, and the only defense against silent regressions is a baseline you can re-run.

Recommend Posts
Tech

Anycast Routing and DNS Steering Diverge Under Load

By Sara Park/Oct 20, 2026

Anycast and DNS steering both promise proximity, but they diverge under load. A craft breakdown of where each fails and how to instrument both planes.
Tech

Maintainer Burnout Rises While Tooling Metrics Stay Green

By Sara Park/Oct 20, 2026

CI dashboards keep reporting green while the people behind the tooling run out of capacity. A look at why build metrics miss maintainer burnout and what to track instead.
Tech

Retry Budgets Decide Which Microservice Failures Become Outages

By Yusuke Tanaka/Oct 20, 2026

Retry budgets cap the ratio of retries to original requests, stopping retry storms from turning a slow dependency into a full outage. How Envoy, Istio, gRPC, and Finagle implement them, what the trade-off costs in user-visible errors, and how to pick a budget without guesswork.
Tech

Open Source Maintainers Trade Salary for Ownership in Hiring Deals

By Sara Park/Oct 20, 2026

Open-source maintainers increasingly negotiate governance authority and equity instead of top salary. What that trade costs, and how to structure the deal before signing.
Tech

Open Source Licenses and Cloud Vendor Contracts Diverge on Support Revenue

By Deepa Iyer/Oct 20, 2026

Open-source licenses grant rights, not revenue. The money lives in cloud support contracts, indemnity terms, and renewal pricing. Here is where the margin actually sits.
Tech

Testing Push Notification Delivery on Android Before Trusting Analytics

By Sara Park/Oct 20, 2026

Analytics dashboards count sends, not deliveries. Here is how Android push actually moves through FCM, Doze, and OEM layers, and how to instrument the real path.
Tech

Mutual TLS Deployment Stalls Where Certificate Rotation Lacks Automation

By Yusuke Tanaka/Oct 20, 2026

Mutual TLS demos cleanly but stalls at renewal. A practical look at what mTLS changes on the wire, where manual rotation breaks, and automation patterns that survive.
Tech

Developer Tooling Careers Trade Depth for Breadth in Hiring

By Lucas Mendes/Oct 20, 2026

Developer tooling careers reward breadth in hiring loops, but depth in package managers, build systems, and CI pays off long-term. How specialists can bridge the gap.
Tech

Why Token Rotation Logs Miss the Sessions Attackers Keep

By Lucas Mendes/Oct 20, 2026

Token rotation logs report success while stolen sessions stay live. A payments team post-mortem shows why session state escapes audit and how to close the gap.
Tech

Maintainer Contracts Rarely Cover the On-Call Hours Behind a Security Fix

By Lucas Mendes/Oct 20, 2026

Security fixes ship on time, but the unpaid on-call hours behind them rarely appear in maintainer contracts. A breakdown of who bears the cost and how to fix it.
Tech

Editors and Package Managers Split Over Who Pays for CI Minutes

By Lucas Mendes/Oct 20, 2026

CI minutes have become a real budget line. Editors, package managers and platforms disagree about who absorbs the cost, and the contracts decide the winner.
Tech

Nvidia's Driver Stack Carries the Correctness Burden Its Hardware Cannot

By Deepa Iyer/Oct 20, 2026

Nvidia's GPUs do not guarantee correct math on their own. The driver and CUDA runtime carry that promise, and the burden is shifting toward users.
Tech

Postgres Wire Protocol Changes and the Client Libraries That Must Track Them

By Lucas Mendes/Oct 20, 2026

How Postgres client libraries track wire protocol changes, where message parsing breaks, and the testing practices that keep drivers compatible across server versions.
Tech

Postgres Replication Slots Hold WAL Until Disk Fills

By Yusuke Tanaka/Oct 20, 2026

Replication slots pin WAL segments indefinitely, filling disk and halting writes. Learn how slots retain WAL, the signals to watch, and the settings that cap the damage.
Tech

Chrome and Firefox Repaint Differently When CSS Grid Changes

By Yusuke Tanaka/Oct 20, 2026

Chrome and Firefox invalidate and repaint CSS Grid changes differently. A look at Blink's invalidation sets, Gecko's display lists, and how to profile both.
Tech

Machine-Learning Teams Rewrite Their Deployment Playbooks as Inference Standards Shift

By Yusuke Tanaka/Oct 20, 2026

Serving engines like vLLM and TensorRT-LLM now define wire behavior. What changes for ML teams at the API level, in on-call rotations, and in hiring loops.
Tech

Open Source Foundations Fund Compliance Work From Trademark Royalties

By Sara Park/Oct 20, 2026

Open source foundations increasingly fund license compliance work through trademark royalties from certification marks, creating a business model with real governance tensions.
Tech

Android Fragmentation Forces Cross-Platform Stacks Into Per-Device Testing

By Sara Park/Oct 20, 2026

Android fragmentation turns one cross-platform codebase into hundreds of test targets. A practical breakdown of device tiering, snapshot matrices, and hardening the mobile pipeline.
Tech

Check Which Maintainers Hold Signing Keys Before Your Next Update

By Yusuke Tanaka/Oct 20, 2026

Code signing only proves what a key says. Here is how to check which maintainers actually hold signing keys, where those keys live, and what to fix this quarter.
Tech

Certificate Pinning Breaks Silently When Rotation Runs Behind Revocation

By Deepa Iyer/Oct 20, 2026

Certificate pinning fails quietly when revocation outruns rotation. A practical breakdown of pin sets, overlap windows, revocation drills and handshake telemetry.