How does scoped CSS work in Vue single-file components?
Understand how Vue scoped CSS isolates component styles with generated data attributes, why child roots inherit scope, and when to use the :deep() selector.
Expected Interview Answer
Scoped CSS in a Vue SFC restricts a component's styles to that component only. Adding the scoped attribute to <style> makes Vue attach a unique data attribute to the component's elements and rewrite selectors to target it.
At compile time Vue generates a hashed attribute like data-v-7ba5bd90, stamps it onto every element the component renders, and appends it to each selector (e.g. .title[data-v-7ba5bd90]). This gives predictable local styling without naming conventions like BEM. Styles do not bleed into child components, though the root node of a child still receives the parent's scope, and deep styling of child internals requires the :deep() pseudo-class.
- Prevents style leakage between components
- Removes the need for strict class-naming conventions
- Keeps component styles co-located and self-contained
- Makes refactoring safer since styles are local
- Still allows targeted child styling via :deep()
AI Mentor Explanation
Scoped CSS is like each team having its own dressing room whose colours only paint that room. The groundsman tags every wall in one room with a hidden team sticker, so the paint order applies only where that sticker exists. Another team's dressing room, even next door, keeps its own look untouched, and only a special override lets colours reach a shared corridor.
Step-by-Step Explanation
Step 1
Add the scoped attribute
Write <style scoped> in the SFC to opt the block into component-local styling.
Step 2
Vue generates a scope id
At compile time Vue creates a unique attribute such as data-v-7ba5bd90 for the component.
Step 3
Elements get the attribute
Every element the component renders is stamped with that data attribute.
Step 4
Selectors are rewritten
Each selector gains an attribute suffix, e.g. .title becomes .title[data-v-7ba5bd90].
Step 5
Use :deep() for child internals
To style a child component's inner elements, wrap the selector with :deep() so it pierces the scope.
What Interviewer Expects
- Understanding that scoped uses a generated data attribute
- Knowing selectors are rewritten with an attribute suffix
- Awareness that a child's root node receives the parent scope
- Correct use of :deep() for child internals
- Difference between scoped styles and CSS Modules
Common Mistakes
- Expecting scoped styles to reach deep into a child's internals without :deep()
- Confusing scoped CSS with CSS Modules
- Assuming scoped changes CSS specificity dramatically
- Forgetting that the child's root element inherits the parent's scope id
Best Answer (HR Friendly)
“Scoped styling keeps a component's CSS from affecting other parts of the page. Vue quietly tags the component's elements with a unique marker so its styles only apply where that marker exists, which avoids clashes without careful class naming.”
Code Example
<template>
<div class="card">
<ChildBadge class="badge" />
</div>
</template>
<style scoped>
.card {
padding: 16px;
}
/* Reach into the child component's inner element */
.card :deep(.badge-label) {
color: teal;
}
</style>Follow-up Questions
- What is the difference between scoped CSS and CSS Modules in Vue?
- When would you need the :deep() pseudo-class?
- Why does a child component's root element receive the parent's scope id?
- How does scoped CSS affect specificity?
- Can you mix scoped and non-scoped style blocks in one SFC?
MCQ Practice
1. How does Vue implement scoped CSS?
Vue stamps a unique data-v attribute on the component's elements and appends it to each selector.
2. Which pseudo-class lets scoped styles target a child component's internals?
:deep() pierces the scope boundary so a parent's scoped rule can style a child's inner elements.
3. Which element of a child component receives the parent's scope id?
The child's root node gets both its own scope id and the parent's, so parents can style the child's root.
Flash Cards
What does <style scoped> do? — Limits the CSS to the current component via a generated data attribute.
What attribute does Vue generate? — A unique scope id like data-v-7ba5bd90 stamped onto rendered elements.
How do you style a child's internals? — Use the :deep() pseudo-class to pierce the scope boundary.
Which child node inherits the parent scope? — The child component's root element receives the parent's scope id.