A New Vue On JavaScript30 - 03 CSS Variables
Tags: anewvueonjs30, vue, javascript30, javascript
Published: 2018-09-07 02:39:01

---
title: A New Vue On JavaScript30 - 03 CSS Variables
published: true
tags: ANewVueOnJS30,Vue,JavaScript30,JavaScript
canonical_url: https://davefollett.io/2018/09/06/a-new-vue-on-javascript30-03-css-variables/
cover_image: https://davefollett.io/2018/09/06/a-new-vue-on-javascript30-03-css-variables/cover-css-variables.jpg
series: A New Vue On JavaScript30
---


This article is part of the [A New Vue On JavaScript30](/t/anewvueonjs30) series that explores re-implementing [#JavaScript30](https://JavaScript30.com) projects using [Vue](https://vuejs.org). Today we will be working with the third of Wes Bos’s ([@wesbos](https://twitter.com/wesbos)) [#JavaScript30](https://JavaScript30.com) projects titled: **03 - CSS Variables**. This project uses an HTML inputs to control [CSS variables](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_variables) to change an image’s blur, padding, and background color.

## Key Vue Concepts

The following Vue concepts are discussed in this article:

- Style binding with `:style` (shorthand for `v-bind:style`)
- `v-model` directive to create two-way data bindings on form input
- Computed Properties
- Watched Properties
- The `mounted` lifecycle hook

## Approach

Setting out to work on this I was conflicted. Should I stay true to #JavaScript30 and use CSS variables or re-implement it taking advantage of Vue’s features? Undecided, I took to the [CodingBlocks.net Slack channel](https://www.codingblocks.net/slack/) to ask for opinions with a poll. The final results were:
* 1 vote for **CSS Variables**
* 1 vote for **Vue's Features**
* 5 votes for **Do Both**

Oh and I also got 1 write in vote for:

> Use React with styled-components :P ~ MinimumViablePerson

Not going to lie, I had a nice chuckle when I read that. Since I began redoing #JavaScript30 with Vue, I have gotten a decent amount of comments that someone should do the same thing with React. I’d love to see how it compares so maybe it’s time to start planning my next blog series…

OK, it’s settled. Let’s do both.

## CSS Variables

The first step is the same as my other articles, grab the [base starter file](https://github.com/davefollett/JavaScript30/blob/master/00%20-%20Getting%20Started/index-VUE.html) from my [getting started](/davefollett/a-new-vue-on-javascript30---getting-started-4o61) article and insert the code from the original #JavaScript30 project into their corresponding Vue locations.

- The HTML section goes inside the root `<div id="app">`
- The function went into the `methods` section
- The `<style>` section was moved into my Vue version
- The `computed` section was removed because it was not needed

Like the other articles, this gets us most of the way to a working solution but not quite. We have some more work to do. First, I added three fields to the Vue Instance data object: `spacing`, `blur`, and `base` and assigned their initial values to match #JavaScript30’s.

{% gist https://gist.github.com/davefollett/282ac7e9c4706c6524ddd2303f346c65 %}

Next, in the HTML section I used the `v-model` directive to bind each `<input>` element’s value to the corresponding Vue Instance data fields. When the `<input>` element changes, Vue will take care of updating the data fields for us. The `v-model` directive also will use the correct method for updating the `<input>` element based on the input type. So that means we don’t have to bind to any events, Vue takes care of it for us. For more information on the the `v-model` directive, I recommend the official Vue Docs [here](https://vuejs.org/v2/guide/forms.html). You also may notice that I removed the `name` and `data-sizing` attributes from the `<input>` elements. They won’t be needed in the final solution.

{% gist https://gist.github.com/davefollett/7bdcdef0741b3566c72af09066bc74cf %}

We are nearly finished - now we just need methods that can update the CSS Variables and then use them to initialize and update them on change. Let’s first look at the code and then I will walk through what each part does.

{% gist https://gist.github.com/davefollett/8487f950f0617db5a03282e1815ec0c8 %}

I created 4 methods for updating the CSS variables but 3 of them, `updateCSSSpacing()`, `updateCSSBlur()`, and `updateCSSBase()`, just use the `updateCSSVariable(name, value)` method with specific arguments. The important take away here is that with Vue you can access the root DOM element that the Vue instance is managing with `this.$el` and then set its style properties like this: `this.$el.style.setProperty(name, value)`.

To initialize the CSS variables I invoked the `updateCSSSpacing()`, `updateCSSBlur()`, and `updateCSSBase()` methods from the `mounted` lifecycle hook.

And to update the CSS variables on change, I set Vue watchers on the data fields to call the appropriate method. Vue’s watchers are another really great feature. In addition to just knowing when something changes, you also get access to the new and previous values of what changed. For this example, I only care about the latest value. For more information on Vue’s watchers, I recommend the official Vue Docs [here](https://vuejs.org/v2/guide/computed.html#Watchers).

## Putting It All Together - CSS Variables

{% codesandbox yvyqm83lnz initialpath=03%20-%20CSS%20Variables%2Findex-VUE-CSS-VARIABLES.html module=%2F03%20-%20CSS%20Variables%2Findex-VUE-CSS-VARIABLES.html %}

I feel like the best way to wrap up this solution is to walk through it in sequence:

1. The CSS variables are initialized when Vue is `mounted`
2. When the user changes an `<input>` element, the `v-model` directive detects the `<input>` element change and stores the value into the corresponding Vue data field.
3. Changing the Vue data field will trigger the Vue watcher which will then call the appropriate method to update the CSS variable.

While this solution works and maintains the spirit of this #JavaScript30 project, I feel like Vue provides an easier way to achieve the same end result, just not with CSS variables.

## Vue Style Bindings And Computed Properties

This solution starts out similar to the CSS variables solution in that I:

- Used my [base starter file](https://github.com/davefollett/JavaScript30/blob/master/00%20-%20Getting%20Started/index-VUE.html)
- Inserted the #JavaScript30 HTML and Style sections into it
- Created the three fields to the Vue Instance data object: `spacing`, `blur`, and `base`.
- Used the `v-model` directive to bind the `<input>` element to those data fields.

But instead of creating methods, watchers, and using the `mounted` lifecycle hook, I created the computed properties: `spanStyle` and `imgStyle` which use the three data fields `spacing`, `blur`, and `base` to return the proper CSS to be used. For more information on Vue’s computed properties, I recommend the official Vue Docs [here](https://vuejs.org/v2/guide/computed.html#Computed-Properties).

{% gist https://gist.github.com/davefollett/1a9a9cf1a1c768a73c6b1c2ceb7d101f %}

Then I bound computed properties to the appropriate HTML elements (`<img>` and `<span>`) using Vue’s style binding (`:style`).

{% gist https://gist.github.com/davefollett/f069ae7813005936310ee8e7ea13d690 %}

## Putting It All Together - Again

{% codesandbox yvyqm83lnz initialpath=03%20-%20CSS%20Variables%2Findex-VUE-COMPUTED-STYLES.html module=%2F03%20-%20CSS%20Variables%2Findex-VUE-COMPUTED-STYLES.html %}

Looking at the whole thing together, I think this solution is better than my CSS variables version but it kinda feels like cheating since the entire purpose of this #JavaScript30 project was to learn about CSS variables. Regardless, I’m glad I did both approaches. Here are links to the #JavaScript30 version as well as my two versions:

- [#JavaScript30’s project 03 - CSS Variables](https://github.com/davefollett/JavaScript30/blob/master/03%20-%20CSS%20Variables/index-FINISHED.html)
- [A New Vue On JavaScript30 - CSS Variables Version](https://github.com/davefollett/JavaScript30/blob/master/03%20-%20CSS%20Variables/index-VUE-CSS-VARIABLES.html)
- [A New Vue On JavaScript30 - Style Bindings And Computed Properties](https://github.com/davefollett/JavaScript30/blob/master/03%20-%20CSS%20Variables/index-VUE-COMPUTED-STYLES.html)

I hope you enjoyed this article, feel free to message me with any questions, comments, or _corrections_. All code presented within this series is available in [my fork](https://github.com/davefollett/JavaScript30) of the official [#JavaScript30 GitHub repository](https://github.com/wesbos/JavaScript30) which is located at:

- [https://github.com/davefollett/JavaScript30](https://github.com/davefollett/JavaScript30)

## Up Next

Next in the [A New Vue On JavaScript30](/t/anewvueonjs30) series is:

{% link /davefollett/a-new-vue-on-javascript30---05-flex-panel-gallery-5g8f %}