Top 30 Frontend Dev Interview Questions and Answers
30 multiple-choice questions on Frontend Dev, of the kind that come up in a technical interview, drawn from 30 bites in the Frontend Dev 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 approach correctly applies Vue's progressive philosophy to a legacy server-rendered page?
Show the answer
Answer: b · Dropping in a CDN script tag to enhance one form, then migrating that component to a Vite SFC later
Vue is progressive because it supports incremental adoption, letting you enhance one element with a CDN script and later scale to a compiled SFC project. Option A is a common misconception because progressive refers to layer-by-layer adoptability, not a small bundle size.
Read the full bite: Explain Vue as a progressive framework and build-step differences
Question 2 of 30
Why can a standard browser not execute a .jsx file directly without a build step?
Show the answer
Answer: c · JSX must first be transpiled into React.createElement or jsx function calls
JSX is syntax the JS engine does not understand, so a transpiler converts it to function calls first. Browsers never receive JSX; the CDN or MIME claims are irrelevant to the transpilation requirement.
Read the full bite: What is JSX and how does the browser run it?
Question 3 of 30
Which TypeScript snippet correctly declares a string name and a numeric array using proper primitive and array type annotations?
Show the answer
Answer: a · const userName: string = "Alice"; const luckyNumbers: number[] = [7, 13, 21]
TypeScript requires lowercase string and number for primitive type annotations, and number[] correctly types an array of numbers. Option B is wrong because uppercase String and Number refer to rare built-in wrapper object types rather than the primitive value types used for standard annotations.
Read the full bite: Declare a string name and an array of lucky numbers in TypeScript
Question 4 of 30
Four divs are set to width: 25%, 10px padding, and 1px border. Under the default box model, why does the last div wrap to a new line?
Show the answer
Answer: a · The declared width applies only to content, so padding and border add extra width.
Under the default content-box model, width applies only to the content area, so padding and border increase the rendered size beyond 25% and cause wrapping. Distractor D is wrong because content-box is the browser default, meaning padding is added outside the declared width rather than included in it.
Read the full bite: Explain the CSS box model: content-box vs border-box
Question 5 of 30
Which built-in Angular module is specifically designed for handling user input and validation, a capability that Vue and Svelte projects typically address through external libraries such as VeeValidate or FormKit?
Show the answer
Answer: a · Template-driven and reactive forms
Angular ships template-driven and reactive forms with built-in validators as a first-party module, while Vue and Svelte generally rely on community libraries like VeeValidate or FormKit for equivalent functionality. NgRx is the most tempting distractor because it is a third-party state management library, not a built-in Angular feature.
Read the full bite: What out-of-the-box Angular features require manual setup in Vue or Svelte?
Question 6 of 30
A child component needs to change a value it received from its parent. What is the correct React pattern?
Show the answer
Answer: c · Call a callback function passed down from the parent via props
Props are immutable and flow one-way from parent to child, so the child must invoke a callback prop to request that the parent update the data. Mutating a prop directly breaks React's rendering assumptions and will not trigger a re-render.
Read the full bite: Explain props in React and how parent components pass data to children
Question 7 of 30
When you write let message = 'hello' without a type annotation, what is the resulting compile-time behavior?
Show the answer
Answer: a · TypeScript infers string and later rejects message = 42 with a type error
TypeScript analyzes the right-hand side to infer string, so reassigning a number later causes a compile-time error. Distractor A is wrong because omitting an annotation does not default to any; the compiler deduces a specific static type instead.
Question 8 of 30
Which statement correctly explains why an ID selector beats a class selector when they conflict?
Show the answer
Answer: c · The ID rule wins because the specificity algorithm compares the ID column first, and 1-0-0 outranks 0-1-0
Specificity is a three-column value scored as ID-CLASS-TYPE, so an ID's 1-0-0 always beats a class's 0-1-0 before the CLASS column is ever evaluated. The most tempting distractor claims the later class wins, but source order only breaks ties when specificity is equal.
Read the full bite: What color wins when an ID and class rule conflict?
Question 9 of 30
Which accurately describes the two primary ways to define a React component?
Show the answer
Answer: c · Function components and class components, with function components being the standard for new React 19 code
Function components and class components are the two distinct definition paradigms, and function components are the React 19 default. Arrow functions and function declarations are merely alternate syntaxes for the same function component paradigm, not separate ways to define components.
Read the full bite: What are the two main ways to define a component in React?
Question 10 of 30
How does Svelte's compiler-first design most directly improve the end-user experience compared to virtual DOM frameworks?
Show the answer
Answer: a · It shifts work to build time, producing smaller bundles and less browser CPU work for faster page loads.
Svelte's compiler generates imperative vanilla JavaScript at build time, which shrinks bundles and eliminates virtual DOM diffing overhead for end users. Option D describes a developer experience benefit, not a user-facing performance improvement.
Read the full bite: What is the primary end-user benefit of Svelte's compiler-first approach?
Question 11 of 30
An element has both id='banner' and class='active'. If #banner sets margin-top: 10px and .active sets margin-top: 20px, which value applies?
Show the answer
Answer: b · 10px, because an ID selector has higher specificity than a class selector
An ID selector contributes 1-0-0 to specificity while a class contributes 0-1-0, so #banner wins even if .active appears later. IDs being unique in the DOM is an HTML constraint, not the reason the cascade favors the ID selector.
Read the full bite: How do class and ID selectors differ in specificity and use case?
Question 12 of 30
What happens when TypeScript cannot infer a type and noImplicitAny is disabled?
Show the answer
Answer: c · The compiler silently assigns the any type, disabling further static analysis for that value
When noImplicitAny is disabled, TypeScript silently falls back to any for uninferrable values, which opts them out of static checking and allows runtime errors to go undetected. Option B describes what happens when the flag is enabled, making it a tempting reversal.
Read the full bite: What is noImplicitAny and why is it best practice?
Question 13 of 30
A user-agent stylesheet sets a button to black with a high-specificity selector, and an author stylesheet sets it to blue with a low-specificity selector. What is the final color?
Show the answer
Answer: b · Blue, because author styles originate from a higher origin than user-agent styles, and origin is evaluated before specificity.
The cascade evaluates origin before specificity, so an author rule always beats a user-agent rule regardless of selector weight. Option A represents the common misconception that specificity trumps origin, while D incorrectly invokes source order when origin already differs.
Read the full bite: Describe the full CSS cascade precedence order
Question 14 of 30
When a reactive variable changes in Svelte, how is the update triggered differently than in Vue 3's runtime Proxy system?
Show the answer
Answer: a · By compiler transforms that turn assignments into explicit update calls
Svelte resolves dependencies at build time by transforming assignments into explicit update logic in the compiled output, so no runtime tracker is needed. Option B is tempting because Vue 3 uses runtime Proxies, but Svelte does not use them at all.
Read the full bite: Compare and contrast Vue 3 and Svelte reactivity systems
Question 15 of 30
Which operation is valid on a variable of type unknown without first narrowing its type?
Show the answer
Answer: b · Assigning a string value to the unknown variable
Any value can be assigned to an unknown variable, but you cannot read properties, call methods, or assign it to a narrower type without narrowing first. Options A and D confuse unknown with any, which is assignable to all types, while B requires narrowing because the compiler cannot guarantee the method exists.
Question 16 of 30
When a dynamic list reorders and items have local state, what happens if array indices are used as React keys?
Show the answer
Answer: d · React reuses component instances by position, causing state from one data item to appear on another.
Array indices tie identity to position, so React reuses the wrong component instance after reorder or deletion and state ends up attached to the wrong data item. Option B is wrong because React does not reset state when keys are unstable—it incorrectly preserves it on the reused instance.
Read the full bite: What is the purpose of React's key prop and index key risks?
Question 17 of 30
When handling a parameter typed as string or string array, which approach correctly narrows the value at runtime?
Show the answer
Answer: d · Check whether Array.isArray(arg) is true
Array.isArray is the recognized type guard that safely narrows the union within the block. Checking typeof against array is a runtime bug because typeof returns object for arrays, never array.
Read the full bite: How do you type and guard a string-or-string-array argument?
Question 18 of 30
Why does Angular treat dependency injection as a runtime architectural layer rather than relying on ES module imports like Vue?
Show the answer
Answer: c · It enables runtime resolution of service lifetimes and implementation swapping without changing consumer code or direct file coupling.
Angular's DI is a runtime inversion-of-control system that supports scoped lifetimes, tree-shakable providers, and test-time substitution without modifying consumer code. The boilerplate distractor is wrong because DI still requires constructor declarations; its architectural value lies in runtime indirection and hierarchical resolution, not syntax savings.
Read the full bite: Why is DI central to Angular architecture versus Vue's module system?
Question 19 of 30
In React, when is an early return with if/else preferable to an inline ternary inside JSX?
Show the answer
Answer: a · When branches are large, structurally different, or to reduce nesting
Early returns improve readability when branches are large, structurally different, or deeply nested. Option B actually describes when an inline ternary is the better choice, not an early return.
Read the full bite: Describe two patterns for conditional rendering in JSX
Question 20 of 30
Two adjacent block-level siblings in normal flow have margin-bottom: 30px and margin-top: 20px. What is the resulting vertical space between them?
Show the answer
Answer: d · 30px, because the larger of the adjacent margins is used
Margin collapsing means adjacent vertical margins in normal flow combine into a single margin equal to the largest value, so 30px is rendered. The 50px option reflects the common misconception that margins always add together.
Read the full bite: What is margin collapsing? Give a sibling scenario and prevention.
Question 21 of 30
Why would wrapping two table cells in a Fragment be preferable to wrapping them in a div?
Show the answer
Answer: a · Fragments avoid creating an invalid HTML structure since they do not add an extra DOM node.
A div placed directly inside a table row creates invalid HTML, while a Fragment groups children without introducing any DOM node. Claiming a performance benefit is a common misconception; the primary reason to use Fragments is structural and semantic correctness, not optimization.
Read the full bite: What is a React Fragment and why use it over a div?
Question 22 of 30
When reactive state changes in a Svelte component, how does the compiled application update the browser DOM?
Show the answer
Answer: d · It executes pre-generated imperative statements that directly mutate the affected DOM nodes.
Svelte compiles components into imperative vanilla JavaScript that retains direct references to DOM nodes and executes precise update statements when state changes, so no intermediate tree is ever created. The distractor suggesting a hidden virtual DOM is wrong because the compiler deliberately avoids emitting any diffing or reconciliation runtime, generating direct DOM manipulation code instead.
Read the full bite: How does Svelte update the DOM without a Virtual DOM?
Question 23 of 30
Which statement correctly distinguishes a pseudo-element from a pseudo-class?
Show the answer
Answer: d · A pseudo-element styles a part or generated sub-part not present in the DOM
Pseudo-elements such as ::before style virtual parts not in the DOM, while pseudo-classes select existing elements by state. Only pseudo-elements use double colons in modern syntax, so the last option is wrong.
Read the full bite: Pseudo-class versus pseudo-element in CSS
Question 24 of 30
When publishing a TypeScript library, why might you export an interface instead of a type alias for a config object?
Show the answer
Answer: a · Interfaces allow consumers to safely augment the shape via declaration merging.
Interfaces support declaration merging, allowing consumers to safely augment public library types, whereas type aliases are closed. Option D is wrong because type aliases can absolutely describe objects with methods and properties; they are not limited to primitives or unions.
Read the full bite: Key differences: type alias vs interface for object shapes
Question 25 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 26 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 27 of 30
A team passes a user object through Layout, Header, Navigation, and finally to UserMenu. What is the strongest argument for replacing this with Context or composition?
Show the answer
Answer: a · Layout, Header, and Navigation are coupled to a prop they ignore, making refactors and reuse harder.
Prop drilling is primarily a maintenance and coupling problem: intermediaries must accept and forward props they do not use, so renaming the prop or reusing those components elsewhere becomes painful. Option B is tempting but wrong because the card explicitly warns against confusing drilling with runtime performance issues like excessive re-renders.
Read the full bite: Explain prop drilling and why it's a problem
Question 28 of 30
In a specificity conflict between `#header` and a selector with eleven classes, which statement is true?
Show the answer
Answer: a · The `#header` selector wins because the ID column outweighs any number of classes
The card explains that specificity is a tuple where the leftmost nonzero column wins, so one ID always beats any number of classes. Option D is tempting because it reflects the common error of collapsing the tuple into a single integer.
Read the full bite: How is CSS specificity calculated for a complex selector?
Question 29 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 30 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()
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.