Skip to content

Frontend Interview Guide — HTML, CSS & JavaScript

DodaTech Updated 2026-06-21 5 min read

In this tutorial, you'll learn about Frontend Interview Guide. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.

Frontend interviews test your knowledge of browser APIs, CSS layout, JavaScript fundamentals, framework internals, performance optimization, and accessibility best practices. Unlike generic coding interviews, frontend rounds focus on how users experience your code — rendering, interactivity, and responsiveness. Doda Browser engineers must understand every layer of web technology to build a fast, accessible browser.

Learning Path

flowchart LR
  A[Coding Interview Prep] --> B[Frontend Interview]
  B --> C[Backend Interview]
  C --> D[System Design]
  D --> E[Behavioral Prep]
  style B fill:#f90,color:#fff

HTML & CSS

Semantic HTML

<!-- BAD: Div soup -->
<div class="header">
  <div class="nav"><div class="nav-item">Home</div></div>
</div>

<!-- GOOD: Semantic structure -->
<header>
  <nav>
    <ul>
      <li><a href="/">Home</a></li>
    </ul>
  </nav>
</header>

CSS Layout — Flexbox & Grid

/* Flexbox: one-dimensional */
.container {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
}

/* Grid: two-dimensional */
.grid-layout {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: 2rem;
}

Specificity & Cascading

/* Specificity: inline > ID > class > element */
#header { color: red; }      /* 0-1-0 */
.header { color: blue; }     /* 0-0-1 */
div { color: green; }        /* 0-0-0 */

JavaScript Fundamentals

Closures

function createCounter() {
  let count = 0;
  return {
    increment: () => ++count,
    decrement: () => --count,
    getCount: () => count,
  };
}

const counter = createCounter();
counter.increment();
counter.increment();
counter.decrement();
console.log(counter.getCount());

Expected output:

1

Event Loop

console.log('1: Sync');

setTimeout(() => console.log('2: setTimeout'), 0);

Promise.resolve().then(() => console.log('3: Microtask'));

console.log('4: Sync');

// Microtasks (Promise) execute before macrotasks (setTimeout)

Expected output:

1: Sync
4: Sync
3: Microtask
2: setTimeout

Debounce & Throttle

// Debounce — wait for pause before executing
function debounce(fn, delay) {
  let timer;
  return (...args) => {
    clearTimeout(timer);
    timer = setTimeout(() => fn(...args), delay);
  };
}

// Throttle — execute at most once per interval
function throttle(fn, interval) {
  let lastCall = 0;
  return (...args) => {
    const now = Date.now();
    if (now - lastCall >= interval) {
      lastCall = now;
      fn(...args);
    }
  };
}

React

Hooks & Lifecycle

function UserProfile({ userId }) {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    let cancelled = false;
    async function fetchUser() {
      setLoading(true);
      const data = await api.getUser(userId);
      if (!cancelled) {
        setUser(data);
        setLoading(false);
      }
    }
    fetchUser();
    return () => { cancelled = true; };
  }, [userId]);

  if (loading) return <Spinner />;
  return <div>{user.name}</div>;
}

Performance Optimization

// Prevent unnecessary re-renders
const ExpensiveList = React.memo(({ items }) => {
  return items.map(item => <ListItem key={item.id} item={item} />);
});

// Memoize computed values
function Dashboard({ transactions }) {
  const totals = useMemo(() => {
    return transactions.reduce((acc, t) => acc + t.amount, 0);
  }, [transactions]);
}

// Memoize callbacks
function Parent() {
  const handleClick = useCallback((id) => {
    console.log('Clicked:', id);
  }, []);
}

Accessibility (a11y)

<!-- Accessible button with ARIA -->
<button aria-label="Close dialog" onclick="close()">
  <span aria-hidden="true">×</span>
</button>

<!-- Accessible form -->
<label for="email">Email address</label>
<input id="email" type="email" aria-describedby="email-hint" required />
<span id="email-hint">We'll never share your email.</span>

<!-- Skip navigation link -->
<a href="#main-content" class="skip-link">Skip to content</a>

Frontend System Design: Search Component

// Custom hook for debounced search
function useSearch(query) {
  const [results, setResults] = useState([]);
  const [loading, setLoading] = useState(false);
  const debouncedQuery = useDebounce(query, 300);

  useEffect(() => {
    if (!debouncedQuery) {
      setResults([]);
      return;
    }
    setLoading(true);
    fetch(`/api/search?q=${debouncedQuery}`)
      .then(r => r.json())
      .then(data => { setResults(data); setLoading(false); });
  }, [debouncedQuery]);

  return { results, loading };
}

Common Mistakes

  1. Not knowing the Rendering Pipeline — Understand DOM → CSSOM → Render Tree → Layout → Paint → Composite.
  2. Framework-only knowledge — React hooks syntax without understanding re-renders, virtual DOM, and reconciliation.
  3. Ignoring accessibility — "We'll add it later" is a red flag. Learn ARIA, keyboard navigation, and screen readers.
  4. No performance awareness — Bundle size, re-renders, lazy loading — every frontend interview covers these.
  5. Weak CSS — Know Flexbox, Grid, stacking contexts, and Responsive Design beyond copy-pasting Bootstrap.
  6. No testing — Know Testing Library, component tests, and E2E testing with Playwright or Cypress.
  7. Over-engineering — Redux for a 3-component app. Start simple, add complexity when needed.

Practice Questions

1. What's the difference between debouncing and throttling? Debouncing waits for a pause before executing. Throttling executes at most once per interval regardless of call frequency.

2. When does React re-render a component? When state changes (useState), when props change, or when a parent re-renders. React.memo and useMemo can prevent unnecessary re-renders.

3. What are Core Web Vitals? LCP (Largest Contentful Paint — loading), INP (Interaction to Next Paint — interactivity), CLS (Cumulative Layout Shift — visual stability).

4. What's the difference between reflow and repaint? Reflow recalculates layout positions (expensive). Repaint redraws pixels without layout changes (cheaper).

5. Challenge: Design and implement an autocomplete search component with debounced API calls, keyboard navigation (arrow keys), loading/error/empty states, and full ARIA accessibility support. Write tests for each interaction.

Real-World Task

Audit a real website (your favorite news site or SaaS) against Core Web Vitals using Chrome DevTools. Identify the top 3 performance issues and propose specific fixes with before/after measurements.

FAQ

Should I learn React or Angular for interviews?

React is more commonly asked and has a broader job market. Angular knowledge is valuable for enterprise roles. Learn React first — the concepts transfer to other frameworks.

Do I need TypeScript for frontend interviews?

Yes — TypeScript is the standard for modern frontend development. Know interfaces, types, generics, and utility types like Partial, Pick, and Omit.

What are the most common frontend interview topics?

Event loop, closures, this binding, CSS specificity, React hooks and re-rendering, state management, performance optimization, and accessibility.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro