Interview questions · free
Frontend Developer interview questions and answers
29 questions Frontend Developer interviews in India ask, grouped by the 7 skills they test, with a short model answer for each. Then the HR round every job has. Try each one out loud before you open the answer.
- 29 questions
- 7 skills
- 17 for freshers
- Updated 30 Oct 2026
First mock interview free: 3 questions, a score and feedback on each · No card needed
Answer out loud first. Read the question, say your answer as you would in the room, then open the model answer and compare. Interviewers ask follow-ups, so learn the reasoning, not the words.
JavaScript · Core skill
Core language
Frameworks change, but every frontend interview checks core JavaScript first: coercion, scope, closures and this explain most of the bugs you will meet in a UI.
What is the difference between == and ===? What do 0 == '' and null == undefined return?Fresher
=== is strict equality: it compares type and value, with no conversion. == is loose equality: if the types differ, JavaScript converts them first, which gives surprising results. 0 == '' is true, because the empty string becomes the number 0. null == undefined is true by a special rule, but null == 0 is false. And NaN isn't equal to anything, even itself, so use Number.isNaN to test for it.
In practice, use === everywhere. The one common exception is value == null, which checks for both null and undefined at once. Interviewers often follow up with falsy values: 0, '', null, undefined, NaN and false.
What is hoisting? How do var, let and const behave differently?Fresher
Hoisting means declarations are processed before the code in their scope runs. A var is hoisted and set to undefined, so reading it before its line gives undefined instead of an error. let and const are hoisted too, but stay in the temporal dead zone until their line runs, so reading them early throws a ReferenceError. Function declarations are hoisted completely, so you can call them before they appear.
The other difference is scope: var is function-scoped, while let and const are block-scoped, limited to the nearest braces. const stops reassignment, not mutation: a const array can still be pushed to. Use const by default and let when the value must change.
What is a closure? Where would you use one in a frontend app?Fresher
A closure is a function that remembers the variables from the scope where it was created, even after that outer function has returned. Every function in JavaScript does this.
A practical frontend example is debouncing a search box. A debounce function keeps a timer variable in its scope and returns a new function. Each keystroke clears the old timer and starts a new one, so the API is called only when the user stops typing for, say, 300 ms. The timer survives between calls because the returned function closes over it. Closures also explain why a React event handler can read stale state from an earlier render.
You pass an object's method as a click handler and this is no longer the object inside it. Why, and how do you fix it?1-6 years
In JavaScript, this is decided by how a function is called, not where it's written. user.greet() sets this to user, but passing user.greet as a callback passes only the function, so the link to user is lost. Passed to addEventListener, this becomes the element; passed as a plain callback, it's undefined in strict mode, which class bodies always use.
There are three usual fixes: bind it (this.greet = this.greet.bind(this)), wrap the call in an arrow function (() => user.greet()), or define the method as an arrow-function class field, since arrow functions take this from the surrounding scope. Mention that arrow functions are the wrong choice for object methods that need their own this.
UI framework · Core skill
Components and props
Most frontend openings in India are React roles, so expect questions on how components, props and lists really work, then a design question on structuring components.
What is JSX, and what does it turn into? Why can't a component return two sibling elements directly?Fresher
JSX is a syntax extension that lets you write HTML-like markup inside JavaScript. Browsers don't understand it: a compiler such as Babel, or the one inside Vite, turns each element into a function call that creates a plain object describing the UI, which React then renders. Because a function returns one value, a component must return a single element. To return siblings without adding an extra div, wrap them in a Fragment, written as an empty pair of tags.
Also mention the small differences from HTML: className instead of class, htmlFor instead of for, camelCase event names like onClick, and curly braces for any JavaScript expression.
Why does React need a key when rendering a list? What goes wrong if you use the array index as the key?Fresher
When a list re-renders, React uses keys to match each new item with the old one, so it can keep, move or remove the right elements instead of rebuilding them all. A key must be stable and unique among siblings, usually the item's id from the data.
The index is fine only for a static list that never changes order. If items are inserted, deleted or sorted, each item's index changes, so React matches the wrong components: an input keeps text typed into a different row, or a checkbox stays ticked on the wrong item. Don't generate keys with Math.random() either, since a new key on every render remounts the item and loses its state.
What is the difference between props and state? Can a child component change its own props?Fresher
Props are inputs passed from a parent to a child, like function arguments. State is data a component owns and changes over time, such as whether a dropdown is open. When either changes, the component re-renders.
A child must never change its props: they're read-only, and React relies on that to keep data flowing one way, from parent to child. If a child needs to change something, the parent keeps it in state and passes down both the value and a function to update it, such as value and onChange. A useful rule: if a value can be calculated from props or other state, don't store it in state at all; calculate it during render.
A Modal component has grown to fifteen props like showHeader, title, footerButtons and hideClose. How would you redesign it?1-6 years
That's a sign the component is trying to configure every layout through props. Use composition instead: let the Modal handle only what's common, such as the overlay, focus handling and closing on Escape, and let callers pass the content as children. For structured parts, offer small pieces such as Modal.Header, Modal.Body and Modal.Footer (a compound component), or slot props like footer that accept any element.
Each screen then builds the modal it needs without a new prop for every variation, and the Modal's own code stays small and easy to test. Mention that you'd migrate gradually, keeping the old props working while screens move to the new API.
Web platform · Core skill
HTML and CSS
A frontend developer is expected to build any design by hand, on every screen size, so interviewers test HTML structure and CSS layout as seriously as JavaScript.
What is semantic HTML, and why does it matter? Give examples.Fresher
Semantic HTML means using elements for what they mean, not just how they look: header, nav, main, article, section, aside and footer for page structure, button for actions, a for links, and h1 to h6 in order for headings. A div with a click handler can look like a button, but it isn't one.
It matters because screen readers use these elements to announce the page and let users jump between landmarks and headings; a real button works with the keyboard for free; and search engines understand the content better. It also makes the code easier to read. A common mistake is choosing a heading level for its size; choose it for structure and style it with CSS.
Explain the CSS box model. A div has width 200px, padding 20px and a 2px border. How wide is it on screen?Fresher
Every element is a box made of content, then padding, then border, with margin outside. By default box-sizing is content-box, so width sets only the content. That div is 200 + 20 + 20 + 2 + 2 = 244px wide; margin adds space around it but isn't part of the box.
With box-sizing: border-box, the width includes padding and border, so the div stays 200px and the content shrinks to 156px. Most projects set border-box on every element because it makes layouts much easier to predict. Interviewers sometimes follow up with margin collapsing: vertical margins between block elements merge into the larger one instead of adding up.
When would you use Flexbox and when would you use CSS Grid?Fresher
Flexbox lays items out in one direction, a row or a column, and is best for sharing space among items whose size comes from their content: a navbar, a row of buttons, centring something, or a card header with a title on the left and an icon on the right. Grid works in two dimensions at once, rows and columns, so it suits page layouts, dashboards and card galleries where items must line up both ways.
They work well together: Grid for the page structure, Flexbox inside each component. For example, grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)) gives a responsive card grid without a single media query.
On some phones your page scrolls sideways and the layout looks broken. How do you find and fix the cause?1-6 years
First check that the page has the viewport meta tag (width=device-width, initial-scale=1); without it, phones render a desktop-width page. Then find the element that is wider than the screen: in DevTools device mode, scroll sideways and inspect what sticks out, or temporarily outline every element with a CSS rule.
The usual causes are fixed pixel widths, images or tables without max-width: 100%, long words or URLs that don't wrap (overflow-wrap: anywhere fixes them), 100vw combined with a scrollbar, and negative margins. Fix the cause with fluid widths and wrapping rather than hiding it with overflow-x: hidden on the body, which can also break sticky elements. Then check on a real phone.
JavaScript
TypeScript
Most new React codebases use TypeScript, so interviewers check that you can type props and API data properly instead of reaching for any.
What is the difference between an interface and a type alias in TypeScript?Fresher
Both describe the shape of an object, and for props or API responses either works. The differences: an interface can be extended with extends and can be declared twice, with the two declarations merged, which is useful for adding to a library's types. A type alias can describe things an interface can't, such as unions (type Status = 'idle' | 'loading' | 'error'), tuples, and types built from other types with mapped or conditional types.
Many teams use interface for object shapes and type for unions and combinations, or simply pick one and stay consistent. Saying you follow the project's convention is a perfectly good answer.
What is the difference between any and unknown? Why do teams try to avoid any?Fresher
Both can hold any value, but any switches type checking off: you can call any method on it and TypeScript won't complain, so mistakes reach the browser. unknown is the safe version: you can't use the value until you narrow it with a check such as typeof value === 'string', Array.isArray, or a type guard.
That makes unknown right for data whose shape you don't control, like a parsed JSON response, or a caught error, which is unknown in a catch block under strict settings. Teams avoid any because it spreads silently through everything it touches. If a type is genuinely hard, use unknown and validate the data, for example with a schema library such as Zod.
Your API returns a User type. The edit form sends only some fields, and the list shows only id and name. How do you type these without repeating yourself?1-6 years
Derive them from the one User type with utility types, so a change to User flows everywhere. The edit payload can be Partial<User>, which makes every field optional, or better, Partial<Pick<User, 'name' | 'email' | 'phone'>>, so only editable fields are allowed. A list row can be Pick<User, 'id' | 'name'>, and a create form Omit<User, 'id' | 'createdAt'>, since the server sets those.
Other useful ones are Required, Readonly and Record, for example Record<string, User> for a lookup by id. Mention that these types exist only at compile time: if the API might change shape, validate the response at runtime as well.
Reading an answer isn't the same as giving one
In a mock interview you answer new Frontend Developer questions out loud or typed, and every answer is scored, with what to fix and a stronger answer.
Web platform
Browser and networking
Frontend developers own what happens in the browser, so interviewers ask about storage, CORS errors and rendering performance, which come up in real projects every week.
What is the difference between localStorage, sessionStorage and cookies?Fresher
All three store small amounts of data in the browser for one site. localStorage keeps data until it's cleared, across tabs and restarts. sessionStorage belongs to one tab and is cleared when the tab closes. Both hold only strings (store objects with JSON.stringify), usually around 5 MB per site, and are read only by JavaScript, never sent to the server automatically.
Cookies are small, about 4 KB each, and are sent to the server with every matching request, which is why they're used for login sessions. A cookie marked HttpOnly can't be read by JavaScript, which protects it from XSS, and Secure and SameSite control when it's sent. Never keep secrets in localStorage.
Your React app on localhost:3000 calls an API on localhost:8080 and the console shows a CORS error. What does it mean, and how is it fixed?1-6 years
Browsers follow the same-origin policy: a page may only read responses from its own origin, which is the scheme, host and port together. Ports 3000 and 8080 are different origins, so the browser blocks your code from reading the response unless the server allows it with an Access-Control-Allow-Origin header. For requests with a JSON body, methods like PUT, or an Authorization header, the browser first sends an OPTIONS preflight request, which the server must answer too.
The fix belongs on the server: allow your frontend's exact origin, not *, especially when cookies are sent. In development, the Vite or webpack dev-server proxy avoids the problem. Postman works fine because CORS is enforced only by browsers.
What is the difference between reflow and repaint? An animation on your page is janky. How would you fix it?1-6 years
Reflow, or layout, is when the browser recalculates the size and position of elements, for example after changing a width, adding elements or changing font size. It can affect much of the page, so it's expensive. Repaint redraws pixels without changing layout, such as a colour change. Cheapest of all are transform and opacity, which the browser can usually animate on the compositor without layout or paint.
So animate transform and opacity instead of top, left, width or height. Also avoid layout thrashing: reading values like offsetHeight right after writing styles, inside a loop, forces a reflow each time, so batch the reads, then the writes, or use requestAnimationFrame. Confirm the fix in the DevTools Performance panel.
Web platform
Accessibility
Banks, government projects and global clients increasingly require accessible interfaces, and frontend developers are the ones who build them, so interviewers check you know the basics.
What do you check to make a web page accessible? Name the basics.Fresher
Accessibility means people using screen readers, keyboards, zoom or voice control can use the page too. The basics I check: semantic elements and a logical heading order; alt text on meaningful images and an empty alt on decorative ones; a visible label for every form field; everything usable with the keyboard alone, with a visible focus outline; enough colour contrast, which WCAG level AA sets at 4.5:1 for normal text and 3:1 for large text; and never using colour alone to show an error.
Then I test: tab through the page, run Lighthouse or axe, and try a screen reader such as NVDA or VoiceOver on the main flow. Automated tools catch only some of the problems.
What is ARIA? When should you not use it?1-6 years
ARIA is a set of attributes that tell assistive technology what an element is and what state it's in, when HTML alone can't: role, aria-label for an icon-only button, aria-expanded on a menu button, aria-live for messages that appear without a page load, and aria-describedby to link an error message to its field.
The first rule is not to use ARIA when a native element does the job: a real button already has the role, focus and keyboard support that a div with role="button" lacks. ARIA changes only what is announced, not how the element behaves, so wrong ARIA is worse than none. A good example to give is aria-live on toast messages so screen readers announce them.
How would you make a custom modal dialog accessible?1-6 years
First check whether the native dialog element with its showModal() method fits, since it handles much of this for you. For a custom modal: give the container role="dialog" and aria-modal="true", with aria-labelledby pointing to its title. When it opens, move focus inside it, usually to the title or the first field. Keep focus trapped inside while it's open, so Tab and Shift+Tab cycle through its controls. Escape should close it, and closing should return focus to the button that opened it. The page behind should be inert, so neither the keyboard nor a screen reader can reach it.
Then test it with the keyboard alone and with a screen reader.
Testing
Component testing
Product companies expect frontend developers to write their own component tests, so interviewers ask how you test what users see rather than internal details.
How would you test a counter component whose button increases a number on the screen?Fresher
With React Testing Library and Jest or Vitest, I'd test it the way a user uses it. Render the component, find the button by its role and name with screen.getByRole('button', { name: /increase/i }), click it with userEvent, then assert that the display shows 1, for example with toHaveTextContent('1').
I wouldn't check the component's internal state or which function was called, because those are implementation details: the test should still pass if the component is rewritten with a reducer. userEvent is preferred over fireEvent because it simulates the whole interaction, including focus and keyboard events. Its methods return promises, so await them.
Why does Testing Library recommend getByRole over getByTestId? What is the difference between getBy, queryBy and findBy?1-6 years
getByRole finds elements the way assistive technology does, by role and accessible name, so the test checks what users experience and fails if, say, a button loses its label. A data-testid ties the test to markup users never see; keep it as a last resort for elements with no role or text.
getBy returns the element, or throws at once if it's missing or there are several. queryBy returns null instead of throwing, so use it to assert that something is not on the screen. findBy returns a promise and retries until the element appears or a timeout passes, for content that shows up after an API call or a timer. Using getBy for async content is a common cause of failing tests.
How do you test a component that loads data from an API? What would you check?1-6 years
Don't call the real API, or tests become slow and unreliable. Either mock the fetch layer with vi.fn or jest.fn, or, better, use Mock Service Worker (MSW), which intercepts requests at the network level so the component's real fetching code runs. Then test the states a user sees: a loading indicator first, then the data, found with findByText, and an error message when the mocked response is a 500 or the network fails. If there's a retry button, click it and check the data appears.
Reset mocks and handlers between tests, and check the request had the right parameters when that matters. The error state is the one most candidates forget to test.
Every job
HR and behavioural round
Frontend developers work between designers, backend teams and users, so the HR round looks for clear communication, ownership of what you ship, and how you keep learning.
Tell me about yourself.Fresher
Keep it to about a minute and lead with what you've built, since frontend work is easy to show. For example: "I'm a [degree] graduate from [college]. I've been building web interfaces for [time], mainly with React and TypeScript. My best project is [project], a [what it does] used by [who], where I built [feature] and raised its Lighthouse performance score from [x] to [y]. It's live at [link] and the code is on GitHub. I'm looking for a frontend role where I can work closely with designers and learn to build at scale."
Have the project open on your phone in case they ask to see it.
Why frontend development and not backend?Fresher
Give a genuine reason that shows you understand the work, not that it seems easier. For example: "I like that my work is visible to users straight away, and that small details, like a loading state or a clear error message, decide whether people trust a product. In [project] I most enjoyed [specific thing: making it fast on slow phones, making a form work with a screen reader]. I know enough backend to work well with that team, but the user's side is where I want to go deep."
Avoid saying you dislike backend or that frontend needs less logic: modern frontend is full of it.
A designer hands you a design that will be slow or awkward on phones. What do you do?1-6 years
Show that you raise problems early, with evidence, and work with the designer rather than overruling them. A structure: understand the intent, show the issue, propose options. For example: "A design used a full-screen video background on the home page. I built a quick version and showed the designer it took [x] seconds to load on a mid-range phone on 4G. We agreed on a still image on mobile, with the video only on wide screens, and the page met our load-time target."
Interviewers want to hear that you didn't silently change the design, and didn't silently ship something slow either.
Frontend tools change every year. How do you keep up, and how do you decide what to learn?Fresher
Show a habit, not a list of trending names. A structure: how you learn, how you filter, a recent example. For example: "I read the official docs and release notes for the tools I use, like React and TypeScript, and follow a couple of newsletters. I don't chase every new library; I learn one when it solves a problem I actually have. Recently [example: I learned TanStack Query because my project's data-fetching code had become hard to manage], and it [result]."
A strong point to add: fundamentals such as JavaScript, CSS and how the browser works last longer than any framework.
Tell me about a bug of yours that reached users. What happened, and what did you change?1-6 years
Pick a real, moderate bug, own it, and spend most of the answer on the fix and what you changed afterwards. Use STAR: "After a release, users on older iPhones couldn't submit the checkout form (situation). It was my change (task): I'd used a JavaScript feature their Safari version didn't support. I rolled it back within the hour, set the right browser targets in our build, and shipped the fix the same day (action). I then added that browser to our test list and set up error monitoring that alerts us to new frontend errors (result)."
Don't blame the testers, and don't pick a trivial typo.
Free interview questions, roadmaps and mock interviews: https://myskillgrid.com/interview-questions/frontend-developer/
Ready to answer them for real?
Your first Frontend Developer mock interview is free: 3 questions, a score and feedback for each, and a stronger answer to learn from, in about 10 minutes.