DEV Community

Cover image for A New Vue On JavaScript30 - 03 CSS Variables
Dave Follett
Dave Follett

Posted on • Originally published at on

A New Vue On JavaScript30 - 03 CSS Variables

This article is part of the A New Vue On JavaScript30 series that explores re-implementing #JavaScript30 projects using Vue. Today we will be working with the third of Wes Bos’s (@wesbos) #JavaScript30 projects titled: 03 - CSS Variables. This project uses an HTML inputs to control 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


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 Slack channel 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 from my getting started 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.

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. 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.

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.

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.$, 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.

Putting It All Together - CSS Variables

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
  • 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.

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

Putting It All Together - Again

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:

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 of the official #JavaScript30 GitHub repository which is located at:

Up Next

Next in the A New Vue On JavaScript30 series is:

Top comments (0)