Back to stories
<Frontend/>

Vue Scoped Styles: When to Use Scoped, :deep(), and Modules

Share by

Vue Scoped Styles: When to Use Scoped, (), and Modules

Vue’s scoped attribute keeps component CSS from leaking out, but styling child components or slots often needs () or (). This post explains how scoped works, when to use these selectors, and when CSS Modules might be a better fit.


How scoped works

With <style scoped>, Vue adds a unique attribute (e.g. data-v-7ba5bd90) to the component’s root and rewrites selectors so they target only that subtree. So .title becomes .title[data-v-7ba5bd90]. That prevents your component’s styles from affecting the rest of the app.

Use scoped by default so component styles are local and you avoid global namespace clashes.


() for child components and DOM

Child components’ root gets the parent’s data attribute, but their inner DOM does not. So a selector like .parent .child-title won’t match inside the child. () (or the deprecated >>> / ::v-deep) pierces that: the selector inside :deep() is not prefixed with the scoped attribute.

Use () when: You need to style the inner DOM of a child component (e.g. a third-party library) or a descendant that doesn’t carry the scoped attribute. Prefer the child exposing a prop or a CSS variable instead of reaching in; use () when you don’t control the child.

Example:

.parent :deep(.child-inner-class) {
  color: var(--override-color);
}

() for slot content

Content passed in via slots is rendered in the parent’s template but may live in the child’s DOM. By default, scoped styles don’t apply to that content because it’s “owned” by the parent. () lets you style slotted content from the component that defines the slot.

Use () when: You want to style the default appearance of slot content (e.g. list items in a generic list component) while still keeping styles component-local.


CSS Modules

With CSS Modules (e.g. <style module>), class names are hashed and you use them via $style.className in the template. You get true local scope and no need for () for your own classes; you explicitly use the generated names.

Use CSS Modules when: You want maximum isolation and don’t mind using $style in the template, or you’re in a large app where scoped + () is getting messy.


Summary

  • Scoped is the default: component styles stay local; use it for most components.
  • () when you must style inner DOM of a child (e.g. a library); prefer the child exposing an API (prop or variable) when possible.
  • () when you need to style slot content from the component that defines the slot.
  • CSS Modules when you want hashed class names and explicit usage. Use scoped, (), and () in a consistent way so Vue styles stay predictable.