Skip to main content
Guides Skills and frameworks Browser Rendering Interview Guide — CRP, Repaint vs Reflow, and Performance Metrics
Skills and frameworks

Browser Rendering Interview Guide — CRP, Repaint vs Reflow, and Performance Metrics

9 min read · April 25, 2026

A browser rendering interview guide covering the critical rendering path, DOM/CSSOM, repaint vs reflow, compositing, Core Web Vitals, DevTools, and practical performance fixes.

Browser Rendering Interview Guide — CRP, Repaint vs Reflow, and Performance Metrics

This browser rendering interview guide explains the critical rendering path, repaint vs reflow, compositing, and the performance metrics frontend interviewers expect you to know. Strong candidates can trace how HTML, CSS, JavaScript, images, fonts, and layout work become pixels on screen. Even stronger candidates can connect that pipeline to real fixes: reducing render-blocking work, avoiding layout thrash, improving LCP, lowering INP, and preventing CLS.

Browser rendering interview guide: the pipeline in one pass

When a browser loads a page, it roughly performs these steps:

  1. Parse HTML into the DOM.
  2. Parse CSS into the CSSOM.
  3. Combine DOM and CSSOM into a render tree.
  4. Compute layout: size and position of boxes.
  5. Paint pixels for text, colors, borders, shadows, and images.
  6. Composite layers onto the screen.

JavaScript can interrupt this pipeline because scripts may read or change the DOM and CSSOM. CSS can block rendering because the browser needs styles before it knows how to paint. Fonts and images can affect layout and perceived loading. Modern browsers optimize aggressively, but the mental model still matters.

A crisp interview opening: “The critical rendering path is the sequence from HTML, CSS, and JS to pixels. Performance improves when we reduce blocking resources, minimize layout and paint work, and keep interaction handlers from blocking the main thread.”

Critical rendering path: what blocks first paint

The critical rendering path, or CRP, is the set of resources and work required to render initial pixels. HTML parsing builds the DOM incrementally. CSS is render-blocking by default because the browser needs the CSSOM to compute styles. Synchronous JavaScript can block parsing, and if the script reads styles, it may force the browser to finish CSS work first.

Common CRP optimizations:

  • inline truly critical CSS for above-the-fold content
  • defer non-critical JavaScript with defer or load it after interaction
  • avoid large blocking CSS bundles
  • split route-level JavaScript for single-page apps
  • preload important fonts or hero images when appropriate
  • set image dimensions to avoid layout shift
  • reduce third-party scripts that block the main thread

Do not say “always inline all CSS” or “always lazy-load everything.” Critical CSS helps first render, but too much inline CSS bloats HTML. Lazy-loading hero images can hurt LCP. The best answer is conditional: optimize the resources needed for the first meaningful view, defer the rest.

DOM, CSSOM, and render tree

The DOM represents document structure. The CSSOM represents parsed styles. The render tree contains visible nodes with computed styles. Elements with display: none are not in the render tree. Elements with visibility: hidden take space but are not visible. Pseudo-elements and text nodes can appear in render output even if they are not DOM elements in the same way.

Interviewers may ask what happens when CSS arrives late. The browser delays rendering until it has enough CSS to avoid flashing unstyled content. That is why CSS is render-blocking. JavaScript complicates this because scripts can query computed styles or mutate DOM while parsing.

A good debugging mindset: if the page is blank for too long, inspect blocking CSS, synchronous scripts, server response time, font loading, and hydration cost. Rendering problems are often resource-order problems, not just “React is slow.”

Reflow versus repaint versus composite

This is the classic browser rendering interview topic.

| Operation | What changes | Relative cost | |---|---|---| | Reflow/layout | geometry: width, height, position, font size, DOM structure | Usually most expensive | | Repaint | pixels: color, background, shadow, visibility | Medium | | Composite | layer transform/opacity combined by compositor | Often cheapest |

A reflow recalculates layout. It happens when changes affect element size or position: adding DOM nodes, changing width, changing font, resizing window, or reading layout after writes. A repaint redraws pixels without changing layout, such as changing color. Compositing combines layers, often allowing transforms and opacity changes to be animated without repainting every frame.

Good animation rule: prefer transform and opacity for smooth animations. Avoid animating top, left, width, or height when possible because they trigger layout.

But avoid absolutism. Promoting too many elements to layers can increase memory and hurt performance. will-change should be used sparingly and removed when no longer needed.

Layout thrashing: the bug behind many janky pages

Layout thrashing happens when code repeatedly writes to the DOM and then reads layout, forcing the browser to recalculate styles and layout synchronously.

Bad pattern:

items.forEach(item => {
  item.style.width = container.offsetWidth / 3 + "px";
});

If offsetWidth forces layout inside a loop after writes, the browser may recalculate repeatedly. Better: read once, then write in a batch.

const width = container.offsetWidth / 3;
items.forEach(item => {
  item.style.width = `${width}px`;
});

Use requestAnimationFrame to schedule visual updates and separate reads from writes. Libraries and frameworks help, but they cannot save code that forces layout at the wrong time.

Mention layout-triggering reads such as offsetWidth, offsetHeight, getBoundingClientRect, scrollTop, and getComputedStyle. The exact list changes by browser, but the principle is stable: reading layout after writes can force the browser to flush pending work.

Main thread, compositor thread, and why JavaScript jank matters

