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 forv-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 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.$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.
Putting It All Together - CSS Variables
I feel like the best way to wrap up this solution is to walk through it in sequence:
- The CSS variables are initialized when Vue is
mounted
- When the user changes an
<input>
element, thev-model
directive detects the<input>
element change and stores the value into the corresponding Vue data field. - 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
, andbase
. - 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:
- #JavaScript30’s project 03 - CSS Variables
- A New Vue On JavaScript30 - CSS Variables Version
- A New Vue On JavaScript30 - Style Bindings And Computed Properties
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)