Preparing for a front-end developer interview can feel daunting. Fortunately, you don’t have to do it alone. At Orchestra, our AI interview assistant serves as a real-time copilot to help you practice and get instant feedback.* In this guide, we’ve reimagined 25 essential front-end developer interview questions – complete with fresh, approachable answers – to help you prepare with confidence. These questions cover the core of HTML, CSS, and JavaScript, along with responsive design, performance, and other key topics. Read on, and imagine having an AI interview copilot by your side as you master each question and answer.*
Let’s dive into the Q&A!
Answer: HTML, CSS, and JavaScript are the foundational trio of front-end development, each with a distinct purpose:
Think of a website like a house: HTML is the building’s frame, CSS is the paint and decor, and JavaScript is the electrical and plumbing systems that make the house functional. Together, these three technologies work in harmony to create the modern web experience. Being able to clearly distinguish their roles shows interviewers you understand the core front-end technologies and how they interrelate in building a web page.
Answer: The CSS Box Model describes how every element on a webpage is essentially a rectangular box, and how its spacing is calculated. Understanding the box model is crucial for layout and design because it affects an element’s total size and how it interacts with other elements. The box model consists of several components:
These layers stack up (content inside padding inside border inside margin) to determine the element’s total occupied space on the page. For example, if a <div>
has width 200px, padding 10px, border 2px, and margin 10px, its total width on the page is 200 + 210 (left & right padding) + 22 (left & right border) = 224px (not counting margins, which add extra space outside).
Why it matters: When you’re trying to size and align elements, you need to account for padding and border in addition to the content width/height. A common interview follow-up might be: “How would you make two elements sit side by side with equal spacing?” Knowing the box model helps here – you might adjust margins or padding accordingly. Mastery of the box model shows you can precisely control element spacing and layout, which is fundamental for implementing clean, professional designs.
<div>
element both horizontally and vertically?Answer: Centering a <div>
(or any element) horizontally and vertically was historically tricky, but modern CSS has made it straightforward. There are a few approaches:
display: flex
. Then add justify-content: center;
to center horizontally, and align-items: center;
to center vertically. This method is quick and works for flex container in one line:css
CopyEdit
.parent {
display: flex;
justify-content: center; /* centers horizontally */
align-items: center; /* centers vertically */
}
<div>
inside this parent, and it will be perfectly centered both ways.display: grid
, and use the shorthand:css
CopyEdit
.parent {
display: grid;
place-items: center; /* centers content in both directions */
}
css
CopyEdit
.child {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.parent { position: relative; }
<div>
50% from the top and left of the parent, then translate(-50%, -50%)
shifts the element up and left by half of its own width/height, resulting in perfect centering. Another simpler (horizontal-only) method is using margin: 0 auto;
on a block element to center it horizontally within a parent with a set width.For modern web development, Flexbox or Grid is preferred for centering because it’s cleaner and responsive. Interviewers often ask this to ensure you’re comfortable with these modern CSS techniques. Demonstrating both Flexbox and Grid solutions (and knowing an older fallback) shows strong knowledge of CSS layout methods.
Answer: Semantic HTML means using HTML elements that clearly describe their purpose and content, rather than just using generic tags. In other words, it’s writing HTML in a way that adds meaning to the markup. For example, using <header>
for page or section headers, <nav>
for navigation menus, <article>
for self-contained content, <section>
for thematic grouping of content, <footer>
for page footers, etc., instead of a bunch of non-descriptive <div>
or <span>
tags.
Why it’s important:
<nav>
element as “navigation region” or understand that an <h1>
is a top-level heading. This helps users with disabilities navigate the page more easily.<article>
tag might be more important, or that <header>
and <footer>
have auxiliary information. This can indirectly improve how your page is indexed and ranked.<aside>
or <main>
immediately convey what that content is (a sidebar and the main content area, respectively). This improves team communication and code quality.For example, compare a non-semantic versus semantic snippet:
html
CopyEdit
<!-- Non-semantic approach -->
<div id="top-banner"> ... </div>
<div class="navigation"> ... </div>
<div class="section"> ... </div>
<!-- Semantic approach -->
<header> ... </header>
<nav> ... </nav>
<section> ... </section>
The second version is immediately clearer. In summary, semantic HTML leads to better structured, more accessible, and more search-friendly webpages. Interviewers ask about this to ensure you write clean, professional HTML rather than relying on generic elements for everything.
Answer: Flexbox (Flexible Box Layout) is a CSS layout module designed to simplify arranging elements in one dimension (a row or a column) and distributing space flexibly among them. It’s ideal for creating responsive layouts and aligning items without using float hacks or complicated CSS. Here are key points about Flexbox:
flex-grow
, flex-shrink
, and flex-basis
, you can control how items flexibly resize relative to each other. This means you can create fluid grids or navigation bars that adapt to different screen sizes easily.justify-content
(for horizontal alignment) and align-items
(for vertical alignment), you can center elements or space them out (e.g., evenly spaced navigation links) with a single line of CSS. There’s also align-self
for individual item alignment and align-content
for multi-line flex containers.order
property (without altering the HTML) and easily switch horizontal to vertical layout (and vice versa) using flex-direction
(row vs. column).Example: Laying out three buttons in a toolbar:
css
CopyEdit
.toolbar {
display: flex;
justify-content: space-between; /* space out buttons evenly */
align-items: center; /* center buttons vertically (if toolbar has height) */
}
This will line up three buttons side by side, evenly spaced across the toolbar.
When to use it: Use Flexbox whenever you need a flexible, easy way to arrange items in a row or column. It shines in responsive design because elements can wrap or adjust size automatically. Interviewers ask about Flexbox to ensure you can create modern, adaptable UI layouts efficiently – a must-have skill for front-end developers.
Answer: To create a basic HTML form with fields for “Name” and “Email” and a submit button, you would use the <form>
element and appropriate <input>
fields. Here’s a simple example of what the HTML form might look like:
html
CopyEdit
<form action="#" method="post">
<!-- Name field -->
<label>
Name:
<input type="text" name="name" placeholder="Your name" required>
</label>
<!-- Email field -->
<label>
Email:
<input type="email" name="email" placeholder="you@example.com" required>
</label>
<!-- Submit button -->
<button type="submit">Submit</button>
</form>
Explanation:
<form>
tag wraps all form elements. In a real scenario, you’d set the action
attribute to the URL of the server endpoint that will process the form, and choose an HTTP method (get
or post
). In this example, action="#"
is just a placeholder.<input type="text" name="name" ...>
. We give it a name
attribute (“name”) which labels the data when the form is submitted. We also included placeholder
text for a hint and required
to indicate the field must be filled out.<input type="email" name="email" ...>
. Using type="email"
helps validate that the input looks like a valid email address. It also has a name
(“email”) and is marked required
.<label>
. Wrapping the input inside a label (or using a separate <label for="...">
) is good practice for accessibility, because it enlarges the clickable area and explicitly associates text (“Name:”, “Email:”) with the input field.<button type="submit">Submit</button>
. This button will submit the form data when clicked. (We could alternatively use <input type="submit" value="Submit">
– it behaves similarly.)This simple form doesn’t include any styling, but it contains all the essential parts: a form container, two labeled inputs, and a submit mechanism. An interviewer asking this question wants to see that you know the basic HTML form syntax and form best practices (like using appropriate input types and labels). It demonstrates your ability to capture user input – a fundamental skill for any web developer.
Answer: Web performance optimization is a big topic, but some key front-end techniques include:
loading="lazy"
attribute on <img>
tags (modern browsers) or implement lazy-load logic via JavaScript (load images as the user scrolls near them). This way, the initial page load only fetches what’s needed upfront.defer
or async
attributes on <script>
tags to avoid blocking page rendering.<link rel="preload">
for important resources to hint the browser to load them early.In practice, optimizing performance often means using build tools (like webpack, Parcel, or Vite) to automate minification, bundling, and code splitting. It also means testing your site (using tools like Google Lighthouse or GTmetrix) to identify bottlenecks.
When discussing this in an interview, try to mention a broad range of techniques (network-related, code-related, and asset-related) to show you understand performance holistically. Front-end performance is crucial because users tend to abandon slow sites, and search engines rank fast sites higher. Showing awareness of these techniques signals to an interviewer that you prioritize user experience and efficiency.
<img>
tag?Answer: The alt
attribute (alternative text) on an image tag serves several important purposes:
alt
text is to provide a textual description of the image for those who can’t see it. Screen readers will read out the alt
text to visually impaired users, so they can understand what the image represents. For example:html
CopyEdit
<img src="team-photo.jpg" alt="Team standing in front of company building">
alt
text in place of the image. This way, users still get an idea of what was intended to be there.alt
text to understand the content of images. A descriptive alt can help images appear in search results (e.g., Google Images) and can slightly improve the overall SEO of your page by reinforcing context. For instance, if your page is about JavaScript frameworks and you have an image of a chart comparing frameworks, an alt like alt="Bar chart comparing popularity of JavaScript frameworks"
provides relevant keywords and context to search engines.Tips for writing good alt text: Make it descriptive yet concise. You don’t need to say “image of…” (the screen reader already announces it’s an image). Instead, describe the content or function of the image. If the image is purely decorative (no informational value), it’s acceptable to use an empty alt attribute alt=""
so that screen readers simply skip it.
In summary, the alt
attribute improves accessibility for users and bots by describing images. Interviewers ask this to gauge if you understand web accessibility basics – a critical aspect of modern web development. Demonstrating that you use proper alt text shows you’re considering all your users and adhering to best practices.
Answer: Responsive web design is an approach to building web pages that adapt to different screen sizes and devices to provide an optimal viewing experience – whether on a large desktop monitor, a tablet, or a small smartphone screen. In a nutshell, a responsive website “responds” to the constraints of the device it’s viewed on.
Key elements of responsive design include:
width: 90%
instead of a fixed 900px
, so it automatically adjusts on smaller screens.img { max-width: 100%; height: auto; }
so images shrink with their container but don’t stretch beyond their natural size.css
CopyEdit
/* Default (mobile-first approach): single-column layout */
.gallery { display: block; }
/* When screen is at least 768px, switch to two-column layout */
@media (min-width: 768px) {
.gallery { display: flex; }
.gallery-item { width: 50%; }
}
.gallery-item
might take full width (one column). On wider screens (min 768px), the media query kicks in and we make .gallery
a flex container with two columns (each item 50%).em
or rem
) that can scale, and ensuring buttons/links have adequate size and spacing for touch controls on small devices.The goal of responsive design is one website that works everywhere. Users shouldn’t need to zoom or scroll horizontally on mobile; likewise, desktop users should see a well-laid-out design that isn’t just an overblown mobile site.
Interviewers ask about responsive design to verify that you know how to make a site usable on any device – which is absolutely essential in an era where a large portion of traffic is on smartphones. You might be prompted to discuss techniques or even coding strategies, so it helps to mention media queries and flexible layouts in your answer, as we did here.
Answer: Reversing a string is a common coding exercise. In JavaScript, strings don’t have a built-in reverse method, but you can reverse a string by converting it to an array, using the array reverse, then joining it back into a string. Here’s a simple and idiomatic way to do it:
js
CopyEdit
function reverseString(str) {
// Step 1: split the string into an array of characters
const chars = str.split(''); // e.g. "hello" -> ["h","e","l","l","o"]
// Step 2: reverse the array
const charsReversed = chars.reverse(); // ["h","e","l","l","o"] -> ["o","l","l","e","h"]
// Step 3: join the reversed array back into a string
return charsReversed.join(''); // ["o","l","l","e","h"] -> "olleh"
}
// Example:
console.log(reverseString("hello")); // Output: "olleh"
This outputs the reversed string. In one line, you often see it written as:
js
CopyEdit
const reversed = str.split('').reverse().join('');
Alternative approach: You could also reverse a string using a loop, building a new string character by character from the end:
js
CopyEdit
function reverseStringLoop(str) {
let reversed = '';
for (let i = str.length - 1; i >= 0; i--) {
reversed += str[i];
}
return reversed;
}
This does the same thing without converting to an array.
When giving this answer in an interview, it’s good to explain your approach in words (split into array, reverse, join back). It shows you understand how the solution works, not just memorized the code. Also, be mindful of Unicode complexity (some characters like emoji are multi-byte), but for basic interview purposes, the above solutions are typically sufficient. This question tests your basic algorithmic thinking and familiarity with string/array methods in JS.
Answer: A CSS preprocessor is essentially a scripting language that extends the default capabilities of plain CSS. You write styles in the preprocessor’s own syntax (which adds useful features), and then you compile that code into normal CSS that browsers can understand.
Why use a preprocessor? Because it makes writing and maintaining CSS more efficient and powerful. Some features they commonly add include:
$primary-color: #4CAF50;
.Examples of popular CSS preprocessors:
scss
CopyEdit
$base-color: #333;
.container {
color: $base-color;
.header {
background: lighten($base-color, 20%);
}
}
How it works in practice: You might write styles.scss
during development. Then a build tool or the Sass compiler processes that and outputs a styles.css
file which is what you include on your website. The end user’s browser never sees the SCSS/LESS/Stylus files – it only gets standard CSS.
When this question comes up, you should mention at least Sass and LESS as examples. Emphasize that preprocessors are there to make a developer’s life easier – they provide abstraction and convenience. Most modern workflows (though increasingly using CSS-in-JS or PostCSS plugins) are still influenced by what preprocessors brought to the table. Demonstrating familiarity with them shows you’re equipped to handle maintainable and scalable CSS in real-world projects.
Answer: Ensuring cross-browser compatibility can be challenging, but here are strategies to handle browser differences:
js
CopyEdit
if ('geolocation' in navigator) {
// Safe to use navigator.geolocation
} else {
// Fallback or notify user
}
.flexbox
or .no-flexbox
) that you can use in CSS to provide fallbacks.fetch()
to support older browsers that only have XMLHttpRequest, or polyfills for Promise
or Array.includes
for IE. You include these conditionally as needed.display: flex
, older browsers like IE10 needed ms-flexbox
, and older mobile WebKit needed webkit-flex
. Autoprefixer can add these automatically based on target browser support you configure.Example: Suppose you used CSS Grid for layout (which IE11 supports only partially). You could detect IE11 by a special CSS media query hack or use an @supports
rule:
css
CopyEdit
@supports not (display: grid) {
/* fallback flexbox layout for older browsers */
}
This applies alternate styles to browsers that don’t support grid.
Ultimately, the goal is to ensure functional experience on all browsers, even if some don’t get the enhanced visuals. Communicate to the interviewer that you prioritize a consistent user experience and you’re aware of tools and best practices (like using polyfills, prefixes, testing). They want to hear that you won’t ship something that mysteriously breaks on Firefox or Safari because you only tested in Chrome.
Answer: To determine if a number is prime, you need to check that it’s not divisible by any smaller number (other than 1). A straightforward approach:
Why up to the square root? Because if n
has a factor larger than sqrt(n), it must have a complementary factor smaller than sqrt(n). So checking up to sqrt(n) covers all possible factor pairs without redundancy.
Here’s a simple implementation in JavaScript:
js
CopyEdit
function isPrime(num) {
if (num < 2) return false; // 0, 1, and negative numbers are not prime
const limit = Math.sqrt(num);
for (let i = 2; i <= limit; i++) {
if (num % i === 0) {
// Found a divisor, not a prime
return false;
}
}
// No divisors found, it's prime
return true;
}
// Examples:
console.log(isPrime(2)); // true (2 is prime)
console.log(isPrime(15)); // false (15 is divisible by 3 and 5)
console.log(isPrime(17)); // true (17 has no divisors except 1 and 17)
This function efficiently checks primality for a single number.
In an interview, if asked, you might first explain the concept (checking divisors up to sqrt) and then either write or verbally describe the loop. If the number is very large, there are more complex algorithms, but for typical interview scenarios, this answer is sufficient. It demonstrates fundamental programming logic and understanding of loops, conditionals, and math – all good signs for a front-end developer who might face algorithmic challenges.
var
, let
, and const
in JavaScript?Answer: Yes. var
, let
, and const
are all used to declare variables in JavaScript, but they differ in terms of scope, reassignability, and hoisting behavior:
var
:var
is function-scoped (or globally scoped if declared outside a function). This means if you declare a var inside a function, it’s not accessible outside that function. However, if you declare it inside a block (like an if
or for
block), it ignores that block scope and is either function or global scoped. This can lead to bugs if you expect block scoping.var
are hoisted to the top of their scope, and initialized with undefined
. That means you can technically use the variable before the line where you declared it (though it will be undefined
at that point). Example:js
CopyEdit
console.log(x); // undefined
var x = 5;
console.log(x); // 5
var
variable in the same scope without errors (it will just override). E.g., var x = 1; var x = 2;
is allowed.var
variables to new values freely.let
: (introduced in ES6)let
is block-scoped. That means if you declare a variable with let
inside a { ... }
block (like inside an if statement or loop), it exists only within that block and its inner blocks. This is more intuitive for most use cases.let
(and const
) are also hoisted, but they’re not initialized. They cannot be accessed before their declaration line in the code. If you try, you’ll get a ReferenceError. This is sometimes called the “temporal dead zone” – the period between the start of the scope and the declaration line. So:js
CopyEdit
console.log(y); // ReferenceError! (since y is not defined yet in TDZ)
let y = 5;
let
variable in the same scope. For instance:js
CopyEdit
let a = 1;
let a = 2; // SyntaxError: Identifier 'a' has already been declared
let
variables (that’s why it’s called “let”, like let it be changed).const
: (also introduced in ES6)const
is also block-scoped, just like let
.let
in terms of hoisting – there’s a temporal dead zone, and you can’t use it before it’s declared.const
in the same scope (same rule as let).const
(short for “constant”) must be initialized at the time of declaration, and once set, you cannot reassign it to a new value. It’s meant for values that shouldn’t change. For example:js
CopyEdit
const PI = 3.1416;
PI = 4; // TypeError: Assignment to constant variable.
js
CopyEdit
const arr = [1, 2];
arr.push(3); // This is allowed (mutating content)
arr = [4, 5, 6]; // Not allowed (reassigning to new array)
When to use which? In modern JS development:
let
for variables that you plan to reassign (like loop counters, or values that will change).const
for values that should not be re-bound to a new value. This is often the majority of your variables; it doesn’t mean the value is immutable, but you treat the reference as constant.var
in new code. There’s almost no need for it now that let
and const
cover all use cases more safely. var
’s function scope and hoisting can cause bugs, so it’s mainly present for legacy reasons.Interviewers ask this question to ensure you understand modern JS best practices and the nuances of scope. A strong answer will mention block vs function scope and the non-reassignable nature of const
.
Answer: Event delegation is a technique where you take advantage of event bubbling to handle events at a higher level in the DOM rather than attaching individual handlers to a bunch of child elements.
In simpler terms, instead of adding an event listener to every single item, you add one event listener to a common parent element and have that listener respond to events coming from its children.
How it works:
<div>
, the sequence is: the button gets the click event first, then its parent <div>
, then perhaps a higher parent, all the way up to the document.<div>
. When any of its child buttons are clicked, the event bubbles up to the <div>
and triggers the handler there.event.target
(the actual element that was clicked) or use properties like event.currentTarget
(the element handling the event) to differentiate what to do.Why it’s useful:
<ul>
and handle the clicks through delegation. Fewer listeners can mean better performance.Example scenario: Imagine a table with 50 rows and each row has a “Delete” button. Instead of:
js
CopyEdit
document.querySelectorAll('.delete-btn').forEach(btn => {
btn.addEventListener('click', deleteRow);
});
You could do:
js
CopyEdit
document.querySelector('#tableBody').addEventListener('click', function(event) {
if (event.target.matches('.delete-btn')) {
// The clicked element is a delete button!
deleteRow(event);
}
});
Here, #tableBody
is a parent element (like the <tbody>
). We check if the actual clicked element event.target
matches the selector .delete-btn
. If so, we call deleteRow(event)
(which can figure out which row to remove, maybe by using event.target
).
This way, one listener handles all current and future “delete” buttons in the table.
In summary, event delegation leverages the structure of the DOM and bubbling to reduce the number of event listeners and gracefully handle dynamic content. Interviewers ask this to see if you write efficient, scalable DOM event handling code and understand the event propagation model in the browser.
Answer: A closure in JavaScript is a fundamental concept where an inner function retains access to variables from an outer function’s scope even after the outer function has finished executing. In other words, a closure is formed when a function is able to "remember" and continue to access its lexical scope (variables defined around it) at a later time, regardless of where that function is executed.
This sounds abstract, so let’s break it down with an example:
js
CopyEdit
function makeAdder(x) {
// x is a parameter to makeAdder
return function(y) {
// This inner function forms a closure.
// It has access to x, even after makeAdder finishes.
return x + y;
};
}
// Using the closure:
const add5 = makeAdder(5);
console.log( add5(3) ); // Output: 8 (because x=5, y=3)
const add10 = makeAdder(10);
console.log( add10(3) ); // Output: 13 (because x=10, y=3)
Here’s what’s happening:
makeAdder
is an outer function that takes x
and returns an inner function. That inner function takes y
and returns x + y
.makeAdder(5)
, it returns a new function (let’s call it F). At the time of that return, x
was 5. In JavaScript, that returned function closes over the variable x
. It remembers x = 5
.add5
. Now, even though makeAdder
’s execution context is gone, the variable x
(with value 5) is kept alive in closure for the function F. So when we later call add5(3)
, it adds 3 to the remembered 5 and returns 8.add10 = makeAdder(10)
creates a function that remembers x = 10
. Calling add10(3)
returns 13.Why closures are useful:
makeAdder
example) to create specialized functions (like add5
, add10
) that carry some preset data.Another quick example:
js
CopyEdit
function counter() {
let count = 0;
return function() {
count++;
console.log(count);
};
}
const increment = counter();
increment(); // 1
increment(); // 2
increment(); // 3
Each time we call increment()
, it increments and logs a count
that it remembers from the counter()
scope. No other part of the code can directly access or modify count
– only the closure function can. This is a closure providing a form of encapsulated state.
In an interview, to explain closures, it’s often best to describe it in your own words and then walk through a simple example like the ones above. The interviewer is checking that you understand how JavaScript scope works and how functions retain references to variables even after those outer function calls have ended. Closures are a powerful feature that every JS developer should grasp.
Answer: CSS frameworks (like Bootstrap, Tailwind, Foundation, Bulma, etc.) are collections of pre-written CSS (and often some JavaScript components) that provide ready-to-use styles and UI components. Here’s why developers use them:
col-md-6
, col-sm-12
, etc. for column widths at various breakpoints). This saves time and ensures consistency in responsive design.Potential downsides (to show you’re aware): Of course, frameworks can add a lot of extra CSS you might not use (making your site heavier if you don’t optimize). They also can make sites look somewhat "generic" if used without customization because many sites end up with the same Bootstrap look. However, you can override styles or use only parts of a framework as needed.
In summary, a developer might use a CSS framework like Bootstrap to save time and ensure a solid, responsive foundation for their UI. It’s about leveraging pre-built solutions for common UI problems so you can focus on unique aspects of your project. Interviewers ask this to see if you’re familiar with industry tools and can weigh their benefits vs writing custom CSS from scratch.
Answer: The modern way to fetch data from an API in the browser is to use the Fetch API or the newer async/await syntax built on promises. Here’s how you can do it using Fetch:
js
CopyEdit
// Using Fetch API with Promises:
fetch('<https://api.example.com/data>')
.then(response => {
if (!response.ok) {
throw new Error(`Network response was not ok: ${response.status}`);
}
return response.json(); // parse the JSON from the response
})
.then(data => {
console.log('Data received:', data);
// Here you can use the data (which is a JS object/array after parsing JSON)
})
.catch(error => {
console.error('Fetch error:', error);
});
A breakdown of this:
fetch(url)
initiates an HTTP request to the given URL and returns a Promise that resolves to a Response
object..then(response => { ... })
to handle the response. We first check response.ok
– this is a boolean indicating HTTP status in the 200-299 range. If not ok, we throw an error to be caught later.response.json()
also returns a promise that resolves to the parsed JSON (since the data comes asynchronously). We return that promise so the next .then
receives the actual data..then(data => { ... })
, we have the JavaScript object/array that was fetched. We can then use it to update the UI or whatever is needed..catch
at the end to handle network errors or any thrown errors (like from a non-OK response). This is important for debugging and graceful error handling.Alternatively, with async/await syntax, the same logic can be written more sequentially:
js
CopyEdit
async function fetchData() {
try {
const response = await fetch('<https://api.example.com/data>');
if (!response.ok) {
throw new Error(`Network error: ${response.status}`);
}
const data = await response.json();
console.log('Data received:', data);
// Use the data as needed
} catch (error) {
console.error('Fetch error:', error);
}
}
This does the same thing but might be easier to read for many. The async
keyword makes the function return a promise and allows using await
inside. We still catch errors with a try/catch around the awaits.
A few additional notes you might mention:
response.text()
or response.blob()
accordingly.XMLHttpRequest
or libraries like Axios/jQuery. But fetch is now widely supported (except IE, which would need a polyfill).js
CopyEdit
fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
});
In an interview, providing the promise chain example and perhaps noting async/await shows you’re comfortable with asynchronous operations in JavaScript, which is essential for web development. It demonstrates knowledge of how to interact with back-end APIs from the front end.
Answer: Data attributes (attributes that start with data-
, like data-user-id="123"
) are a way to embed custom data into HTML elements. They don’t affect the presentation or functionality by themselves, but they allow developers to store extra information in the markup that can be script-accessible.
Why use them:
data-id
attribute on the element. This keeps the data within the HTML, rather than needing a separate structure in JS to map IDs.data-product-name
, data-price
) to make the HTML more meaningful. It’s like adding your own custom attributes without breaking validation – the HTML5 standard explicitly allows any attribute that starts with data-
.How to use them:
In HTML:
html
CopyEdit
<div class="card" data-user-id="42" data-user-role="admin">
... card content ...
</div>
Here we stored a user ID and a role in a div
.
In CSS:
content
property in pseudo-elements or attribute selectors generally), you can select elements by data attribute. For instance:css
CopyEdit
.card[data-user-role="admin"] {
border: 2px solid red;
}
data-user-role="admin"
. This is a less common use but can be handy.In JavaScript:
element.getAttribute('data-user-id')
will give you "42" (as a string)..dataset
property which is an object of all data attributes. For the above example:js
CopyEdit
const card = document.querySelector('.card');
console.log(card.dataset.userId); // "42"
console.log(card.dataset.userRole); // "admin"
card.dataset.userId = 100
would change the attribute to data-user-id="100"
in the DOM.Use cases:
data-toggle="modal"
might be used by a JS component to know this element toggles a modal).In summary, data- attributes allow HTML elements to carry extra information in a standard, accessible way.* They’re especially helpful when building interactive applications where you might want to pass data from server-generated HTML to client-side scripts. Interviewers might ask this to confirm you know how to pass data around in the DOM cleanly and are aware of the dataset API.
Answer: In HTML/CSS, elements have a default display type, commonly inline or block (and there’s also inline-block which is a hybrid). These terms affect how elements flow and how you can style them:
<div>, <p>, <h1>-<h6>, <ul>, <li>, <section>, <article>, <header>, <footer>
etc.<span>, <a>, <strong>, <em>, <img>
(note: <img>
is inline by default, which surprises some, but it behaves like a replaced inline element).<img>
tags often behave like inline-block (as images have intrinsic dimensions), also <button>
and <input>
are inline-block by default (they don’t break line but you can set their width/height).<li>
an inline-block – they will sit next to each other, and you can control their size.Summary analogy:
Key differences to highlight to an interviewer:
Often, interviewers include this to test fundamental CSS knowledge. A good answer might also mention you can change an element’s display type using CSS (display: block;
or display: inline;
etc.), which can be useful if you want an element to behave differently (for example, making a list of links horizontal by changing <li>
to inline or inline-block).
Answer: JavaScript arrays have a built-in .sort()
method, but by default it sorts elements as strings, which can lead to incorrect order for numbers (e.g., [2, 10, 3] would sort to [10, 2, 3] lexicographically as strings “10”, “2”, “3”). To sort numerically, you need to provide a comparison function to .sort()
.
For ascending numeric sort, you can do:
js
CopyEdit
const numbers = [42, 5, 16, 25, 8];
// Sort in ascending order
numbers.sort((a, b) => a - b);
console.log(numbers);
// Output: [5, 8, 16, 25, 42]
Explanation of the comparison function (a, b) => a - b
:
.sort()
will take pairs of elements from the array (call them a
and b
) and apply your function.a - b < 0
), it will sort a
to come before b
(meaning a
is “smaller” in terms of sort order).a - b > 0
), it will place a
after b
.a - b
will be negative if a < b
, positive if a > b
. That yields ascending order.b - a
instead.Without sort’s comparison: One could implement sorting manually (e.g., bubble sort or other algorithms), but that’s rarely needed thanks to .sort()
.
It’s worth noting:
js
CopyEdit
[42, 5, 16].sort(); // yields [16, 42, 5] because it converts to ["42","5","16"] and compares lexicographically.
Edge cases / advanced notes (if needed):
js
CopyEdit
items.sort((item1, item2) => item1.price - item2.price);
This question is testing basic understanding of array manipulation and the fact that JS’s default sort is lexicographic. Mentioning the need for a compare function demonstrates you know how to correctly sort numerically. Providing the simple arrow function answer like above is usually sufficient to show you’re adept with modern JS syntax as well.
Answer: The Document Object Model (DOM) is a programming interface (essentially a structured representation) for HTML (and XML) documents. When a web page loads in your browser, the browser parses the HTML and builds the DOM, which is a tree-like structure of objects that represent all the elements on the page.
Key points about the DOM:
<body>
is a node that might have child nodes like <div>
or <p>
elements, which in turn have text nodes or other child elements.<ul>
element would be a DOM node (with child nodes for each <li>
).document.getElementById('foo')
– find an element by its ID.document.querySelector('.bar')
– find the first element matching a CSS selector.element.innerHTML
or element.textContent
– to read or modify content.element.appendChild(childNode)
– to add a new node to the DOM.element.style.color = 'red'
– to change inline styles.element.addEventListener('click', func)
– to respond to user interactions.Think of the DOM as a live, in-memory representation of your page. If you add a DOM node via JavaScript (say, create a new <p>
element and attach it to the body), the browser immediately updates what’s rendered on screen. Conversely, if the user clicks a button and you have an event listener, the DOM event triggers your JS function, which might then, say, remove a node (element.remove()
), and the content disappears from the page.
It’s also worth noting:
document
is the root, then typically <html>
element as document.documentElement, then <head>
and <body>
, and so on.window
and navigator
, but that’s more about the browser environment. The DOM specifically refers to the document structure.Interviewers ask this to ensure you understand that web pages are not just strings of text, but a structured model that you can interact with via JavaScript. A good answer might also mention that the DOM is specified by standards (like W3C/WHATWG) so that different browsers implement it in a compatible way, which is crucial for cross-browser scripting.
Answer: Lazy loading for images means deferring the loading of images (or other resources) until they are actually needed – typically until they are about to enter the viewport (i.e., about to be seen by the user). This can greatly improve initial page load performance, especially if you have many images below the fold.
There are a couple of ways to implement lazy loading:
1. Using the native loading
attribute (if available):
Modern browsers support a native way to lazy-load images. You simply add loading="lazy"
to your <img>
tags:
html
CopyEdit
<img src="photo.jpg" alt="Description" loading="lazy">
This hints the browser to only load the image when it’s close to being needed (typically when the user scrolls near it). It’s a very easy solution – just add the attribute, and the browser handles it. However, support should be checked (at this point, most modern browsers support it, but older ones may not).
2. Using JavaScript (IntersectionObserver API):
For more control or broader support (including older browsers via polyfills), you can use the IntersectionObserver API to detect when an element (like an image placeholder) is in the viewport. Steps:
src
on the <img>
. Instead, maybe set a placeholder image or leave it empty, and store the actual image URL in another attribute like data-src
.js
CopyEdit
const img = document.querySelector('img[data-src]');
const observer = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const imgElement = entry.target;
imgElement.src = imgElement.getAttribute('data-src');
imgElement.removeAttribute('data-src'); // optional: clean up attribute
observer.unobserve(imgElement); // stop observing once loaded
}
});
});
observer.observe(img);
img[data-src]
and observe each).entry.isIntersecting
becomes true), you set the real src
, causing it to load at that moment.(If IntersectionObserver isn’t available, you could fall back to listening for scroll events and calculating element positions, but that’s more complex and less efficient.)
3. Using third-party libraries:
There are libraries and small scripts dedicated to lazy loading (e.g., Lozad.js, lazySizes). These basically do the above under the hood but might handle more edge cases or provide convenient features.
Additional tips:
<img>
but also things like iframes (you can lazy load iframes like maps or videos using similar techniques or using loading="lazy"
on iframes).Why it’s important: If you have many images, loading them all upfront can be slow and data-heavy, especially on mobile. Lazy loading ensures the browser isn’t doing unnecessary work for content the user hasn’t scrolled to yet. It leads to a faster Time to First Meaningful Paint and overall better user experience.
In an interview answer, mentioning the native loading="lazy"
is a nice touch (shows you’re up-to-date). Then describing the IntersectionObserver approach shows you understand how to implement it manually if needed. This question is about performance and modern web practices, so showing awareness of multiple approaches and the performance benefits will make a solid impression.
Answer: To change a button’s background color when a user hovers over it with their mouse, you can use the :hover
pseudo-class in CSS. The :hover
pseudo-class targets an element when the mouse pointer is "hovering" over it.
Here’s a simple example:
html
CopyEdit
<button class="my-button">Click me</button>
css
CopyEdit
.my-button {
background-color: #4CAF50; /* default background */
color: white; /* default text color */
padding: 10px 20px;
border: none;
cursor: pointer;
}
/* Hover state */
.my-button:hover {
background-color: #45a049; /* new background on hover (a darker green, for example) */
}
In this CSS:
.my-button
class for the default state of the button (green background, white text, some padding, and remove default border)..my-button:hover
defines what the button looks like when hovered. In this case we set a different background color (slightly darker green). You could change other properties on hover too (text color, add an underline if it’s a link, etc.), but the question specifically asks for background color.When you hover over the button, the browser will apply the :hover
styles, so the background transitions to #45a049. When the mouse leaves, it goes back to the default.
Additional considerations:
.my-button
, just with :hover
extra for the hover, so it’s fine. If you had multiple classes or more specific selectors, ensure the hover one isn’t getting overridden by something else.css
CopyEdit
.my-button {
background-color: #4CAF50;
transition: background-color 0.3s ease;
}
:hover
pseudo-class works on all modern browsers and even IE6+ for most elements. Just note that on touch devices, :hover
styles generally activate on touch (and may stick until touch end). It’s usually fine, but purely hover-dependent effects should not be critical for functionality on mobile.This question is straightforward – it’s checking that you know basic CSS interactions. A strong answer is concise: “Use the :hover selector in CSS, for example: button:hover { background-color: ...; }
.” Including the code or at least describing it as above demonstrates you know the syntax.
Answer: A Single Page Application (SPA) is a web application that loads a single HTML page and dynamically updates the content on that one page as the user interacts with the app, instead of loading entire new pages from the server. In contrast, a traditional multi-page website loads a new HTML page from the server for each new route or request.
Key differences and characteristics:
/about
or /contact
) triggers the browser to make a request to the server for a new HTML document. The server responds with a full HTML page and the browser unloads the current page and loads the new one.In summary, the difference lies in where the rendering and navigation logic happen. SPAs do more in the browser (client-side), providing a smoother experience at the cost of complexity (managing state, routing, etc. in JavaScript). Traditional web apps rely on the server for each page change, which can simplify development but might feel less snappy in the user experience.
Interviewers ask this to gauge if you understand modern web app architectures and trade-offs. A good answer notes the user experience benefits of SPAs (fast transitions, app-like feel) and the complexity/SEO considerations, as well as clearly describing that SPAs update content dynamically without full page reloads.
Preparing for a front-end developer interview goes beyond just memorizing Q&A. Here are some interview preparation tips to keep in mind:
With solid preparation of technical topics and good practice, you’ll be well-equipped to tackle your front-end interview. Keep a clear head, explain your thought process out loud when solving problems, and don’t be afraid to pause and organize your thoughts if you get a tough question.
Good luck! You’ve got the knowledge – now it’s time to show it. For extra support on interview day, consider having a real time interview assistant in your corner.