vuejs-scoped-styles

What are scoped styles in Vue.js and how to use them

  • 3 min

Scoped styles are a way to encapsulate CSS styles within a specific component.

As applications grow, global styles can become difficult to maintain and can cause conflicts between components.

This is where scoped styles come into play, a Vue.js feature that allows encapsulating styles within a component.

Scoped styles are styles that are applied only to the component in which they are defined, avoiding conflicts with other components.

How to Use Scoped Styles in Vue.js

To use scoped styles in Vue.js, simply add the scoped attribute to the <style> tag in your component.

<template>
  <div class="container">
    <p class="text">This is styled text.</p>
  </div>
</template>

<style scoped>
.container {
  padding: 20px;
  border: 1px solid #ccc;
}

.text {
  color: blue;
  font-size: 18px;
}
</style>
Copied!

In this example,

  • The styles defined in <style scoped> only apply to the elements inside the component.

How Scoped Styles Work Internally

When we define styles with the scoped attribute in a component, Vue.js automatically performs a series of modifications to the elements when rendering it.

  1. Adds a unique attribute: Each element in the component is assigned a unique attribute, such as data-v-123456.
  2. Modifies CSS selectors: Vue.js modifies the CSS selectors to include the unique attribute.

For example, the following CSS:

.container {
  padding: 20px;
}
Copied!

Will become:

.container[data-v-123456] {
  padding: 20px;
}
Copied!

This ensures that the styles are only applied to the elements of the current component.

This happens transparently for us, without us having to worry about (almost) anything.

Propagating Styles to Child Components with Deep

By default, styles with scoped are not applied to child components. However, in some cases, we might want them to propagate.

For this, Vue.js provides the deep selector (:deep()).

<template>
  <div class="parent">
    <ChildComponent />
  </div>
</template>

<script setup>
import ChildComponent from './ChildComponent.vue';
</script>

<style scoped>
.parent :deep(.child-class) {
  color: red;
}
</style>
Copied!

In this example, the style is applied to elements with the class child-class inside the ChildComponent, even though the styles are defined with scoped.

Applying Styles to Slot Elements with :slotted

Similarly, when working with slots, Vue.js does not propagate scoped styles to slots by default. For this, it provides the :slotted() selector.

<template>
  <div class="wrapper">
    <slot></slot>
  </div>
</template>

<style scoped>
:slotted(p) {
  font-weight: bold;
  color: green;
}

/* You can also use classes or more complex combinations */
:slotted(.special) {
  background-color: #eee;
}
</style>
Copied!

In this example:

  • The :slotted(p) selector will apply to all <p> elements inserted into the component’s slot.
  • The :slotted(.special) selector will apply to any element with the class special inserted into the slot.