Frontend Interview Questions - Easy
Easy-level frontend interview questions covering HTML, CSS, JavaScript, React, and Vue fundamentals.
Q1: What is the DOM and how does it work?
Answer:
graph TB
A[HTML Document] --> B[Browser Parses]
B --> C[DOM Tree]
C --> D[Document]
D --> E[html]
E --> F[head]
E --> G[body]
G --> H[div]
H --> I[p]
H --> J[span]
style C fill:#FFD700
style D fill:#87CEEBDOM (Document Object Model): Tree-like representation of HTML document that JavaScript can manipulate.
DOM Manipulation
1// Select elements
2const element = document.getElementById('myId');
3const elements = document.querySelectorAll('.myClass');
4
5// Modify content
6element.textContent = 'New text';
7element.innerHTML = '<strong>Bold text</strong>';
8
9// Modify attributes
10element.setAttribute('class', 'new-class');
11element.style.color = 'red';
12
13// Create and append
14const newDiv = document.createElement('div');
15newDiv.textContent = 'Hello';
16document.body.appendChild(newDiv);
Q2: Explain the CSS Box Model.
Answer:
graph TB
A[Box Model] --> B[Content<br/>Actual content]
A --> C[Padding<br/>Space around content]
A --> D[Border<br/>Edge of box]
A --> E[Margin<br/>Space outside border]
style A fill:#FFD700Visual Representation
graph TB
subgraph Margin
subgraph Border
subgraph Padding
A[Content<br/>Width × Height]
end
end
end
style A fill:#87CEEB1.box {
2 width: 200px; /* Content width */
3 height: 100px; /* Content height */
4 padding: 20px; /* Space inside border */
5 border: 5px solid black; /* Border */
6 margin: 10px; /* Space outside border */
7}
8
9/* Total width = 200 + 20*2 + 5*2 + 10*2 = 270px */
Box-sizing:
1/* Default: content-box */
2.box { box-sizing: content-box; }
3/* Width = content only */
4
5/* Better: border-box */
6.box { box-sizing: border-box; }
7/* Width = content + padding + border */
Q3: What is event bubbling and capturing?
Answer:
graph TB
A[Event Propagation] --> B[Capturing Phase<br/>Top to target]
A --> C[Target Phase<br/>At target]
A --> D[Bubbling Phase<br/>Target to top]
style A fill:#FFD700Event Flow
graph TB
A[Window] --> B[Document]
B --> C[html]
C --> D[body]
D --> E[div]
E --> F[button CLICK]
F -.Bubbling.-> E
E -.Bubbling.-> D
D -.Bubbling.-> C
A --Capturing--> B
B --Capturing--> C
C --Capturing--> D
style F fill:#FF6B6B 1// Bubbling (default)
2element.addEventListener('click', handler);
3
4// Capturing
5element.addEventListener('click', handler, true);
6
7// Stop propagation
8function handler(event) {
9 event.stopPropagation(); // Stop bubbling/capturing
10 event.preventDefault(); // Prevent default action
11}
Example:
1<div id="parent">
2 <button id="child">Click me</button>
3</div>
4
5<script>
6document.getElementById('parent').addEventListener('click', () => {
7 console.log('Parent clicked');
8});
9
10document.getElementById('child').addEventListener('click', (e) => {
11 console.log('Child clicked');
12 // e.stopPropagation(); // Uncomment to stop bubbling
13});
14
15// Output: "Child clicked", "Parent clicked"
16</script>
Q4: What are React components and props?
Answer:
graph TB
A[React Component] --> B[Function Component<br/>Modern approach]
A --> C[Class Component<br/>Legacy]
B --> D[Receives Props]
C --> D
D --> E[Returns JSX]
style A fill:#FFD700
style B fill:#90EE90Function Component
1// Function component
2function Welcome(props) {
3 return <h1>Hello, {props.name}!</h1>;
4}
5
6// Arrow function
7const Welcome = ({ name }) => {
8 return <h1>Hello, {name}!</h1>;
9};
10
11// Usage
12<Welcome name="Alice" />
Props Flow
graph LR
A[Parent<br/>Component] -->|Props| B[Child<br/>Component]
B -->|Cannot modify| A
style A fill:#87CEEB
style B fill:#90EE90 1function App() {
2 return (
3 <div>
4 <Welcome name="Alice" age={25} />
5 <Welcome name="Bob" age={30} />
6 </div>
7 );
8}
9
10function Welcome({ name, age }) {
11 return (
12 <div>
13 <h1>Hello, {name}!</h1>
14 <p>Age: {age}</p>
15 </div>
16 );
17}
Props are read-only - components cannot modify their props.
Q5: What is React state and how do you use useState?
Answer:
graph TB
A[State] --> B[Component's<br/>Memory]
A --> C[Triggers Re-render<br/>When changed]
A --> D[Managed by<br/>useState Hook]
style A fill:#FFD700useState Hook
1import { useState } from 'react';
2
3function Counter() {
4 // Declare state variable
5 const [count, setCount] = useState(0);
6 // ^state ^setter ^initial value
7
8 return (
9 <div>
10 <p>Count: {count}</p>
11 <button onClick={() => setCount(count + 1)}>
12 Increment
13 </button>
14 <button onClick={() => setCount(count - 1)}>
15 Decrement
16 </button>
17 <button onClick={() => setCount(0)}>
18 Reset
19 </button>
20 </div>
21 );
22}
State Updates
sequenceDiagram
participant U as User
participant C as Component
participant R as React
U->>C: Click button
C->>C: Call setCount(count + 1)
C->>R: State change
R->>R: Schedule re-render
R->>C: Re-render with new state
C->>U: Updated UI 1// Multiple state variables
2function Form() {
3 const [name, setName] = useState('');
4 const [age, setAge] = useState(0);
5 const [email, setEmail] = useState('');
6
7 return (
8 <form>
9 <input
10 value={name}
11 onChange={(e) => setName(e.target.value)}
12 />
13 <input
14 type="number"
15 value={age}
16 onChange={(e) => setAge(Number(e.target.value))}
17 />
18 <input
19 type="email"
20 value={email}
21 onChange={(e) => setEmail(e.target.value)}
22 />
23 </form>
24 );
25}
Q6: What is Vue.js and how does it differ from React?
Answer:
graph TB
A[Vue.js] --> B[Progressive<br/>Framework]
A --> C[Template Syntax<br/>HTML-like]
A --> D[Reactive Data<br/>Automatic tracking]
A --> E[Single File<br/>Components]
style A fill:#FFD700Vue vs React
graph TB
subgraph Vue["Vue.js"]
V1[Template-based]
V2[Two-way binding]
V3[Directives v-if, v-for]
V4[Options API / Composition API]
end
subgraph React
R1[JSX]
R2[One-way data flow]
R3[JavaScript expressions]
R4[Hooks]
endVue Component
1<template>
2 <div>
3 <h1>{{ message }}</h1>
4 <button @click="increment">Count: {{ count }}</button>
5 </div>
6</template>
7
8<script>
9export default {
10 data() {
11 return {
12 message: 'Hello Vue!',
13 count: 0
14 }
15 },
16 methods: {
17 increment() {
18 this.count++;
19 }
20 }
21}
22</script>
23
24<style scoped>
25h1 {
26 color: blue;
27}
28</style>
React Component (Equivalent)
1import { useState } from 'react';
2
3function MyComponent() {
4 const [message] = useState('Hello React!');
5 const [count, setCount] = useState(0);
6
7 const increment = () => setCount(count + 1);
8
9 return (
10 <div>
11 <h1 style={{ color: 'blue' }}>{message}</h1>
12 <button onClick={increment}>Count: {count}</button>
13 </div>
14 );
15}
Q7: What are Vue directives?
Answer:
graph TB
A[Vue Directives] --> B[v-if<br/>Conditional rendering]
A --> C[v-for<br/>List rendering]
A --> D[v-bind<br/>Bind attributes]
A --> E[v-on<br/>Event listeners]
A --> F[v-model<br/>Two-way binding]
style A fill:#FFD700Common Directives
1<template>
2 <!-- v-if: Conditional rendering -->
3 <div v-if="isLoggedIn">
4 Welcome back!
5 </div>
6 <div v-else>
7 Please log in
8 </div>
9
10 <!-- v-show: Toggle visibility (CSS display) -->
11 <div v-show="isVisible">
12 This toggles visibility
13 </div>
14
15 <!-- v-for: List rendering -->
16 <ul>
17 <li v-for="item in items" :key="item.id">
18 {{ item.name }}
19 </li>
20 </ul>
21
22 <!-- v-bind (shorthand :) -->
23 <img :src="imageUrl" :alt="imageAlt" />
24 <div :class="{ active: isActive }"></div>
25
26 <!-- v-on (shorthand @) -->
27 <button @click="handleClick">Click me</button>
28 <input @input="handleInput" />
29
30 <!-- v-model: Two-way binding -->
31 <input v-model="username" />
32 <p>Username: {{ username }}</p>
33</template>
34
35<script>
36export default {
37 data() {
38 return {
39 isLoggedIn: false,
40 isVisible: true,
41 items: [
42 { id: 1, name: 'Item 1' },
43 { id: 2, name: 'Item 2' }
44 ],
45 imageUrl: '/path/to/image.jpg',
46 imageAlt: 'Description',
47 isActive: true,
48 username: ''
49 }
50 },
51 methods: {
52 handleClick() {
53 console.log('Clicked!');
54 },
55 handleInput(event) {
56 console.log(event.target.value);
57 }
58 }
59}
60</script>
Q8: What is the Virtual DOM?
Answer:
graph TB
A[Virtual DOM] --> B[Lightweight Copy<br/>of Real DOM]
A --> C[JavaScript Object<br/>Representation]
A --> D[Efficient Updates<br/>Diffing algorithm]
style A fill:#FFD700How it Works
sequenceDiagram
participant S as State Change
participant V1 as Old Virtual DOM
participant V2 as New Virtual DOM
participant D as Diffing
participant R as Real DOM
S->>V2: Create new Virtual DOM
V1->>D: Compare
V2->>D: Compare
D->>D: Find differences
D->>R: Update only changed partsExample
1// State changes
2setState({ count: count + 1 });
3
4// React creates new Virtual DOM
5const newVDOM = {
6 type: 'div',
7 props: {
8 children: [
9 { type: 'p', props: { children: 'Count: 1' } }
10 ]
11 }
12};
13
14// Compare with old Virtual DOM
15const oldVDOM = {
16 type: 'div',
17 props: {
18 children: [
19 { type: 'p', props: { children: 'Count: 0' } }
20 ]
21 }
22};
23
24// Only update the text node in real DOM
25// Instead of re-rendering entire component
Benefits:
- Faster than direct DOM manipulation
- Batches multiple updates
- Cross-platform (React Native)
Q9: What is component lifecycle in React?
Answer:
graph TB
A[Component Lifecycle] --> B[Mounting<br/>Component created]
A --> C[Updating<br/>State/props change]
A --> D[Unmounting<br/>Component removed]
B --> E[useEffect<br/>with empty deps]
C --> F[useEffect<br/>with deps]
D --> G[useEffect<br/>cleanup]
style A fill:#FFD700useEffect Hook
1import { useState, useEffect } from 'react';
2
3function Component() {
4 const [count, setCount] = useState(0);
5
6 // Runs after every render
7 useEffect(() => {
8 console.log('Component rendered');
9 });
10
11 // Runs once on mount (like componentDidMount)
12 useEffect(() => {
13 console.log('Component mounted');
14
15 // Cleanup on unmount
16 return () => {
17 console.log('Component unmounted');
18 };
19 }, []); // Empty dependency array
20
21 // Runs when count changes
22 useEffect(() => {
23 console.log('Count changed:', count);
24 }, [count]); // Dependency array
25
26 return <button onClick={() => setCount(count + 1)}>Count: {count}</button>;
27}
Lifecycle Flow
sequenceDiagram
participant M as Mount
participant R as Render
participant E as Effect
participant U as Update
participant C as Cleanup
M->>R: Initial render
R->>E: Run effects
Note over U: State/Props change
U->>R: Re-render
R->>C: Cleanup previous effects
C->>E: Run new effects
Note over C: Component unmounts
C->>C: Final cleanupQ10: What is Vue Composition API?
Answer:
graph TB
A[Composition API] --> B[setup Function<br/>Entry point]
A --> C[Reactive References<br/>ref, reactive]
A --> D[Lifecycle Hooks<br/>onMounted, etc.]
A --> E[Better Code<br/>Organization]
style A fill:#FFD700Options API vs Composition API
1<!-- Options API (Traditional) -->
2<script>
3export default {
4 data() {
5 return {
6 count: 0,
7 message: 'Hello'
8 }
9 },
10 methods: {
11 increment() {
12 this.count++;
13 }
14 },
15 mounted() {
16 console.log('Mounted');
17 }
18}
19</script>
1<!-- Composition API (Modern) -->
2<script setup>
3import { ref, onMounted } from 'vue';
4
5const count = ref(0);
6const message = ref('Hello');
7
8function increment() {
9 count.value++;
10}
11
12onMounted(() => {
13 console.log('Mounted');
14});
15</script>
16
17<template>
18 <div>
19 <p>{{ message }}</p>
20 <button @click="increment">Count: {{ count }}</button>
21 </div>
22</template>
Reactive References
1import { ref, reactive, computed } from 'vue';
2
3// ref: For primitives
4const count = ref(0);
5console.log(count.value); // Access with .value
6count.value++;
7
8// reactive: For objects
9const state = reactive({
10 name: 'Alice',
11 age: 25
12});
13console.log(state.name); // Direct access
14state.age++;
15
16// computed: Derived state
17const doubled = computed(() => count.value * 2);
18console.log(doubled.value);
Benefits:
- Better TypeScript support
- More flexible code organization
- Easier to reuse logic
- Better tree-shaking
Summary
Key frontend concepts:
- DOM: Tree structure, manipulation
- CSS Box Model: Content, padding, border, margin
- Event Propagation: Bubbling and capturing
- React Components: Function components, props
- React State: useState hook, re-rendering
- Vue.js: Template syntax, directives
- Vue Directives: v-if, v-for, v-model, v-bind, v-on
- Virtual DOM: Efficient updates, diffing
- React Lifecycle: useEffect hook, cleanup
- Vue Composition API: setup, ref, reactive
These fundamentals are essential for frontend development.
Related Snippets
- Frontend Interview Questions - Hard
Hard-level frontend interview questions covering advanced patterns, performance … - Frontend Interview Questions - Medium
Medium-level frontend interview questions covering advanced React, Vue, state …