CSS in Vue
css in vue css in vue centers on single file components — <style scoped>, css modules in sfc, :deep()/:slotted()/:global(), and
Introduction
CSS in Vue centers on Single File Components — <style scoped>, CSS modules in SFC, :deep()/:slotted()/:global(), and v-bind() in style blocks for reactive custom properties. Vue 3.2+ script setup pairs with scoped styles for lean component authoring.
Staff Vue architects integrate UnoCSS/Tailwind alongside scoped SFC — defining when markup uses utilities vs when scoped CSS handles complex component internals.
Business problem
Business pressure: Vue powers internal admin tools and Nuxt marketing sites — teams need consistent scoping without Shadow DOM overhead and reactive theme binding when dark mode toggles at runtime.
- Nuxt SSR: Scoped ids must match server HTML — hydration style flash avoided.
- Design system: Headless UI primitives + scoped skin in each app.
- v-bind in CSS: Dynamic theme without inline styles.
Why this feature exists
Platform history: Vue SFC scoped styles since Vue 2 — compiler innovation. Vue 3.2 v-bind in CSS connects reactivity to custom properties in style block.
- Problem solved: Component style isolation with familiar CSS syntax.
- Modern role: Nuxt 3 + Vue 3 + Vite default pipeline.
Browser rendering perspective
v-bind(): Sets inline custom property on element — style block references var() — single recalc on reactive change without full class swap.
Internal browser workflow
SFC compile: scoped id generated → selectors rewritten → CSS extracted to chunk or inline for SSR critical.
Feature deep dive
SFC style features:
<script setup>const color = ref('#4f46e5')</script><template><button class="btn">Save</button></template><style scoped>.btn {background: v-bind(color);padding: 0.5rem 1rem;}:deep(.icon) { margin-right: 0.5rem; }</style>
Syntax
module: <style module> for CSS Modules map as $style. scoped + module can combine.
Examples
Nuxt layer CSS: app.vue unscoped tokens; pages scoped layouts.
Real-world use
Nuxt ecosystem, Laravel Inertia Vue apps, GitLab UI partially Vue. Element Plus / Vuetify provide unscoped library CSS + app scoped overrides via :deep.
Real production example
Pattern: tokens.css global; components scoped; eslint vue-scoped-css enforce :deep limits.
Enterprise use case
Enterprise: Multi-app Nuxt monorepo — shared @nuxtjs/tailwind preset + scoped component skins.
Accessibility considerations
A11y: :slotted() for styling slot content from child — ensure focus styles apply to slotted interactive elements.
Performance considerations
Performance: v-bind cheaper than recomputing full class strings for color alone.
SEO considerations
SEO: Nuxt SSR extracts scoped CSS to head — good FCP for content pages.
Scalability considerations
Scale: :deep proliferation — audit as coupling metric.
Common production issues
Failures: Teleport content loses scoped parent — style teleport target explicitly.
Debugging guide
Debug: Vue DevTools show component scoped id; inspect data-v-* attributes.
Best practices
- Global tokens; scoped internals.
- v-bind for reactive single-property theme hooks.
- Limit :deep — prefer slot class props.
Anti-patterns
- Second unscoped style block per component without reason.
- Importing Vuetify and scoped overriding every class with :deep.
Trade-offs
- scoped: isolation; pierce needed for libs.
- Tailwind in Vue: speed vs markup density.
Architecture review questions
- Scoped vs module vs global policy per folder?
- Nuxt SSR style extraction verified in CI?
Interview questions
Vue v-bind in CSS — how does it work?(Intermediate)
Compiler converts v-bind(color) to inline --var on element and references in scoped rule — reactive updates change custom property without remounting style tag.
Follow-up: scoped vs module in same SFC?
Hands-on exercise
Exercise: Theme toggle using v-bind in scoped block — no inline style on root.
Staff engineer notes
- Vue CSS = scoped + tokens + disciplined :deep — Nuxt adds SSR extraction requirements.
Common pitfalls
- Teleport + scoped — classic missed style bug.
Try it yourself
Edit the CSS panel — the preview updates live. Use DevTools Performance and Accessibility panels to validate.
Try it yourself
Summary
CSS in Vue leverages SFC scoped styles, CSS modules, and v-bind() for reactive theming — with Nuxt SSR requiring correct style extraction for production performance.
Key takeaways
- Vue SFC scoped, modules, and v-bind() cover isolation and reactivity.
- :deep/:slotted for library integration.