Vue vs Traditional CSS - Beginner's Guide
Tags: vue, javascript, css, vanilla
Published: 2019-01-28 12:56:40

> Originally posted at [michaelzanggl.com](https://michaelzanggl.com/articles/vue-vs-traditional-css). Subscribe to [my newsletter](https://michaelzanggl.com/) to never miss out on new content.

#### This is part two of a series on comparing traditional frontend web development with VueJs. Be sure to check out [part 1](https://michaelzanggl.com/articles/vue-vs-vanilla-javascript-for-beginners) if you haven't already. Today we want to take a look at CSS!

---

For traditional websites there are a multitude of ways we can implement CSS.
The most common way is to put the styles in its own CSS file.

There is usually a global CSS file and then one CSS file per page. For smaller pages you will also often find the CSS within the HTML page (usually in the `<head>` part).

This more than often results in big CSS files, that are very hard to manage or refactor without breaking something while doing so.

### Vue

In Vue, each component can have its own styling that is **scoped** to the component.

```vue
<template>
<div class="success-message">this will be green</div>
</template>

<style scoped>
.success-message {
    color: green;
}
</style>
```

Notice the `scoped` attribute we pass along the `<style>` tag. Without this, the CSS would be applied globally. Something we want to avoid. So if I go ahead and create another component with a div that uses the class `success-message`, that div will not become green.

What we end up in Vue is a bunch of small components with only little to no CSS inside each. Gone are the days of having to organize a large set of global CSS somehow, dealing with conflicting style rules and specificity. Together with a CSS framework (see below) you will end up with easily understable and small CSS!

It also avoids constantly having to switch between JavaScript, HTML and CSS files since everything is in one file.

For the CSS you do write, I still recommend following a methodology like BEM.

## Dealing with classes

We often have to add and remove classes from elements to apply specific styles.

### Traditional

```javascript
function handleClick() {
    const messageEl = document.getElementById('message')
    messageEl.classList.add('primary')
}
// ...
// ...
function deleteProject() {
    const messageEl = document.getElementById('message')
    messageEl.classList.remove('primary')
    messageEl.classList.add('danger')
}
```

As you can see, the classList might get modified at any point in the application and it become hard to track.

### Vue

In Vue there are multiple ways:
##### Using Arrays
```vue
<template>
<div :class="['consistent-rule', isPrimary ? 'primary' : '']">message</div>
</template>

<script>
export default {
    data() {
        return {
            isPrimary: true,
        }
    }
}
</script>

<style scoped>
.primary {
    color: #369369;
}
</style>
```

##### Using Objects

```vue
<template>
<div :class={'consistent-rule': true, 'primary': isPrimary}">message</div>
</template>

<script>
export default {
    data() {
        return {
            isPrimary: true,
        }
    }
}
</script>

<style scoped>
.primary {
    color: #369369;
}
</style>
```

The convenient thing is that all possible classes are together in one place. Of course you can also extract the `class` out to a computed field.

## Using SCSS (or other preprocessors) (skipping setup)

### Traditional
This usually requires you to create a `.scss` file that will get compiled down to a `.css` file in the `public` or `dist` directory that you then have to import. You will no longer be able to have the CSS in the same file as the HTML. 

### Vue
Take a look at this please
```vue
<template>
<a class="red--text" href="#">this will be red</a>
</template>

<style scoped lang="scss">
$alert: #c04848;
.red--text {
    color: $alert;
}
</style>
```

The only change that is necessary is to add `lang="scss"` to the `<style>` tag. 


## Using Frameworks

Let's compare two material design frameworks. MaterializeCSS for Vanilla JavaScript/HTML and Vuetify for VueJs.

### MaterializeCSS

CSS frameworks are usually just that, CSS frameworks. So if you want a pagination for example, you will have to take care of how many list items you actually want to display.

```html
<ul class="pagination">
    <li class="disabled"><a href="#!"><i class="material-icons">chevron_left</i></a></li>
    <li class="active"><a href="#!">1</a></li>
    <li class="waves-effect"><a href="#!">2</a></li>
    <li class="waves-effect"><a href="#!">3</a></li>
    <li class="waves-effect"><a href="#!">4</a></li>
    <li class="waves-effect"><a href="#!">5</a></li>
    <li class="waves-effect"><a href="#!">6</a></li>
    <li class="waves-effect"><a href="#!"><i class="material-icons">chevron_right</i></a></li>
</ul>
```
Now when the data changes you have to add / remove `<li>` elements which can become very messy.

### Vuetify 

Vue of course, with the UI being synced with the data, can make your life a lot easier.

```vue
<template>
<v-pagination
    v-model="page"
    :length="6"
></v-pagination>
</template>

<script>
export default {
    data() {
        return {
            page: 1,
        }
    }
}
</script>
```

This also avoids all of these `data-` attributes for many components.

---

Vuetify also makes the overall HTML more readable.
Let's take a look at the popular `cards`.

### MaterializeCSS

```html
<div class="card blue-grey darken-1">
    <div class="card-content white-text">
        <span class="card-title">Card Title</span>
        <p>I am a very simple card. I am good at containing small bits of information.
        I am convenient because I require little markup to use effectively.</p>
    </div>
    <div class="card-action">
        <a href="#">This is a link</a>
        <a href="#">This is a link</a>
    </div>
</div>
```

### Vuetify

```vue
<template>
<v-card class="blue-grey darken-1 white--text">
    <v-card-title>
        <h3 class="headline">Card Title</h3>
        <div>I am a very simple card. I am good at containing small bits of information. 
        I am convenient because I require little markup to use effectively.</div>
    </v-card-title>
    <v-card-actions>
        <v-btn flat color="orange">This is a link</v-btn>
        <v-btn flat color="orange">This is a link</v-btn>
    </v-card-actions>
</v-card>
</template>
```

I don't know about you, but I find the Vue solution much more expressive. I see right away what kind of element we are dealing with (e.g. `<v-card-actions>`), rather than having to search for it in the class list.

## Conclusion
I have to give it to Vue again for making the code once again more readable, and all of that without any complicated syntax like

```javascript
styled.a`
  padding: 0.5rem 0;

  ${props => props.primary && css`
    background: white;
    color: palevioletred;
  `}
`
```

It feels really refreshing having only little to no CSS in your components and therefore having only little CSS to worry about when working on a component!

---

If this article helped you, I have a lot more tips on simplifying writing software [here](https://michaelzanggl.gumroad.com/l/intent-driven-development).