Front end developer interviews test browser mechanics, UI architecture, and performance—not only whether you can scaffold a todo app. Expect depth on how JavaScript runs in the browser, React patterns, CSS layout, accessibility, Core Web Vitals, and live UI exercises such as autocomplete, infinite scroll, or modal dialogs.
Below are 42 questions from HTML and CSS through JavaScript, React, and senior UI engineering topics. Answer each one out loud before expanding the collapsed response. For computer networks interview questions (HTTP, DNS, TLS, TCP), see computer networks interview questions. For dedicated CSS interview questions and html and css interview questions depth (box model, specificity, flexbox, grid, modern CSS), see CSS interview questions. For TypeScript interview questions (generics, utility types, narrowing, satisfies), see TypeScript interview questions. For basic React JS interview questions, see React interview questions and answers. For interview questions on React JS for experienced and scenario-based senior prep, see React JS interview questions for experienced developers. For Angular-specific depth (signals, RxJS, standalone components), see Angular developer interview questions. For Selenium UI automation (locators, waits, DOM timing), see Selenium interview questions. For API design and full-stack integration, see full stack developer interview questions.
Interview context and how to prepare
What do front end developer interviews actually test?
Front end interviews test whether you can build user interfaces that are correct, usable, accessible, performant, and maintainable.
| Level | What interviewers focus on |
|---|---|
| Junior | HTML semantics, CSS basics, JavaScript fundamentals, DOM APIs, simple React components |
| Mid-level | Hooks, state management, forms, accessibility, debugging, API integration, CSS architecture |
| Senior | UI architecture, performance, Core Web Vitals, design systems, trade-offs, testing strategy, cross-team decisions |
Common areas tested:
- HTML/CSS fundamentals — semantic HTML, box model, flexbox, grid, responsive design
- JavaScript — closures, promises, async/await, event loop, scope, equality, DOM events
- Framework skills — React hooks, component design, rendering behavior, state flow
- UI quality — accessibility, keyboard navigation, loading/error states, edge cases
- Performance — LCP, INP, CLS, bundle size, lazy loading, rendering cost
- Communication — explaining trade-offs and debugging approach clearly
In modern front end interviews, many companies also include machine coding rounds where you build a component or small UI in 45–60 minutes. Examples include autocomplete, tabs, modal, accordion, pagination, infinite scroll, or a small dashboard widget.
DSA basics can still appear in screens, but front end interviews usually care more about practical UI implementation than pure algorithm trivia.
What formats should you expect?
A typical front end developer interview process has 3–5 rounds, depending on company size and seniority.
| Round | What it tests |
|---|---|
| Online assessment | JavaScript fundamentals, small UI tasks, basic logic |
| Technical interview | HTML, CSS, JavaScript, React, browser behavior |
| Live coding / machine coding | Build a component or widget from scratch |
| Front-end system design | Senior-level UI architecture and trade-offs |
| Behavioral round | Collaboration, ownership, debugging, design handoff |
Common machine-coding prompts:
- Autocomplete search box
- Tabs component
- Modal dialog
- Todo list with filters
- Infinite scroll feed
- Data table with sorting/filtering
- Star rating component
- Image carousel
For senior roles, expect architecture questions such as:
- Design a Twitter-like feed
- Design a component library
- Design a dashboard with real-time updates
- Design a design system for multiple teams
- Design an analytics-heavy web app
A strong candidate does not only make the UI work. They also discuss accessibility, loading states, error states, performance, testing, and maintainability.
What is a realistic 4–5 week prep plan?
A realistic front end prep plan should balance fundamentals, React, UI coding, accessibility, and performance.
| Week | Focus | Output |
|---|---|---|
| 1 | HTML semantics, CSS box model, flexbox, grid, responsive layouts | Rebuild 2–3 common layouts |
| 2 | JavaScript fundamentals — closures, promises, event loop, equality, classes | Solve small JS logic and DOM tasks |
| 3 | React hooks, state, props, forms, effects, component composition | Build one medium React component |
| 4 | Accessibility, performance, Core Web Vitals, testing basics | Improve one UI for keyboard, screen reader, and speed |
| 5 | Machine coding + mock interviews + portfolio walkthrough | Complete 3–5 timed UI drills |
Further reading:
The highest-ROI practice is to build one polished UI that is responsive, accessible, tested, and handles loading/error/empty states.
That is a stronger interview signal than memorizing many isolated questions.
What React 19 topics appear in modern front end interviews?
For modern front end interviews, prepare both React fundamentals and modern React 19+ patterns.
Topics worth knowing:
| Topic | What to understand |
|---|---|
| Actions | Handling async mutations and form submissions more cleanly |
| useActionState | Managing state produced by an action |
| useOptimistic | Showing optimistic UI before a server update completes |
| use() | Reading promises or resources in render, mainly in supported patterns |
| Server Components | Rendering parts of the UI on the server to reduce client-side JavaScript |
| useTransition | Marking non-urgent updates so the UI stays responsive |
| useDeferredValue | Deferring expensive updates from fast-changing input |
| React Compiler | Automatic memoization that can reduce manual useMemo, useCallback, and memo usage |
Important clarification:
React Compiler is better described as a modern React optimization tool, not just a normal React 19 hook. Do not say it removes the need to understand rendering. You still need to know when components re-render, how state changes flow, and how effects behave.
Interviewers still expect strong fundamentals:
useStateuseEffectuseMemouseCallbackuseRef- controlled vs uncontrolled components
- keys and reconciliation
- prop drilling vs context
- component composition
Front end vs full stack interview — what is different?
Front end and full stack interviews overlap, but the depth is different.
| Area | Front end interview | Full stack interview |
|---|---|---|
| UI implementation | Deep | Moderate |
| HTML/CSS | Deep | Basic to moderate |
| Browser rendering | Deep | Moderate |
| React/component design | Deep | Moderate |
| Accessibility | Important | Sometimes lighter |
| Performance | LCP, INP, CLS, bundle size, rendering | API latency, database, caching |
| Backend/API design | Basic to moderate | Deep |
| SQL/databases | Usually lighter | More important |
| Deployment | Front-end build/CDN basics | Full app deployment |
Front end loops go deeper on:
- Browser rendering and paint
- CSS specificity and layout systems
- Component API design
- Design systems
- Accessibility
- Responsive behavior
- Client-side performance
- State management trade-offs
Full stack loops spend more time on APIs, databases, authentication, backend architecture, and deployment.
See full stack guide for that path.
HTML and semantic markup
Why does semantic HTML matter in interviews?
Semantic HTML means using the right element for the job instead of using div and span everywhere.
Examples:
| Use case | Prefer | Avoid |
|---|---|---|
| Page header | header |
Generic div |
| Main content | main |
Generic div |
| Navigation | nav |
Generic div |
| Article/card content | article or section |
Generic div |
| Click action | button |
Clickable div |
Why it matters:
- Accessibility — landmarks and native controls help screen readers and keyboard users.
- SEO and structure — crawlers can better understand page hierarchy and content areas.
- Maintainability — the markup explains intent to other developers.
- Less JavaScript — native elements already support many expected behaviors.
A common interview task is to refactor a “div-soup” login form into semantic, accessible markup.
A strong answer is:
I use semantic HTML first because it gives accessibility and browser behavior for free. ARIA should enhance semantics, not replace the correct HTML element.
What belongs in document head for performance and SEO?
The document head contains metadata and resource hints that help browsers, search engines, and social platforms understand the page.
Important items:
<title>— unique page title- Meta description — short search-result summary
- Viewport meta — responsive layout on mobile
- Canonical URL — preferred version of the page
- Open Graph / social tags — better sharing previews
- Favicon and app icons
- Preload for critical resources such as hero image, critical font, or key CSS
- Preconnect for important third-party origins such as CDN, fonts, or API domains
For performance, connect this to LCP. If the hero image or main heading font is discovered late, the page may render slowly.
Be careful:
- Do not preload too many resources.
- Use
preconnectonly for important origins. - Make sure canonical URLs are correct.
- Avoid blocking critical rendering with unnecessary scripts.
A strong interview answer is:
I use the head for metadata, responsive behavior, canonical/social tags, and carefully chosen resource hints. For performance, I prioritize early discovery of LCP resources without over-preloading.
How do you build an accessible form?
An accessible form should be usable with a keyboard, screen reader, and clear visual feedback.
Key practices:
- Pair every input with a visible
<label> - Use
forandidto connect labels to inputs - Do not use placeholder text as the only label
- Use
aria-describedbyfor help text and error messages - Show visible focus styles with
:focus-visible - Keep tab order logical
- Mark required fields clearly
- Announce validation errors with
role="alert"or a live region when needed - Use the right input type, such as
email,tel,number, orpassword
Common mistake:
“Placeholder text disappears when users type and may not work well as an accessible label.”
A strong answer is:
I start with native form controls and visible labels, then connect helper text and errors using
aria-describedby. I also test keyboard navigation and error announcement.
CSS layout and architecture
Explain the CSS box model and box-sizing.
The CSS box model describes how an element’s size is calculated.
From inside to outside:
- Content
- Padding
- Border
- Margin
By default, width applies only to the content box. That means padding and border are added on top of the declared width.
box-sizing: border-box makes layout easier because the declared width includes content, padding, and border.
Example interview explanation:
“Without
border-box, an element withwidth: 100%plus padding can overflow its container. Withborder-box, the padding is included inside the 100% width.”
This is why many projects apply box-sizing: border-box globally.
Flexbox vs CSS Grid — when do you use each?
Use Flexbox for one-dimensional layouts and CSS Grid for two-dimensional layouts.
| Layout need | Better choice |
|---|---|
| Navbar items in a row | Flexbox |
| Centering content | Flexbox |
| Button group | Flexbox |
| Page shell with sidebar and content | Grid |
| Dashboard cards in rows and columns | Grid |
| Complex responsive layout | Grid |
A practical rule:
- Use Grid for the page or section layout.
- Use Flexbox inside components.
A strong answer is:
Flexbox is best when I mainly care about flow in one direction. Grid is best when I need control over rows and columns together.
How does CSS specificity work?
CSS specificity decides which rule wins when multiple rules target the same element.
Basic order from lower to higher priority:
- Element selector
- Class, attribute, and pseudo-class selectors
- ID selector
- Inline style
!important
But specificity is not the only factor. The browser also considers:
- Cascade layer
- Origin
- Importance
- Specificity
- Source order
Common interview debugging question:
“Why does my utility class not override component CSS?”
Things to check:
- Is the component selector more specific?
- Does the rule appear later in the stylesheet?
- Is
!importantinvolved? - Is the rule inside a lower-priority
@layer? - Is inline style overriding it?
Modern CSS can use @layer to organize styles such as reset, base, components, and utilities. This helps large codebases and design systems avoid specificity wars.
A strong answer is:
I debug CSS conflicts by checking cascade order, specificity, source order, and layers before adding
!important.
How do you approach responsive design?
I approach responsive design by making layouts flexible first, then adding breakpoints only where the design actually needs them.
Good practices:
- Start mobile-first
- Use relative units where appropriate
- Use Flexbox and Grid for fluid layouts
- Use
clamp()for fluid typography - Use responsive images with
srcsetandsizes - Use container queries when a component should respond to parent width
- Test keyboard and touch behavior across screen sizes
- Avoid fixed heights that break with longer content
Media queries respond to the viewport. Container queries respond to the size or state of a parent container, which is useful for reusable components.
Senior-level discussion:
| Topic | Trade-off |
|---|---|
| Tailwind | Fast utility workflow, but class-heavy markup |
| CSS Modules | Scoped styles, but less design-token structure by default |
| Design tokens | Consistency across teams, but need governance |
| Component library | Reuse and consistency, but can slow custom UI work |
A strong answer is:
I prefer fluid layouts and mobile-first CSS, then use media or container queries where the component actually needs a layout change.
What CSS choices hurt performance?
CSS performance issues usually come from layout shifts, heavy rendering work, unused styles, or JavaScript forcing repeated layout calculations.
Common problems:
- Large unused CSS shipped to the browser
- Animating layout properties such as
width,height,top, orleft - Not reserving space for images, ads, or dynamic content
- Loading blocking CSS late or inefficiently
- Excessive style recalculation in very large pages
- JavaScript layout thrashing from repeated DOM reads and writes
Better choices:
- Animate
transformandopacitywhen possible - Reserve image and ad space to reduce CLS
- Remove or split unused CSS
- Keep critical CSS small
- Batch DOM reads and writes
- Avoid unnecessary deep selector complexity in large apps
A strong answer is:
For CSS performance, I focus on reducing unused CSS, avoiding layout shifts, and using compositor-friendly animations such as
transformandopacity.
JavaScript in the browser
How does the browser JavaScript event loop work?
The browser JavaScript event loop coordinates synchronous code, async callbacks, rendering, and user interactions.
A simple explanation:
- Synchronous code runs on the call stack.
- Browser APIs handle async work such as timers, events, and network requests.
- Completed async work is queued as a task or microtask.
- Microtasks run before the browser moves to the next task.
- The browser gets chances to render between event loop turns.
Common examples:
| Source | Queue type |
|---|---|
setTimeout() |
Task / macrotask |
| DOM event callback | Task / macrotask |
Promise.then() |
Microtask |
queueMicrotask() |
Microtask |
That is why Promise.then() usually runs before setTimeout(..., 0).
In front end interviews, the key point is that JavaScript runs on the main thread. Long synchronous work can block rendering and user input.
A strong answer is:
The call stack runs sync code first. Promise callbacks go to the microtask queue, which drains before the next task. For UI work, I avoid blocking the main thread because it hurts responsiveness.
What is a closure and why do interviewers ask?
A closure is when a function remembers variables from its outer scope even after the outer function has finished running.
Closures are common in front end code because event handlers, callbacks, and utility functions often need to remember state.
Common uses:
- Event handlers
- Debounce and throttle functions
- Private state
- Module pattern
- Function factories
- React hooks and callbacks
Classic interview example:
A loop using var may cause every callback to share the same variable. Using let creates a new block-scoped variable for each loop iteration.
Interviewers ask closures because they test whether you understand scope, async callbacks, and state.
A strong answer is:
A closure lets an inner function keep access to variables from its outer scope. It is useful for callbacks, event handlers, and utilities like debounce.
Explain prototypal inheritance in JavaScript.
JavaScript uses prototypal inheritance. Objects can delegate property lookup to another object through their prototype chain.
If a property is not found on the object itself, JavaScript looks up the prototype chain until it finds the property or reaches null.
Important points:
- Every normal object has an internal prototype link.
Object.create()can create an object with a chosen prototype.instanceofchecks whether a constructor’s prototype appears in an object’s prototype chain.classsyntax is mostly cleaner syntax over JavaScript’s prototype-based model.
Example interview explanation:
“In JavaScript, inheritance is based on objects delegating to other objects. Classes make the syntax familiar, but under the hood objects still use prototypes.”
See javascript instanceof for related checks.
How does this behave in JavaScript?
In JavaScript, this depends mainly on how a function is called, not where it is written.
Common rules:
| Call style | this value |
|---|---|
| Method call | Object before the dot |
Constructor with new |
Newly created object |
call, apply, bind |
Explicitly provided value |
| Arrow function | Lexical this from surrounding scope |
| Standalone function | undefined in strict mode, otherwise global object |
Common mistakes:
- Passing an object method as a callback and losing
this - Expecting arrow functions to have their own
this - Mixing class methods and event handlers without binding
A strong answer is:
For normal functions,
thisis decided by the call site. Arrow functions do not create their ownthis; they capture it from the surrounding scope.
Explain event bubbling, capturing, and delegation.
Browser events move through three phases:
- Capturing phase — event travels from the document down toward the target.
- Target phase — event reaches the actual target element.
- Bubbling phase — event bubbles back up through ancestors.
stopPropagation() stops the event from continuing through the propagation path.
Event delegation means attaching one listener to a parent and handling events from child elements using event.target.
This is useful for:
- Large lists
- Dynamic items added later
- Reducing many repeated event listeners
list.addEventListener("click", (event) => {
const item = event.target.closest("[data-id]");
if (!item || !list.contains(item)) {
return;
}
handleSelect(item.dataset.id);
});The list.contains(item) check avoids accidentally handling a matching element outside the intended parent.
A strong answer is:
Events capture down, reach the target, then bubble up. Delegation uses bubbling so a parent can handle child events efficiently.
How do you fetch data and handle errors in the browser?
I would use fetch() with async/await, but I would handle more than just the happy path.
Important points:
- Show a loading state while the request is pending.
- Check
response.okbecause HTTP errors like 404 or 500 do not automatically reject the fetch promise. - Catch network errors.
- Handle empty states separately from error states.
- Use
AbortControllerto cancel stale requests when users navigate, type quickly, or change filters. - Avoid updating UI from an old response after a newer request finishes first.
Example structure:
const controller = new AbortController();
try {
const response = await fetch("/api/products", {
signal: controller.signal,
});
if (!response.ok) {
throw new Error("Request failed");
}
const data = await response.json();
renderProducts(data);
} catch (error) {
if (error.name !== "AbortError") {
renderError();
}
}A strong interview answer is:
I handle loading, success, empty, and error states. I also check
response.okand useAbortControllerto avoid race conditions from stale requests.
Implement debounce vs throttle — common live-coding ask.
Debounce and throttle both limit how often a function runs, but they solve different problems.
| Technique | Meaning | Common use |
|---|---|---|
| Debounce | Run after the user stops triggering events | Search input, autocomplete, resize end |
| Throttle | Run at most once per interval | Scroll handler, mousemove, resize progress |
Debounce example:
function debounce(fn, delay) {
let timerId;
return (...args) => {
clearTimeout(timerId);
timerId = setTimeout(() => {
fn(...args);
}, delay);
};
}In interviews, also explain the trade-off:
- Debounce reduces unnecessary work after rapid input.
- Throttle keeps updates happening at a controlled rate.
- Both can help reduce main-thread work and improve responsiveness.
- They do not fix expensive rendering by themselves; you still need to optimize the actual work.
A strong answer is:
I use debounce when I only care about the final value after the user pauses. I use throttle when I need regular updates but want to limit frequency.
React and modern UI libraries
What is the virtual DOM and reconciliation?
The virtual DOM is React’s in-memory representation of the UI.
When state or props change, React creates a new UI tree, compares it with the previous tree, and decides what needs to change in the real DOM. This process is called reconciliation.
Important points:
- React updates the DOM efficiently, but not magically for free.
- Stable component structure and stable keys help reconciliation.
- Expensive renders can still hurt performance if components do too much work.
- Modern React can prioritize urgent updates, such as typing or clicking, over less urgent UI work.
A strong interview answer is:
React uses reconciliation to compare the previous and next UI trees and update the browser DOM efficiently. But performance still depends on good state design, stable keys, and avoiding unnecessary expensive renders.
What are the rules of hooks?
React hooks have two main rules:
- Call hooks only at the top level of a component or custom hook.
- Call hooks only from React function components or custom hooks.
Do not call hooks inside:
- Conditions
- Loops
- Nested functions
- Event handlers
- Plain JavaScript functions
Why this matters:
React tracks hook state by call order. If hooks run in a different order between renders, React cannot correctly match state to each hook.
A strong answer is:
Hooks must run in the same order on every render. That is why we call them at the top level and not inside conditions or loops.
What are common useEffect mistakes?
Common useEffect mistakes include:
- Missing dependencies, causing stale values
- Adding unnecessary dependencies, causing repeated effects
- No cleanup for timers, subscriptions, or event listeners
- Fetching data without aborting stale requests
- Using effects for derived state that could be calculated during render
- Putting too much business logic inside effects
For data fetching, modern React interviews often expect this distinction:
| State type | Better tool |
|---|---|
| Local UI state | useState, useReducer |
| Server/cache state | React Query, SWR, framework loader, or server-side data fetching |
A strong answer is:
I use
useEffectfor synchronizing with external systems, not for every calculation. For server state, I prefer a data-fetching library or framework pattern that handles caching, refetching, and stale requests.
When do you use Context, Redux, Zustand, or React Query?
State management depends on what kind of state you are managing.
| Tool | Best for |
|---|---|
| useState | Simple local component state |
| useReducer | Complex local state transitions |
| Context | Low-frequency global values such as theme, locale, auth user |
| Zustand | Lightweight shared client state |
| Redux Toolkit | Large apps with complex shared state, strict patterns, debugging needs |
| React Query / SWR | Server state: cache, refetch, dedupe, loading/error states |
Important distinction:
- Client state lives in the browser and is controlled by the UI.
- Server state comes from APIs and needs caching, refetching, invalidation, and synchronization.
A strong answer is:
I do not put everything into global state. I keep state local when possible, use Context for low-frequency global values, use a client-state library when state is complex, and use React Query or SWR for server state.
When should you use React.memo, useMemo, and useCallback?
Use memoization when profiling shows avoidable re-renders or expensive calculations.
| Tool | Use case |
|---|---|
| React.memo | Skip re-rendering a component when props are unchanged |
| useMemo | Cache an expensive calculated value |
| useCallback | Keep a function reference stable when passing it to memoized children |
Do not memoize everything by default.
Problems with over-memoization:
- More complex code
- Harder debugging
- Extra memory usage
- Little or no benefit if the component is cheap
Modern React tooling, including React Compiler, can reduce the need for manual memoization in supported setups. But candidates should still understand rendering, props, state, and expensive work.
A strong answer is:
I profile first. I use memoization when a component is expensive, props are stable, or a callback causes unnecessary child renders. Memoization is not my default starting point.
What are React Server Components (RSC)?
React Server Components are components that render on the server or during build, instead of running in the browser.
Key points:
- They can fetch server-side data directly.
- Their component JavaScript is not shipped to the browser.
- They cannot use browser-only APIs such as
windowordocument. - They cannot use client-only hooks such as
useStateoruseEffect. - They can be composed with Client Components for interactivity.
Use Server Components for:
- Data-heavy pages
- Static or mostly static UI
- Reducing client JavaScript
- Keeping server-only logic off the client
Use Client Components for:
- Click handlers
- Forms with client-side state
- Browser APIs
- Interactive widgets
- Effects and subscriptions
A strong answer is:
Server Components reduce client-side JavaScript by rendering non-interactive parts on the server. For interactivity, I compose them with Client Components at clear boundaries.
Why do lists need stable keys in React?
React uses keys to identify list items across renders.
Stable keys help React preserve the right component state when items are added, removed, filtered, or reordered.
Bad keys:
Math.random()- Array index for reorderable lists
- Values that change between renders
Good keys:
- Database ID
- Product ID
- User ID
- Stable slug or unique key from data
Example problem:
If you use array index as the key in a reorderable list, React may keep the wrong input state with the wrong row after sorting.
A strong answer is:
Keys should be stable and unique among siblings. They help React match items correctly during reconciliation and avoid state bugs.
Performance and Core Web Vitals
Explain LCP, INP, and CLS.
Core Web Vitals measure loading speed, responsiveness, and visual stability.
| Metric | Measures | Good target |
|---|---|---|
| LCP | Largest Contentful Paint: main content loading speed | <= 2.5s |
| INP | Interaction to Next Paint: responsiveness to user interactions | <= 200ms |
| CLS | Cumulative Layout Shift: unexpected layout movement | <= 0.1 |
Important distinction:
- LCP is about how quickly the main content appears.
- INP is about how quickly the page responds to interactions.
- CLS is about whether the layout jumps unexpectedly.
INP replaced FID as the responsiveness Core Web Vital, so candidates should avoid giving outdated FID-only answers.
A strong answer is:
LCP measures loading, INP measures interaction responsiveness, and CLS measures visual stability. For front end interviews, I connect each metric to a real fix, not just the definition.
How do you improve LCP on a marketing page?
To improve LCP, first identify the LCP element. On a marketing page, it is often the hero image, hero heading, or large banner.
Common fixes:
- Compress and resize the hero image
- Use modern formats such as WebP or AVIF
- Use responsive images with
srcsetandsizes - Preload the LCP image when appropriate
- Use
fetchpriority="high"for the main hero image when appropriate - Reduce server response time with caching or CDN
- Remove unnecessary render-blocking JavaScript
- Load critical CSS early
- Avoid late-loading fonts that block the main heading
Measure with:
- Lighthouse
- PageSpeed Insights
- Chrome DevTools Performance panel
- CrUX or other field data
A strong answer is:
I would first identify the actual LCP element, then optimize its discovery, download, and render path. For a marketing page, that often means optimizing the hero image, critical CSS, fonts, and server response time.
How do you improve INP?
To improve INP, reduce the time between a user interaction and the next visual response.
Common fixes:
- Break up long JavaScript tasks
- Reduce expensive work inside click, input, and key handlers
- Debounce or throttle high-frequency handlers
- Avoid large synchronous JSON parsing during interactions
- Use
useTransitionfor non-urgent React updates - Use
useDeferredValuefor expensive UI updates from fast-changing input - Move heavy work to Web Workers when appropriate
- Reduce unnecessary re-renders
- Keep the DOM smaller where possible
Example:
If clicking a filter button triggers a huge list recalculation, the UI may feel frozen. You can improve INP by splitting work, virtualizing the list, memoizing measured bottlenecks, or deferring non-urgent updates.
A strong answer is:
INP improves when the main thread is free to respond quickly. I would profile the interaction, find long tasks, and reduce or defer expensive work.
What is the difference between CSR, SSR, SSG, and ISR?
These are different rendering strategies for web applications.
| Pattern | Where rendered | When to use |
|---|---|---|
| CSR | Browser | Highly interactive dashboards behind login |
| SSR | Server per request | Personalized pages, dynamic SEO pages |
| SSG | Build time | Static marketing pages, docs, blogs |
| ISR | Static generation with revalidation | Large content sites that change occasionally |
Important details:
- CSR can have slower first content if the browser must download and run a lot of JavaScript first.
- SSR can improve initial HTML and SEO, but it may increase server work.
- SSG is fast and cacheable, but content updates usually require rebuilds.
- ISR keeps static-page benefits while allowing pages to refresh after a revalidation period or trigger.
- SSR/SSG HTML may still need hydration before interactive components work.
A strong answer is:
I choose the rendering strategy based on freshness, personalization, SEO, cacheability, and hydration cost.
How do you reduce JavaScript bundle size?
To reduce JavaScript bundle size, first measure what is inside the bundle.
Common fixes:
- Route-based code splitting
- Component-level lazy loading
- Dynamic
import() - Remove unused dependencies
- Replace heavy libraries with smaller alternatives
- Use tree-shaking-friendly imports
- Avoid importing entire utility libraries for one function
- Split vendor bundles where useful
- Keep heavy server-only logic out of the client bundle
- Use Server Components where appropriate
- Analyze bundles with tools such as webpack-bundle-analyzer, source-map-explorer, or Vite visualizer
Senior-level points:
- Set performance budgets in CI
- Track bundle size changes in pull requests
- Measure both lab and field impact
- Avoid hurting UX with excessive lazy loading
A strong answer is:
I start with bundle analysis, remove or split the biggest costs, and set performance budgets so bundle size does not regress silently.
Accessibility and UX
When do you use ARIA vs native HTML?
Use native HTML first.
Native elements such as button, input, select, label, form, and dialog already include built-in browser behavior, keyboard support, and accessibility semantics.
Use ARIA when native HTML is not enough, especially for custom widgets such as:
- Combobox
- Tabs
- Accordion
- Modal dialog
- Custom menu
- Custom listbox
Common ARIA examples:
| Need | ARIA |
|---|---|
| Expanded/collapsed state | aria-expanded |
| Relationship between trigger and panel | aria-controls |
| Current active option | aria-activedescendant |
| Modal context | aria-modal |
| Helper or error text | aria-describedby |
Important rule:
Bad ARIA can be worse than no ARIA.
For modals, interviewers expect more than role="dialog". You should discuss:
- Move focus into the modal when it opens
- Trap focus while the modal is open
- Close with Escape where appropriate
- Restore focus to the trigger when closed
- Prevent background content from being interacted with
A strong answer is:
I prefer native HTML first. I use ARIA only when building custom interactions, and I test keyboard behavior, screen reader semantics, and focus management.
What WCAG concepts should front end developers know?
Front end developers do not need to memorize every WCAG success criterion, but they should understand the four main principles.
| Principle | Meaning | Front end examples |
|---|---|---|
| Perceivable | Users can perceive the content | Alt text, captions, color contrast |
| Operable | Users can operate the interface | Keyboard access, focus states, no keyboard traps |
| Understandable | UI and errors are clear | Labels, instructions, predictable behavior |
| Robust | Works across browsers and assistive tech | Valid markup, semantic HTML, correct ARIA |
Important examples to know:
- Normal text contrast should meet common accessibility contrast expectations
- Interactive elements should be keyboard reachable
- Focus should not be hidden or trapped incorrectly
- Form errors should be clear and associated with inputs
- Touch/click targets should be usable
- Do not rely only on color to communicate meaning
Testing tools:
- Browser keyboard testing
- Screen reader smoke testing
- axe DevTools
- Lighthouse accessibility checks
- Playwright accessibility assertions where useful
A strong answer is:
I use WCAG as a practical checklist: can users perceive, operate, understand, and reliably use the UI across devices and assistive technologies?
Machine coding and system design (UI)
How would you build a search autocomplete component?
First, clarify the requirements.
Questions to ask:
- Should results load from local data or an API?
- What debounce delay is expected?
- Should keyboard navigation be supported?
- What happens on empty, loading, and error states?
- Should clicking outside close the menu?
- Should the first result be highlighted automatically?
- How should stale API responses be handled?
Implementation approach:
- Use a controlled input.
- Debounce the search query.
- Fetch results after the debounce delay.
- Abort stale requests using
AbortController. - Show loading, error, empty, and success states.
- Support keyboard navigation with ArrowUp, ArrowDown, Enter, and Escape.
- Use an accessible combobox/listbox pattern.
- Highlight matched text if required.
Accessibility points:
- Input should have a clear label
- Results should be announced appropriately
- Active option should be tracked
- Keyboard and mouse behavior should match user expectations
A strong answer is:
Autocomplete tests async JavaScript, accessibility, keyboard handling, state management, and edge cases. I would focus on correctness before styling.
How do you implement infinite scroll performantly?
For infinite scroll, I would use an Intersection Observer with a sentinel element near the bottom of the list.
Key practices:
- Fetch the next page when the sentinel enters the viewport
- Prevent duplicate requests while loading
- Keep track of pagination cursor or page number
- Show loading and error states
- Stop requesting when there are no more results
- Virtualize very long lists using tools such as
react-window - Preserve scroll position when users navigate back
- Reserve space for loading content to reduce layout shift
Trade-offs:
| Approach | Pros | Cons |
|---|---|---|
| Infinite scroll | Smooth browsing experience | Harder for accessibility, SEO, and footer access |
| Load more button | More controlled and accessible | Slightly more manual user action |
| Pagination | Best for SEO and direct navigation | Less fluid experience |
A strong answer is:
I would use Intersection Observer for loading, virtualization for long lists, and consider a Load more button when accessibility or SEO matters.
How would you design a component library for 10+ product teams?
For a shared component library, I would design for consistency, accessibility, versioning, and adoption.
Core pieces:
- Design tokens — color, spacing, typography, radius, shadow, motion
- Primitive components — Button, Input, Modal, Tooltip, Tabs, Select
- Accessible defaults — keyboard support, focus states, labels, ARIA where needed
- Variant API — size, intent, state, density, icon support
- Documentation — Storybook, usage examples, do/don’t guidelines
- Theming — brand or product-level customization
- Testing — unit, interaction, accessibility, visual regression
- Versioning — semantic versioning and changelog
- Migration support — codemods or deprecation warnings for breaking changes
Senior-level trade-offs:
| Decision | Trade-off |
|---|---|
| Flexible API | Powerful but harder to govern |
| Strict API | Consistent but may block edge cases |
| Central ownership | Higher quality but slower delivery |
| Federated contribution | Faster adoption but needs review process |
A strong answer is:
I would build accessible primitives, document clear usage patterns, version changes carefully, and create a contribution process so teams can adopt the system without forking it.
Testing, tooling, and behavioral
How do you test front end code?
Front end testing should focus on user-visible behavior, not implementation details.
Common levels:
| Test type | Tools | What to test |
|---|---|---|
| Unit | Vitest, Jest | Pure functions, utilities, reducers |
| Component | React Testing Library | Rendering, user interactions, states |
| Integration | Testing Library, MSW | Component + API behavior |
| E2E | Playwright, Cypress | Critical user flows |
| Visual regression | Chromatic, Percy | Design system and layout changes |
Good testing practices:
- Prefer queries such as
getByRoleandgetByLabelText - Test loading, error, empty, and success states
- Mock network calls at the boundary
- Avoid testing internal state directly
- Add E2E tests for checkout, login, signup, and other critical flows
- Include accessibility checks where practical
A strong answer is:
I test what the user sees and does. I prefer role-based queries, cover important UI states, and reserve E2E tests for critical flows.
What is the role of Vite or webpack in modern front end?
Build tools such as Vite and webpack help convert source code into optimized files the browser can run.
They commonly handle:
- JavaScript and TypeScript compilation
- JSX transform
- CSS processing
- Module resolution
- Hot Module Replacement during development
- Tree shaking
- Code splitting
- Asset optimization
- Production bundling
Vite is popular because it provides a fast development server and quick HMR. For production, it creates optimized builds suitable for deployment.
Webpack is still widely used in many mature codebases and gives deep configuration control.
Interview-level answer:
“We use build tools to support modern JavaScript, TypeScript, JSX, CSS processing, dev-server HMR, code splitting, and optimized production bundles. I do not need to know every plugin, but I should understand what the build pipeline does.”
Tell me about a UI bug you fixed in production.
Use the STAR format: Situation, Task, Action, Result.
A strong story should include:
- User impact
- How you reproduced the issue
- Browser/device details
- Root cause
- Fix
- Test or monitoring added afterward
- What you learned
Example structure:
| STAR step | Example |
|---|---|
| Situation | Checkout button failed on Safari for some users |
| Task | Identify and fix the issue quickly |
| Action | Reproduced on BrowserStack, traced it to a CSS/flex or event-handling issue, shipped a fix |
| Result | Checkout recovered, and a regression test or monitoring alert was added |
Other good front end examples:
- CLS spike after image layout change
- Hydration mismatch in SSR page
- Race condition in fetch results
- Modal focus trap bug
- Mobile layout breaking at a specific viewport
- Third-party script blocking page interaction
A strong answer is:
I explain the user impact first, then how I reproduced, debugged, fixed, and prevented the issue from happening again.
Final-week checklist for front end interviews?
Use the final week for timed practice, not new theory.
Checklist:
- Build autocomplete or infinite scroll from scratch
- Build one accessible modal, tabs, or dropdown component
- Explain LCP, INP, and CLS with one fix each
- Review closures, prototypes,
this, promises, and the event loop - Practice DOM events, bubbling, capturing, and delegation
- Review React hooks, keys, state ownership, and effect cleanup
- Practice one front-end system design prompt
- Prepare one production UI bug story using STAR
- Prepare a portfolio walkthrough for one polished UI project
- Check keyboard navigation and Lighthouse issues in your portfolio
Also review:
A strong final-week goal:
“Be ready to build, explain, debug, and discuss trade-offs. Front end interviews reward practical UI judgment, not only memorized definitions.”