The main thread handles JavaScript, style calculation, layout, and much painting work. If JavaScript runs for too long, the browser cannot respond quickly to input or render new frames. At 60 frames per second, each frame has about 16.7 ms, and not all of that is available to your code.

The compositor can handle some work, especially transforms and opacity on separate layers, without blocking on full layout. That is why moving an element with transform: translateX() is usually smoother than changing left.

Performance interviews often test whether you understand that JavaScript optimization is rendering optimization. A large hydration task, expensive event handler, or JSON parsing burst can make the UI feel frozen even if CSS is perfect.

Performance metrics: LCP, CLS, INP, TTFB, and FCP

Modern frontend interviews often reference Core Web Vitals and related metrics.

| Metric | Meaning | Common fixes | |---|---|---| | LCP | Largest Contentful Paint: when main content appears | optimize server time, hero image, render-blocking CSS/JS, font loading | | CLS | Cumulative Layout Shift: visual instability | reserve space, set image dimensions, avoid late banners, manage fonts | | INP | Interaction to Next Paint: responsiveness | reduce long tasks, optimize handlers, defer work, break up JS | | FCP | First Contentful Paint: first text/image painted | reduce blocking resources, improve TTFB | | TTFB | Time to First Byte | server, CDN, caching, backend latency |

Be precise: LCP is not always the hero image, but it often is. CLS is not caused by every movement; it measures unexpected layout shifts. INP replaced FID as the broader interaction responsiveness metric because it considers more interactions, not only the first.

A senior answer connects metrics to diagnosis. Poor LCP could be server latency, render-blocking CSS, client hydration, a late-discovered hero image, or font behavior. Poor INP often means main-thread long tasks or heavy event handlers. Poor CLS often means missing dimensions, late injected content, or font swaps.

Images, fonts, and third-party scripts

Images affect LCP, bandwidth, memory, and layout. Use responsive images, correct sizing, modern formats when supported, and explicit width and height or aspect-ratio boxes. Lazy-load below-the-fold images, but do not lazy-load the LCP image.

Fonts can block or shift text. Use sensible font-display, preload critical fonts only when truly needed, subset fonts, and avoid loading many weights. A font swap can improve visibility but may cause layout shift if fallback metrics differ.

Third-party scripts are a frequent hidden cost: analytics, ads, chat widgets, tag managers, A/B testing, and heatmaps. They can block parsing, add long tasks, mutate layout, and compete for bandwidth. In an interview, say you would measure third-party cost rather than blindly blame your app bundle.

DevTools debugging flow

A practical rendering answer includes tools:

  1. Use Lighthouse or PageSpeed Insights for a high-level metric snapshot.
  2. Use the Performance panel to record loading or interaction.
  3. Look for long tasks, layout events, style recalculation, paint cost, and main-thread blocking.
  4. Use the Network panel to inspect blocking resources, priority, compression, caching, and image discovery.
  5. Use the Coverage panel to find unused CSS/JS.
  6. Use the Rendering panel to highlight paint flashing or layout shifts.

If the prompt is “the page feels slow,” ask whether slow means load, scroll, animation, input, or route transition. Different symptoms point to different parts of the rendering pipeline.

Common interview traps

The most common trap is mixing up repaint and reflow. Reflow changes geometry; repaint changes pixels; compositing combines layers.

Other traps:

  • saying CSS never blocks rendering
  • lazy-loading the hero image and hurting LCP
  • using average input latency instead of worst interactions
  • overusing will-change and creating too many layers
  • ignoring font-induced layout shift
  • blaming the framework before profiling
  • forgetting mobile CPU constraints
  • treating Lighthouse score as the goal rather than user experience
  • optimizing bundle size while leaving long tasks in interaction handlers

A strong debugging answer starts with measurement. “I would profile the slow interaction, identify whether time is spent in scripting, style, layout, paint, or network, then target the bottleneck.” That beats a random list of tips.

Example interview answer: slow product page

Prompt: “A product page has poor LCP and janky image carousel interactions. What do you do?”

Answer structure:

“First I would profile on a representative mobile device. For LCP, I would identify the LCP element and check TTFB, CSS/JS blocking, image priority, image size, and whether the hero image is discovered late by JavaScript. I would preload or prioritize the hero image if appropriate, serve responsive dimensions, and avoid lazy-loading it. For carousel jank, I would record an interaction trace and look for long tasks, layout thrashing, and animations using layout properties. I would move animations to transform/opacity where possible, batch DOM reads and writes, and reduce handler work. I would verify improvements using LCP and INP, with CLS as a guardrail.”

That answer ties symptoms to pipeline and metrics.

Resume and interview language

Good frontend performance bullets are specific:

  • “Reduced LCP from 4.1s to 2.3s by prioritizing hero image discovery, splitting render-blocking JS, and trimming critical CSS.”
  • “Fixed layout thrashing in a virtualized table by batching DOM reads/writes, cutting scroll long tasks by 45%.”
  • “Lowered CLS by reserving media aspect ratios and replacing late-injected banners with stable slots.”

Avoid vague bullets like “Optimized website performance.” Name the metric, bottleneck, fix, and result.

Prep checklist

Before a browser rendering interview, be ready to draw the critical rendering path and define DOM, CSSOM, render tree, layout, paint, and composite. Practice explaining repaint versus reflow with examples. Know why transform and opacity animate better. Understand LCP, CLS, INP, FCP, and TTFB. Be able to describe a DevTools profiling flow. The winning answer is not a memorized list of micro-optimizations; it is a clear map from browser work to user-visible performance.