Style in Vue

Styling in Vue is a breeze.

Organization

It's most common to have a <style> tag last/at-the-bottom of SCFs.

vue
1
<script setup>
2
</script>
3
<template>
4
</template>
5
<style>
6
/* css styles */
7
</style>

Scoping

Adding a scoped attribute to the <style> limits the css to the component only, meaning that the styles don't cascade to child elements.

vue
1
<script setup>
2
</script>
3
<template>
4
<div class="container">
5
<!-- Child components -->
6
</div>
7
</template>
8
<style>
9
.container {
10
background-color: red;
11
}
12
</style>

Children components which have the class .container won't have the background color property applied despite.

Possibilities

We can use both style tags to get the best of both worlds.

vue
1
<style>
2
/* global styles */
3
</style>
4
5
<style scoped>
6
/* local styles */
7
</style>

Deep Selectors

If we want to target style the child elements/components we can use deep selectors.

vue
1
<style scoped>
2
.a >>> .b { /* ... */ }
3
</style>

CSS Modules

It's possible to define styles as a module. Doing so helps to prevent name collisions of classes.

vue
1
<template>
2
<p :class="$style.red">This should be red</p>
3
</template>
4
5
<style module>
6
.red {
7
color: red;
8
}
9
</style>

Binding State

It's possible to make component state apply CSS styles as well.

vue
1
<template>
2
<div class="text">hello</div>
3
</template>
4
5
<script>
6
export default {
7
data() {
8
return {
9
color: 'red'
10
}
11
}
12
}
13
</script>
14
15
<style>
16
.text {
17
color: v-bind(color);
18
}
19
</style>

In this case the color state variable defines the property to a CSS class which ultimately styles the template/component.

Flexibility

It's possible to use POJO's & JS expressions together to produce dynamic styling as well.

Note that we have to wrap the expression with strings.

vue
1
<script setup>
2
const theme = {
3
color: 'red'
4
}
5
</script>
6
7
<template>
8
<p>hello</p>
9
</template>
10
11
<style scoped>
12
p {
13
color: v-bind('theme.color');
14
}
15
</style>