104 Frontend Essentials interview questions with detailed answers, sorted from basic to advanced. Free to practice, with progress saved automatically.
A curated shortlist of questions that frontend interviews tend to touch, drawn from several technologies rather than a single stack. It covers core JavaScript such as closures and async code, CSS layout and the box model, CORS and browser-side token storage, React hooks, rendering, and Git workflows like merge versus rebase.
DOCTYPE (Document Type Declaration) states which HTML version the document uses and must be the first line. HTML5 needs a single line: It decides whether the browser renders in standards mode or quirks mode. Without it you get quirks mode: the browser emulates a few…
Semantic HTML means using tags that describe the role of the content instead of neutral <div/<span. Four reasons it pays off: 1. Accessibility — a screen reader can jump straight to a landmark (main, nav, header); with <div there is nothing to jump to. 2.…
Key differences include: - Architecture: App Router (Next.js 13+) uses the app/ directory and supports React Server Components by default. Pages Router uses the pages/ directory: pages are still rendered to HTML on the server (SSR/SSG), but the JavaScript for every component is sent to…
Use a Server Component when you need: data fetching, access to backend resources, keeping sensitive data (API keys) off the client, or reducing the client bundle. Use a Client Component when you need: onClick/onChange event handlers, useState/useEffect, browser APIs, real-time updates, or custom hooks. Default…
next/image automatically: - Generates multiple sizes plus a srcset so the browser picks one that fits the viewport/DPR (paired with the sizes prop). - Converts to a modern format: WebP by default; AVIF must be enabled via images.formats. - Lazy-loads by default. For the LCP…
SEO (Search Engine Optimization) is the practice of optimizing a website to rank higher on Google, Bing, and other search engines. Many users reach a website through a search engine, and frontend developers directly determine whether pages can be indexed and ranked. Frontend developers impact…
Frontend developers need five things in <head for SEO: title, description, robots, canonical and Open Graph. People call them all "meta tags" for convenience, but <title is its own element and canonical is a <link; only description and robots are <meta tags. Title (<title): the…
Rendering strategy decides whether content is already in the HTML the server returns or only appears after JS runs — CSR carries the highest risk, SSR/SSG are the safest choices. CSR (Client-Side Rendering): The initial HTML is essentially empty; JS renders the content — Google…
Core Web Vitals (CWV) are three metrics measuring real user experience, and have been a Google ranking signal since 2021. INP replaced FID in March 2024. LCP (Largest Contentful Paint): how long it takes to render the largest element in the first screen (hero image,…
Amend the last commit — only when the commit has NOT been pushed: If already pushed (your own branch only): Note: - --amend creates a NEW commit with a different hash — it does not edit in place - NEVER amend commits on main/develop or…
Merge: creates a merge commit that joins the two branches and keeps the full history. git log --graph still shows the branch splitting off and coming back. Merge never modifies existing commits. Rebase: takes each commit of the current branch and reapplies it on top…
The hardest conflict is not a simple add/delete but one where both sides refactored the structure: a function was renamed, logic was reorganized. The conflict markers then only show two different blocks of code, not what each side intended. Safe process: 1. Understand context before…
A commit already on main that others have pulled calls for git revert; use git reset only on a local branch nobody else has. git revert git reset --------- What it does Creates a new commit that undoes the old commit's changes Moves the branch…
The access token is short-lived; when it expires, the client uses the longer-lived refresh token to call the /token endpoint and get a new access token — without forcing the user to log in again. That is a "silent refresh". Why the access token must…
XSS (Cross-Site Scripting) is injecting malicious JS into a page so it runs in the victim's session — stealing tokens/cookies, impersonating, reading data. Three types: - Stored: the payload is saved on the server (a comment, a display name) and served to everyone who views…
The Same-Origin Policy blocks fetch/XHR from reading cross-origin data; CORS is how a server uses HTTP headers to permit other origins to read it. - Simple request (GET/HEAD/POST + a safelisted Content-Type): no preflight. - Preflighted: when using another method, a custom header, or Content-Type:…
An origin = scheme + host + port; two URLs share an origin only when all three match (different http/https scheme, different port, or different subdomain are all cross-origin). The SOP restricts cross-origin interactions: - Reads (fetch/XHR reading a response body) → blocked by default;…
A JWT (RFC 7519) has 3 parts separated by dots: header.payload.signature, each Base64URL-encoded. - Header: token type + signing algorithm (e.g. HS256). - Payload: the claims — statements about the subject + metadata. - Signature: signs header+payload with HMAC/RSA/ECDSA using a secret/private key → guarantees…
- Plain <script: fetches then executes immediately, blocking HTML parsing; multiple scripts run in order. - async: downloads in parallel while HTML parses, runs as soon as it finishes (can interrupt HTML parsing), with NO order guarantee between scripts. Good for independent scripts: analytics, ads.…
Tree-shaking is dead-code elimination: the bundler drops exports that are never imported from the production bundle. It relies on the static structure of ES modules: import/export have fixed names, so the bundler can tell at build time which module uses what. CommonJS is different: require()…
A closure is a function that keeps a reference to the scope where it was declared, so it can still read/write the parent scope’s variables even after the parent function has returned. The function "remembers" the environment that created it. - It is built on…
this depends on how a function is called, not where it is defined (except arrow functions). Priority: 1. new → this is the newly created object. 2. call/apply/bind → this is the value you pass. 3. Method call obj.fn() → this is obj. 4. Plain…
Hoisting: declarations are moved to the top of their scope at compile time — but initialization differs: var let / const --------- Scope function block {} Hoisted yes, initialized to undefined yes, but TDZ Access before declaration undefined ReferenceError Reassign allowed let yes, const no…
Every object has a hidden [[Prototype]] link (read via Object.getPrototypeOf, or proto) pointing to another object. When you access a property the object lacks, the engine walks up the prototype chain until it finds it or hits null. That is the prototype chain. - obj.hasOwnProperty(k)…
- === (strict): compares both type and value, no coercion. 1 === '1' → false. - == (loose): coerces the two sides to a common type before comparing, producing many surprising results. Surprising == cases: - 0 == '' → true - 0 == false…
Callbacks: pass a function to call when done. Nesting several async callbacks → "callback hell": hard to read, hard to handle errors, and inversion of control. Promises: an object representing a future result, with 3 states pending → fulfilled rejected. Benefits: - Flat chaining with…
A DOM event travels in 3 phases: capturing (from window down to the target) → target → bubbling (from the target back up). By default addEventListener listens in the bubbling phase; pass { capture: true } to listen during capturing. - event.target = the element…
Both limit how often a rapidly-triggered function runs, but differently: - Debounce: collapse many calls into one — run only after triggering stops for wait ms. Each new call resets the timer. - Use for: search-as-you-type (wait until the user pauses), form validation, auto-save, handling…
- Destructuring: pull values out of arrays/objects into variables. - const [a, b] = arr, const { x, y } = obj. - Rename { x: newX }, defaults { x = 0 }, nesting, and function parameters. - Spread ...: "spreads" elements out. -…
All three are pure (they do not mutate the original), return a new value, and suit a declarative style: - map: transforms each element, returns a same-length array. [1,2,3].map(x = x 2) → [2,4,6]. - filter: keeps elements matching a predicate, returns a shorter-or-equal array.…
Objects/arrays are reference types; b = a copies only the reference, so mutating b also mutates a. - Shallow copy: copies one level; nested properties still share references. - How: { ...obj }, Object.assign({}, obj), arr.slice(), [...arr]. - Enough for flat data (common when doing…
All three store data on the client but differ clearly: Cookie localStorage sessionStorage ------------ Size ~4KB ~5–10MB ~5–10MB Sent with requests Yes (every HTTP request) No No Lifetime per Expires/Max-Age until cleared ends when the tab closes Scope per domain/path per origin per origin +…
Every element is a box with 4 layers from inside out: content → padding → border → margin. - Default content-box: width/height count only the content; padding and border are added on top of the rendered size. Setting width: 200px; padding: 20px; border: 2px →…
When multiple rules target the same element, the browser picks the one with the highest specificity, computed as a triple (A, B, C): - A — number of ID selectors (id). - B — number of classes, attributes, pseudo-classes (.x, [type], :hover). - C —…
- Flexbox = one-dimensional layout (a row or a column). It distributes space along one axis; great when the item count is dynamic and you want them to grow/shrink/wrap. - Main axis: flex-direction, justify-content (main axis), align-items (cross axis), gap, flex: 1. - Use for:…
- static (default): normal flow; top/left/z-index have no effect. - relative: still occupies its slot in flow but shifts via top/left… relative to its own original position. Often used as an anchor for absolute children. - absolute: removed from flow (takes no space); positioned against…
Both are font-size-relative units, but reference different bases: - rem (root em): always relative to the root <html font-size. One single base → consistent and predictable, no cascading. - em: for the font-size property, relative to the parent’s font-size; for other properties (padding, margin, width...),…
Virtual DOM (VDOM): a lightweight JS-object description of the UI mirroring the real DOM tree. Operating on objects is far cheaper than touching the real DOM. When state/props change, React: 1. Builds a new VDOM tree for the render. 2. Reconciliation / diffing: compares the…
key gives React a stable identity for each list item across renders. That lets the diff know which items are kept, added, removed, or reordered instead of rebuilding everything. Why not use the array index as key: when the list is inserted into / removed…
Rules of Hooks (required so React lines up state correctly across renders): 1. Only call hooks at the top level — not inside if, loops, or nested functions (React 19's use() is the exception and may be called inside if/loops). React identifies hooks by call…
The distinction is where the form input’s value lives: - Controlled: React state is the single source of truth. The input takes value={state} and updates via onChange. React controls every keystroke. - Pros: easy instant validation, disabling buttons, formatting while typing, syncing multiple fields. -…
The four differ in where and when the HTML is built. CSR builds it in the browser, SSR on the server for every request, SSG once at build time, and ISR is like SSG but rebuilds the page after a set interval. CSR SSR SSG…
Both describe the shape of an object and are mostly interchangeable. The core differences: - interface: extended with extends, and supports declaration merging — same-name declarations merge into one. Good for library public APIs (library users can declare more to add to the type) and…
A generic parameterizes types: you write a function/class/type that works over many types while preserving the relationship between them. - function identity<T(x: T): T — T is inferred from the argument, and the return keeps that exact type. - Constraint: <T extends { id: number…
TypeScript ships types that transform a base type, letting you derive rather than redeclare (DRY): - Partial<T — makes every field optional (good for update/patch payloads). - Required<T — makes every field required. - Pick<T, K — selects a subset of fields K from T.…
- React.lazy(() = import('./X')) declares a dynamically loaded component: the bundler splits it into its own chunk, fetched only when the component actually renders → code splitting. - <Suspense fallback={...} wraps the lazy component (or a component reading data via a Suspense-enabled data library) and…
An error boundary is a class component implementing static getDerivedStateFromError() and/or componentDidCatch(); it catches rendering errors in its child tree and shows fallback UI instead of crashing the whole app (blank screen). Catches: errors during render, in lifecycle methods, and in the constructors of child…
Context passes data through the component tree without threading props at every level (prop drilling): createContext → <Provider value → useContext. A key caveat: Context is not a state manager. Every consumer re-renders when value changes (even if it only reads a small part) →…
Instead of shipping one big bundle for the whole app, code splitting breaks it into on-demand chunks → less JS to parse/execute up front, fewer long main-thread tasks (TBT), and better responsiveness (INP). - Dynamic import('./mod') returns a Promise; the bundler (webpack/Vite) splits a separate…
- CommonJS (traditional Node.js): require() / module.exports, loads synchronously at runtime and is dynamic (you can require inside an if). Its module structure is not fully statically analyzable. - ES Modules (the language standard): import / export, a static structure — analyzable at build time,…
Memoization = caching a result by its input: when the input repeats, return the stored result instead of recomputing. React gives you three tools: - useMemo(fn, deps): remembers the value of an expensive computation; recomputes only when deps change. - useCallback(fn, deps): remembers a function…
JavaScript has 7 primitive types (string, number, boolean, undefined, null, symbol, bigint) and reference types — objects, arrays, functions. - Copying: assigning a primitive to another variable copies the value — the two variables are independent. Assigning an object only copies the reference — both…
Arrow functions are not just shorter syntax — they differ from regular functions in four ways: - this: an arrow has no this of its own — it captures this from the enclosing scope at definition time (lexical) and cannot be changed via call/apply/bind. A…
All three make an element "disappear" but differ in layout, interaction, and a11y: - display: none: removes the element from the layout — takes no space, is not rendered, descendants are hidden with no way to opt back in. Removed from the accessibility tree (screen…
Responsive design = one codebase that renders well at every screen size, instead of a separate mobile site. Three key pieces: - Viewport meta: <meta name="viewport" content="width=device-width, initial-scale=1" — tells mobile browsers to render at the device's real width instead of emulating a ~980px desktop…
Both are scripts running on a separate thread, off the main thread and without DOM access — but their roles differ entirely: - Web Worker: a computation thread for one page. Use it to move CPU-heavy work (parsing large files, image processing, data crunching) off…
fetch is the modern standard API replacing XHR: - Returns a Promise → works directly with async/await instead of onreadystatechange callbacks. - Cleaner API with Request/Response objects, supports streaming bodies, and is the only way to make HTTP requests inside a Service Worker (XHR is…
The browser caches responses based on server headers, so repeat visits skip re-downloading assets: - Cache-Control: max-age=N — the response stays "fresh" for N seconds; within that window the browser uses the cached copy without asking the server (fastest path). Add immutable to signal the…
- SPA (Single-Page Application): the server returns one initial HTML page, then JavaScript takes over — "page" changes happen via client-side routing (updating the URL through the History API and rendering a new view) without a browser reload. React/Vue/Angular are typical SPA tools. - MPA…
A component re-renders when: - Its own state changes (setState/useState/useReducer). - Its parent re-renders — by default React renders the entire subtree, whether or not props changed. Common misconception: "props changed" is not an independent trigger — the child renders because the parent rendered. -…
Both represent "no value" but differ in meaning and origin: - undefined: a declared-but-unassigned variable, a missing function argument, a non-existent property, or a function with no return — set by the engine. It means "nothing yet". - null: explicitly assigned by the programmer to…
When a value is used in a boolean context (if, !, &&, , the ternary operator), JS coerces it to true or false. Values that coerce to false are falsy; everything else is truthy. There are exactly 8 falsy values (memorize them all): - false…
These three display values decide how an element takes part in layout flow: block inline inline-block ------------ Starts a new line Yes (takes the whole row) No (sits on the same line) No (same line) width/height Respected Ignored Respected Vertical margin/padding Fully applied (pushes layout)…
Both are data that drive what a component renders, but they differ in ownership and mutability: - Props (properties): data passed down from a parent to a child. To the receiving component, props are read-only — you must not modify them. Data flows one-way, top-down.…
The HTTP method signals a request’s intent: - GET — retrieve data, no body, safe (no state change) and idempotent; cacheable. - POST — create / submit data; not idempotent (calling twice creates two records). - PUT — replace an entire resource; idempotent (repeats give…
- Optional chaining ?.: access nested properties / call methods without erroring on null/undefined. user?.address?.city — if user or address is null/undefined, it returns undefined instead of throwing a TypeError. Works with properties (a?.b), indexing (a?.[i]), and calls (fn?.()). It short-circuits: on a nullish value…
Map — a collection of key–value pairs, replacing objects used as dictionaries: - Keys of any type (objects, functions, numbers...), unlike objects (keys are coerced to string/symbol). - Preserves insertion order when iterating. - Has .size and set/get/has/delete; iterate directly with for...of. - No inherited…
Four combinators take an array of promises and differ in their settle condition: - Promise.all: waits for all to fulfill → returns a results array in order. Fail-fast: a single rejection rejects immediately with that error (it does not wait for the rest). Use when…
0.1 + 0.2 → 0.30000000000000004: JS's number type is an IEEE 754 double (64-bit floating point). Fractions like 0.1 and 0.2 cannot be represented exactly in binary (much like 1/3 never terminates in decimal), so the addition accumulates a tiny rounding error. This affects every…
useRef returns a { current } object that is stable across every render (the same reference). Mutating ref.current does not trigger a re-render. Two main uses: 1. Referencing a DOM node: attach ref={myRef} in JSX and act on it directly — inputRef.current.focus(), measuring getBoundingClientRect(), controlling…
Both manage component state; useReducer is the more general form for complex update logic. - useState: update directly via a setter — good for simple, independent state (a boolean flag, an input string). - useReducer(reducer, initialState): gathers update logic into a pure reducer (state, action)…
IntersectionObserver is a browser API that asynchronously watches when an element intersects the viewport (or a scrollable ancestor), calling a callback when visibility crosses the thresholds you set. Why it beats listening to scroll + getBoundingClientRect(): - scroll events fire very frequently and handlers run…
A data-fetching view has four states, not one, and I design all four up front: loading, error, empty (succeeded but no data), and success with data. Missing empty is the classic bug — an empty list shows an endless spinner or a blank screen. -…
Because React state is a snapshot of the current render: setState does not mutate the variable immediately — it requests a new render; every line after it in the same handler still reads the old snapshot. Batching: React groups multiple setState calls in one event…
Redux is one global store with a one-way data flow: 1. The UI dispatches an action — a plain object describing "what just happened": { type: 'cart/itemAdded', payload: item }. 2. The action passes through middleware (if any) — the only place allowed to perform…
Core Web Vitals are the three metrics Google uses to assess page experience (and a search ranking signal), computed over real users at the 75th percentile: - LCP (Largest Contentful Paint) — loading: when the largest content element in the viewport finishes rendering. Good ≤…
The main techniques, ordered by what you should reach for today: 1. Flexbox — the default for most cases: 2. Grid — the shortest: 3. position: absolute + translate — when the element leaves the flow (overlay, modal): Use translate(-50%) rather than fixed negative margins…
CSRF (Cross-Site Request Forgery) abuses the fact that browsers auto-attach cookies to every request to a site. The attacker lures a logged-in user to a malicious page, which silently sends a request to the victim site (e.g. a transfer or email-change form). The request carries…
They solve two different problems. Server Action — mutations originating from your own UI: - Binds directly to <form action={...} or is called from a client component; no hand-written fetch plus endpoint. - Works even before JS loads (progressive enhancement with forms). - After writing,…
Next.js splits environment variables into two clear groups: - No prefix (DATABASEURL, STRIPESECRETKEY): server-only — Server Components, Route Handlers, Server Actions. Reading them on the client yields undefined. - NEXTPUBLIC prefix (NEXTPUBLICGAID): inlined into the source at build time and shipped inside the JavaScript bundle…
The error happens because Next.js renders that component on the server (Node), where window/document do not exist. Chart, editor, and map libraries often touch the DOM at import time. ssr: false tells Next.js to skip the component during server rendering and mount it only on…