Top 30 Advanced Frontend Dev Interview Questions and Answers
30 advanced multiple-choice Frontend Dev interview questions, the deep end: internals, failure modes, and the design calls a senior engineer is expected to defend. They come from 30 bites in the Frontend Dev library, the hardest slice of the 537 Frontend Dev interview questions in the library. Answer them here or read straight down. Every question carries the correct option, why it is correct, and a link to the bite it came from.
Frontend web development and UI engineering
30 questions. Pick an answer, or open “Show the answer” to read it.
Answers are graded in your browser. Nothing is saved, and no XP or streak is earned here. The app keeps score.
Question 1 of 30
Which getProperty signature both rejects invalid keys at compile time and returns the exact type of the requested property?
Show the answer
Answer: c · Two generics T and K where K extends keyof T and the return type is T[K]
Option C is correct because constraining K with extends keyof T limits keys to valid properties on T, while T[K] preserves the exact type of the accessed property. Option D is tempting because keyof T does restrict keys, but T[keyof T] produces a union of all property types rather than the specific one for the key passed.
Read the full bite: Create a generic getProperty using generics and keyof
Question 2 of 30
Why does Vue's architectural philosophy make it the better choice for gradually modernizing a ten-year-old monolith one module per quarter?
Show the answer
Answer: b · Vue's progressive nature allows incremental adoption via the Composition API without requiring a full rewrite.
The card describes Vue as progressive and ideal for incremental adoption without full rewrites, using the Composition API for modular development. Distractor C incorrectly attributes Angular's built-in standardization to Vue, when in fact Vue's flexibility requires stronger platform discipline to prevent fragmentation.
Question 3 of 30
Which call reflects how Babel transforms the JSX <a href='/home' className='link'>Go Home</a> into React.createElement()?
Show the answer
Answer: b · React.createElement('a', {href: '/home', className: 'link'}, 'Go Home')
The JSX transform emits a quoted string for lowercase host tags, places attributes in the second argument preserving className, and passes text children as the third argument, not inside props. Option A is tempting because the resulting element object has props.children, but the createElement API signature requires children as a separate argument from props.
Read the full bite: Write the React.createElement() equivalent for this JSX
Question 4 of 30
A design system groups element selectors for a global reset. Developers complain that single-class utilities cannot override it. Switching from :is() to :where() fixes this because...
Show the answer
Answer: b · :where() has zero specificity, while :is() takes on the specificity of its most specific argument
:where() always has zero specificity, so a single class easily overrides it, whereas :is() inherits the most specific argument's weight, creating a barrier. Option D is tempting because it admits :where() is lower but incorrectly claims it still carries element-level weight rather than zero.
Read the full bite: Explain :is() vs :where() specificity and when to pick :where()
Question 5 of 30
When building a no-code canvas where users assemble layouts from hundreds of possible components at runtime, what is a concrete downside of Svelte's compile-time model versus Vue or Angular?
Show the answer
Answer: d · Svelte must eagerly import all possible dynamic targets, sacrificing tree-shaking and reintroducing runtime overhead through escape hatches like svelte:component.
The correct answer notes that Svelte requires eager imports and runtime escape hatches for open-ended dynamic sets, which reintroduces overhead and sacrifices tree-shaking. Distractor A is tempting because Svelte does compile to imperative DOM operations, but dynamic components are still possible via compiler-aware patterns rather than impossible.
Read the full bite: Svelte compiler downsides vs Vue and Angular runtime
Question 6 of 30
What makes a user-defined type guard unsound when its predicate claims value is User but the body only verifies value is not null?
Show the answer
Answer: d · TypeScript narrows the type in conditional branches while the value may still lack required User properties at runtime
A type predicate is purely a compile-time hint; if the runtime check is too permissive, TypeScript narrows the type based on a false promise, allowing unsafe property access. Distractor B is wrong because TypeScript never mutates or coerces runtime values to satisfy a type predicate.
Read the full bite: What is a type predicate? Write a custom type guard for User.
Question 7 of 30
Why can using array indices as keys cause state pollution when a list is reordered?
Show the answer
Answer: d · React relies on keys to identify elements across renders; indices make React match DOM nodes to the wrong data, preserving state for the wrong item.
Keys provide sibling-scoped identity, not just a performance shortcut; when indices are reused after reordering, React incorrectly associates the old DOM node and its state with new data. Option A is wrong because keys fundamentally determine state preservation, so unstable keys create correctness bugs rather than merely slower reconciliation.
Read the full bite: How does React use keys in reconciliation? When do keys cause bugs?
Question 8 of 30
An element with position: absolute has its offsets computed relative to which box?
Show the answer
Answer: a · The padding box of the nearest ancestor whose position is not static
Absolutely positioned elements resolve against the nearest positioned ancestor's padding box, not necessarily the direct parent. The viewport rule is for fixed, and the normal-flow ancestor rule applies to static and relative elements.
Question 9 of 30
What is the key architectural difference between passing a render function prop and passing a component reference prop in React?
Show the answer
Answer: a · A render function is called by the child with internal data, letting the parent control what renders while the child controls when and where.
This captures inversion of control: the parent supplies the function (what to render) and the child invokes it with internal data (when and where). Option D is tempting because both patterns enable reuse, but HOCs wrap components at definition time while render props compose at runtime.
Read the full bite: Can you pass a React component as a prop? Explain Render Props.
Question 10 of 30
When passing a large ArrayBuffer from the main thread to a dedicated Web Worker for image processing, which technique avoids duplicating that memory in the browser?
Show the answer
Answer: c · Include the ArrayBuffer in the postMessage transfer list so ownership moves to the worker
Listing the ArrayBuffer in the transfer list moves ownership to the worker without copying, preventing memory duplication. The most tempting distractor is wrong because structured clone always copies data; postMessage never shares memory by reference between threads.
Read the full bite: Offload CPU-intensive work to a Web Worker and explain communication.
Question 11 of 30
When implementing route-level lazy loading for an NgModule, which combination ensures the CLI emits a separate chunk without manual build configuration?
Show the answer
Answer: b · The feature uses loadChildren with a dynamic import and is removed from AppModule imports
The CLI automatically splits a chunk when it detects a dynamic import in loadChildren and the module is absent from AppModule's static dependency graph. Manual Webpack entry points are a red flag because Angular abstracts the build tool, and keeping an eager import in AppModule forces the feature into the main bundle.
Read the full bite: How would you implement lazy loading for an Angular feature module?
Question 12 of 30
In a single Vite Library Mode build producing ESM and UMD outputs, which setup correctly externalizes Vue and maps it to window.Vue in the UMD bundle?
Show the answer
Answer: b · build.rollupOptions.external includes vue and output.globals maps vue to Vue, with formats set to es and umd
rollupOptions.external keeps Vue out of the bundle while output.globals tells the UMD build to use window.Vue at runtime. The most tempting distractor omits globals because ESM does not need them, but without that mapping the UMD output will throw a runtime error trying to resolve vue as a module.
Read the full bite: How do you configure Vite Library Mode for ESM and UMD outputs?
Question 13 of 30
A heading has background-image: linear-gradient(gold, purple) and background-clip: text applied, yet the text still appears solid black. What is the root cause?
Show the answer
Answer: b · The foreground text color remains opaque and paints over the clipped background layer
The card states that foreground text color sits above the background in stacking order, so an opaque text fill completely obscures the clipped gradient unless color is transparent. Option C is a tempting distractor because candidates often confuse background-origin, which controls positioning, with background-clip, which controls the painting area.
Question 14 of 30
You must measure a rendered DOM element and immediately adjust a modal to prevent visual flicker. Which choice is correct?
Show the answer
Answer: d · useLayoutEffect, because it runs synchronously after DOM mutations but before paint, letting you correct layout before it is visible
useLayoutEffect runs synchronously after React commits DOM changes but before the browser paints, so layout corrections happen before the user sees anything. Option C is tempting because it names the right hook but incorrectly claims it runs after paint, which would actually cause the flicker you are trying to prevent.
Read the full bite: When would you choose useLayoutEffect over useEffect?
Question 15 of 30
Which statement accurately compares open and closed shadow modes regarding encapsulation and event propagation?
Show the answer
Answer: b · Closed mode returns null for external shadowRoot access but does not prevent events from bubbling out retargeted to the host
Closed mode returns null for element.shadowRoot to prevent accidental access, yet bubbling events still cross the boundary with their target retargeted to the host. Distractor D is tempting because closed sounds like a security boundary, but the platform explicitly does not protect against malicious inspection.
Read the full bite: Explain Shadow DOM, encapsulation, and event propagation
Question 16 of 30
How should you refactor an effect that needs the latest prop value inside a polling interval without listing that prop as a dependency?
Show the answer
Answer: b · Lift the prop value into a ref and read the ref inside the interval with an empty dependency array.
Lifting the prop into a ref lets the interval read the latest value without re-subscribing, because refs are mutable and do not trigger re-renders. Disabling the rule and reading the prop directly hides the stale closure from the linter and leaves the code vulnerable to refactor hazards.
Read the full bite: Why is exhaustive-deps critical and when can you disable it?
Question 17 of 30
When controlling a variable font, why prefer font-weight over font-variation-settings where both can set weight?
Show the answer
Answer: b · High-level properties integrate with the cascade and inheritance more predictably
Dedicated properties like font-weight map to axes while participating cleanly in the cascade and animation, so they are preferred. font-variation-settings can set wght but is a low-level escape hatch, not faster or print-only.
Question 18 of 30
You have a product listing page that updates daily. Should you prerender it or SSR it? What's the main trade-off?
Show the answer
Answer: a · Prerender once per day on a cron schedule to balance freshness and speed
Daily-updated content fits a hybrid model: prerender on a cron (freshness every 24 hours) combined with instant static serve. Option C (prerender without schedule) risks stale data. Option B (pure SSR) is overkill and costly if the data doesn't change frequently. Option D adds complexity without solving the core need.
Read the full bite: Prerendering vs SSR in SvelteKit: trade-offs?
Question 19 of 30
You set color-scheme: light dark on :root and use prefers-color-scheme for custom tokens, but a browser forced dark mode breaks your hero section. What is the most targeted fix?
Show the answer
Answer: a · Add color-scheme: only light to the hero section to prevent UA overrides
The only keyword explicitly forbids the UA from overriding an element's color scheme, making it the correct tool to opt a specific component out of a forced dark mode. A prefers-color-scheme media query cannot block browser overrides because it only lets authors react to the user's preference, not control native UI recoloring.
Question 20 of 30
Which approach is the idiomatic TypeScript solution for constructing a typesafe ApiRoute type that includes both /api/v1/<resource> collection paths and /api/v1/<resource>/{id} item paths from a finite Resource union?
Show the answer
Answer: b · A base route template interpolating Resource into /api/v1/, unioned with the same base route suffixed by /{id}
Template literal types automatically distribute a union through an interpolated position into every concrete string permutation, so unioning BaseRoute with BaseRoute/{id} is the idiomatic, machinery-free solution. Option A is tempting because it yields the same members, but it unnecessarily uses a mapped type when direct interpolation already expands the union, and C sacrifices compile-time exhaustiveness for false flexibility.
Read the full bite: Build a typesafe ApiRoute type using template literal types
Question 21 of 30
In a nested CSS grid, what fundamentally prevents a grandchild element from aligning to the outer grid's tracks without using subgrid?
Show the answer
Answer: b · The inner grid establishes its own independent track list, isolating its children from the parent's grid lines.
The inner grid creates its own independent track list, so its children have no knowledge of the outer grid's lines. Distractor D is tempting because identical fraction values appear to create alignment, but independent track contexts mean the grids remain isolated regardless of the units used.
Read the full bite: What problem does subgrid solve? Give a concrete example.
Question 22 of 30
What return type does fetchItem<T extends boolean>(..., includeHistory: T): T extends true ? ExtendedItem : BaseItem yield when includeHistory is a plain boolean variable?
Show the answer
Answer: c · The type resolves to ExtendedItem | BaseItem because boolean encompasses both true and false
Because boolean is equivalent to true | false, the distributive conditional type evaluates both branches and produces a union. Option B is tempting but wrong because TypeScript does not narrow a plain boolean variable to a literal across a function boundary.
Read the full bite: How would you model fetchItem's return type with generics and conditional types?
Question 23 of 30
In a context-reducer feature, a component only dispatches actions but never reads state. How do you prevent it from re-rendering when state changes?
Show the answer
Answer: c · Provide state and dispatch through two separate contexts and consume only the dispatch context
Splitting state and dispatch into two contexts lets components subscribe only to the stable dispatch function, isolating them from state reference changes. React.memo cannot prevent re-renders caused by a changing context value, and useReducer already returns a stable dispatch, so memoizing it with useCallback does not solve the subscription problem.
Read the full bite: Describe combining useContext and useReducer for scalable feature state
Question 24 of 30
When a CSS Grid container lacks sufficient horizontal space, how does a fit-content track behave compared to a max-content track?
Show the answer
Answer: a · fit-content is clamped by the container's available space and can compress to min-content, while max-content demands the full unwrapped width even if it overflows
fit-content caps expansion at the container's available space but can still compress to min-content, whereas max-content always takes the content's full unwrapped width regardless of overflow. Option B is tempting because it confuses fit-content with auto, which distributes leftover space and can grow beyond max-content, while fit-content hard-caps growth.
Read the full bite: How do min-content, max-content, and fit-content work in CSS Grid?
Question 25 of 30
In a reusable DataList component, what is the primary architectural benefit of using scoped slots instead of having the parent manage the iteration?
Show the answer
Answer: a · It allows the child to own data fetching, filtering, and iteration while the parent controls only the visual template for each row.
Scoped slots preserve encapsulation by keeping data fetching and iteration inside the child while letting the parent determine markup. Option C is a common misconception because slot content uses lexical scope and cannot see child data unless the child explicitly exposes it through slot props or template context.
Read the full bite: Implement a scoped slot pattern in a reusable DataList
Question 26 of 30
When preventing CLS in a responsive CSS Grid of images with known build-time dimensions, which approach is most robust?
Show the answer
Answer: a · Include HTML width and height attributes on images, ensure grid-template-rows respects intrinsic ratios, and use CSS aspect-ratio for dynamic elements
HTML width and height attributes provide the earliest aspect-ratio signal before download, and combining them with grid row sizing plus CSS aspect-ratio for dynamic elements prevents collapse at every stage. Option C is tempting but wrong because aspect-ratio alone lacks the early HTML signal and does not stop grid rows from collapsing to zero before content arrives.
Read the full bite: How can CSS aspect-ratio and modern layout properties prevent CLS?
Question 27 of 30
When a React Server Component fetches data required by deeply nested Client Components, which pattern correctly respects the server-client boundary?
Show the answer
Answer: b · Pass the fetched data as serializable props to the Client Components or to a Client wrapper that distributes them
Server Components must communicate with Client Components through serializable props because props are the only channel across the RSC boundary. Creating Context in a Server Component is incorrect because Context cannot be created in a Server Component and consumed by a Client Component.
Read the full bite: Pass server-fetched data from Server Components to nested Client Components
Question 28 of 30
When architecting a headless Toggle component, which approach correctly inverts control so the parent owns the markup?
Show the answer
Answer: a · Rendering only a scoped slot that passes on and toggle to the parent, which decides what DOM to emit
A headless component must render no DOM of its own and expose state and actions through a scoped slot so the parent controls all markup. Option B is a red flag because config props like theme tightly couple logic to a specific visual implementation rather than truly inverting control.
Read the full bite: Architect a headless Toggle with scoped slots
Question 29 of 30
In a useEffect with setInterval reading a state variable, which fix removes the stale closure without leaking or duplicating timers?
Show the answer
Answer: b · Add the state variable to the dependency array and return a cleanup that clears the interval
Adding the state to the dependency array and returning a cleanup that clears the interval recreates the callback with the latest value and prevents leaks. The functional updater distractor is wrong because functional updates only help inside setState, not inside intervals or event listeners where the closure remains stale.
Question 30 of 30
When a parent mutates a nested property of an object passed to a child component, how does Vue 3's behavior differ from Angular's OnPush strategy?
Show the answer
Answer: d · Vue 3 recursively tracks nested access with Proxies and updates dependents automatically, while Angular OnPush skips re-rendering because the input reference remains unchanged.
Vue 3 uses Proxy-based reactivity to intercept and trigger updates for nested mutations automatically, while Angular OnPush only checks input references and skips re-rendering when they are unchanged. Option C is wrong because Angular Default never performs deep observation; it relies on zone.js-triggered digest cycles, so it does not behave like Vue 3.
Read the full bite: How do Vue and Angular detect nested object mutations?
Could you explain these out loud?
That is what an interview actually tests. Tezvyn gives you questions like these with what the interviewer is really checking, the answer that lands, and the mistake that ends the conversation, in the four minutes before your next meeting.
The iPhone app is on the way
We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.
Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.