Updating our hover effect demo
If we're altering code to use PostCSS for the first time, it naturally makes sense to start with something simple; incorporating variables and mixins into our code is the perfect place to begin.
For this next exercise, we're going to create a handful of variables to store some values, then add a mixin to handle styles for the fonts used in the demo. Let's make a start:
- We'll start by opening up a copy of
gulpfile.js
from the root of our project area—we first need to make some changes to accommodate using the new plugin. - In
gulpfile.js
, add this line immediately below the first block ofvar
statements—this should be on or around line 9:var cssvariables = require('postcss-css-variables');
- We now need to make some changes to our gulp task file—we'll start with the simplest, which is to remove the
var
reference to SASS, as we will no longer need it:var sass = require('gulp-sass');
Now that we have a reference to the
postcss-css-variables
plugin, we need to make use of it in our tasks. Go ahead and amend the highlighted lines of code in theautoprefixer
task, as indicated; this also removes the dependency on the lint-styles task, as this is no longer needed:gulp.task('autoprefixer', function() { return gulp.src('src/*.css') .pipe(postcss([ autoprefixer, cssnano, cssvariables(/* options */) ])) .pipe(gulp.dest('dest/'));
- Note that we've also reinstated the
cssnano
command—you will also need to add this line in as a variable declaration, as indicated:var rename = require('gulp-rename'); var cssnano = require('cssnano');
- A little further down, on or around line 25, change the code as highlighted, as we will no longer use SASS to compile our code; we can tweak the order in which each task is run:
gulp.task("lint-styles", ['autoprefixer'], function() {
- Next up, we can remove the SASS task in its entirety:
gulp.task('sass', function () { gulp.src('src/*.scss') .pipe(sass({outputStyle: 'compressed'}) .on('error', sass.logError)) .pipe(gulp.dest('src/')); });
- Toward the end of the file, go ahead and alter the default task as indicated—we don't need to call the SASS task, as it has now been removed:
gulp.task('default', ['lint-styles', 'autoprefixer', 'rename']);
- Alter the
gulp.watch
command to look for plain CSS files in thesrc
folder—we're not using SASS, so the reference toscss
format files is now invalid and needs to be changed:var watcher = gulp.watch('src/*.css', ['default']); watcher.on('change', function(event) {
At this point, if all is well, we should have a working gulp task file that we can now use to compile our code. Let's go ahead and start to convert the code in our orchid demo, to use PostCSS:
- We'll start by saving a copy of the
Tutorial2
folder from the code download that accompanies this book, locally, to within the project area we created underc:\wamp\www
, back in Chapter 1, Introducing PostCSS. - Open up a copy of
style.css
from within thesrc
folder of theTutorial2
folder. At the top of the file, remove lines 1 to 14 (the variables and mixin code), so that the file starts with thefont-face
declaration. - In its place, add the following lines—these are the replacement variable assignments:
:root { --dark-grayish-green: #868a7b; --very-dark-gray: #333333; --white: #fff; --fullsize: 100%; }
- Further down, look for the
html
,body {
declaration, and alter it as indicated—note the syntax used for thevar
statements; this is not the same as standard SASS. We've changed it to the format supported by thepostcss-css-variables
plugin:html, body { width: var(--fullsize); padding: 0; margin: 0; height: var(--fullsize); min-width: var(--fullsize); max-width: var(--fullsize); overflow: hidden; background: var(--dark-grayish-green); }
- We added the
--fullsize
variable at the top of our style sheet—let's make use of it now and update theimg
rule accordingly:img { width: var(--fullsize); height: var(--fullsize); }
- The final change we will make is to the
.info
class—go ahead and alter the background attribute as indicated:/* ------ Hover Effect Styles ------ */ .info { background: var(--very-dark-gray); }
Our code changes are complete, so go ahead and save the file—once done, fire up a NodeJS command prompt, and change to the project working area.
- Save the file as
styles.css
into thesrc
folder of our project area. - Switch to the NodeJS command prompt, then enter the usual command at the prompt, and press Enter:
gulp
- Copy the compiled code back to the
css
folder withinTutorial2
. If all is well, when we preview the results in a browser, we should see our demo continue to work as shown at the start of the first part of this exercise.
Phew, there were a fair few steps there! There is a copy of the completed stylesheets, both prior to and post compilation, available in the code download that accompanies this book: they can be found in the css
| completed
folder. You will need to rename the two style sheet files to just style.css
for them to work correctly.
If you want to see the effects of compiling variables, without committing changes to code, then have a look at the playground offered with this plugin, at https://madlittlemods.github.io/postcss-css-variables/playground/. It's a great way to get accustomed to using the postcss-css-variables
plugin, before diving in and editing production code.
Okay, let's change tack; we've covered a number of key concepts in our demo, so let's take a moment to let the proverbial dust settle, and explore what we've learned through the demo.
Taking it a step further
Over the last few pages, we've created a simple demo, which shows off animated information boxes for a couple of orchid images. There's nothing outrageous or complex about what we've done, but nevertheless, it serves to illustrate some key points about using this plugin, and PostCSS in general:
- Although we used SASS to precompile our CSS code prior to conversion, we could easily have used another pre-processor, such as Less CSS or Stylus. The key here is to work as much as possible within the confines of a task runner such as Gulp, so that we don't need to introduce another technology into the mix.
- It is essential to note that although converting the code looks straightforward, the plugin does not compile in the same manner as pre-processors such as SASS would compile. It makes a direct translation from SASS to Less CSS difficult for anything more than simple code.
- In this example, the key to understanding how it works is to follow the CSS Custom Properties Module Level 1 document from the W3C, which is available at https://drafts.csswg.org/css-variables/. The trick here is to be aware of CSS specificity, or which element takes precedence over others; in this respect, PostCSS does not simply replace variables with values, but compiles code based on calculating CSS specificity. When using PostCSS, it is likely you will see the
:root
pseudo-element being used frequently—it's worth getting acquainted with how it works!Note
For an explanation of how CSS specificity works, please refer to http://vanseodesign.com/css/css-specificity-inheritance-cascade/. If needed, we can consider using a plugin to increase specificity—check out the
postcss-increase-specificity
plugin at https://github.com/MadLittleMods/postcss-increase-specificity. - The modular nature of PostCSS means that we can be selective about the plugins we use—in this instance we used the
postcss-css-variables
plugin, which gives more flexibility than others such aspostcss-custom-properties
. As an alternative, we might consider separating our variables into a separate document, and import them in using thepostcss-constants
plugin (which is available at https://github.com/macropodhq/postcss-constants). - If we use the
postcss-css-variables
plugin, we can either store the values in the code itself, or hive them off into the gulp task file; an example of the latter would look like this:var postcss = require('postcss'); var cssvariables = require('postcss-css-variables'); postcss([ cssvariables({ variables: { '—foo-var': { '100px', isImportant: true }, '--other-var': { value: '#00CC00' }, '--important-var': { value: '#ffCC00' } } }) ]) .process(css, opts);
In short, we create a reference to each variable within the configuration object for cssvariables
, as the alias for the postcss-css-variables
plugin.
Creating an object map using this approach can have mixed benefits. For some, it reduces issues around separation of concerns, where we can keep more PostCSS code within the task file, and less within our style sheet. This can make for a task file that is harder to read; it's not a good route to take if you have lots of variables to define. In this instance, we would be better off exporting them to an import file and referencing them at compilation.
If there is one important message at this point, it can be that of flexibility—the modular nature of PostCSS means that we can be free to pick and choose how we proceed; it really is a case of weighing up the pros and cons of using a plugin, and making a decision as to whether this best fits our needs, or if we need to look for an alternative solution.