Table of Contents for
Mastering PostCSS for Web Design

Version ebook / Retour

Cover image for bash Cookbook, 2nd Edition Mastering PostCSS for Web Design by Alex Libby Published by Packt Publishing, 2016
  1. Cover
  2. Table of Contents
  3. Mastering PostCSS for Web Design
  4. Mastering PostCSS for Web Design
  5. Credits
  6. About the Author
  7. About the Reviewer
  8. www.PacktPub.com
  9. Preface
  10. What you need for this book
  11. Who this book is for
  12. Conventions
  13. Reader feedback
  14. Customer support
  15. 1. Introducing PostCSS
  16. Introducing PostCSS
  17. Setting up a development environment
  18. Creating a simple example using PostCSS
  19. Linting code using plugins
  20. Exploring how PostCSS works
  21. Summary
  22. 2. Creating Variables and Mixins
  23. Creating a hover effect example
  24. Transitioning to using PostCSS
  25. Adding variable support to PostCSS
  26. Updating our hover effect demo
  27. Setting the order of plugins
  28. Creating mixins with PostCSS
  29. Looping content with PostCSS
  30. Summary
  31. 3. Nesting Rules
  32. Navigating through pages
  33. Transitioning to using PostCSS plugins
  34. Exploring the pitfalls of nesting
  35. Making the switch to BEM
  36. Exploring our changes in more detail
  37. Summary
  38. 4. Building Media Queries
  39. Exploring custom media queries in PostCSS
  40. Making images responsive
  41. Adding responsive text support
  42. Optimizing media queries
  43. Retrofitting support for older browsers
  44. Moving away from responsive design
  45. Taking things further with CSS4
  46. Summary
  47. 5. Managing Colors, Images, and Fonts
  48. Managing fonts with PostCSS
  49. Creating image sprites
  50. Working with SVG in PostCSS
  51. Adding support for WebP images
  52. Manipulating colors and color palettes
  53. Creating color functions with PostCSS
  54. Summary
  55. 6. Creating Grids
  56. Creating an example with Bourbon Neat
  57. Exploring the grid plugins in PostCSS
  58. Transitioning to using PostCSS-Neat
  59. Creating a site using Neat and PostCSS
  60. Adding responsive capabilities
  61. Summary
  62. 7. Animating Elements
  63. Moving away from jQuery
  64. Making use of pre-built libraries
  65. Switching to using SASS
  66. Making the switch to PostCSS
  67. Exploring plugin options within PostCSS
  68. Updating code to use PostCSS
  69. Creating a demo in PostCSS
  70. Optimizing our animations
  71. Using our own animation plugin
  72. Summary
  73. 8. Creating PostCSS Plugins
  74. Dissecting the architecture of a standard plugin
  75. Creating an transition plugin
  76. Building a custom font plugin
  77. Simplifying the development process
  78. Guidelines for plugin building
  79. Making the plugin available for use
  80. Summary
  81. 9. Working with Shortcuts, Fallbacks, and Packs
  82. Exploring plugin packs for PostCSS
  83. Adding shortcuts with Rucksack
  84. Linting and optimizing your code
  85. Providing fallback support
  86. Summary
  87. 10. Building a Custom Processor
  88. Exploring our processor
  89. Dissecting issues with our processor
  90. Optimizing the output
  91. Adding reload capabilities
  92. Extending our processor further
  93. Testing the final pre-processor
  94. Getting started with some hints and tips
  95. Introducing the CSStyle library
  96. Summary
  97. 11. Manipulating Custom Syntaxes
  98. Preparing our environment
  99. Implementing custom syntax plugins
  100. Parsing CSS
  101. Formatting the output with the API
  102. Highlighting our syntax code
  103. Summary
  104. 12. Mixing Preprocessors
  105. Exploring the conversion process
  106. Introducing the Pleeease library
  107. Compiling with other preprocessors
  108. Using the PreCSS library
  109. Converting a WordPress installation
  110. Setting up our environment
  111. Considering the conversion process
  112. Making changes to our code
  113. Compiling and testing the changes
  114. Summary
  115. 13. Troubleshooting PostCSS Issues
  116. Exploring some common issues
  117. Getting help from others
  118. Summary
  119. 14. Preparing for the Future
  120. Converting CSS4 styles for use
  121. Supporting future syntax with cssnext
  122. Creating plugins to provide extra CSS4 support
  123. Summary
  124. Index

Making the switch to BEM

So what is BEM, and why can it help with reducing or removing CSS specificity issues?

BEM, or Block Element Modifier, helps us style elements using a systematic naming convention, which is structured thus:

  • .block: top-level containing the element we're going to change
  • .block__modifier: the style assigned when the state of an element is changed
  • .block__element: an element inside a top-level container
  • .block__element__modifier: alternate representation of an element, when its state has been changed

The idea behind this style of coding is to make it portable and easier to maintain. The basis for this is that, while standard, non-BEM CSS is more concise, it is harder to infer what each rule does. We frequently have to assign multiple classes to an element, which introduces a degree of CSS specificity, and reduces the reusability of CSS rules. Using BEM allows us to combine the constituent names into one style class name, and remove any concern around CSS specificity.

If we use this concept, we can use it to write style rules such as this:

.block {
  &__element {
  }
  &__modifier {
  }
}

This will compile to the following:

.block {}
.block__element {}
.block__modifier {}

The preceding code uses plain BEM format, but from within a processor environment such as SASS to construct BEM rules in PostCSS, we can use the postcss-bem plugin (available from https://github.com/ileri/postcss-bem) to produce our BEM CSS using @-rules. For example:

@component ComponentName {
  color: cyan;
 
  @modifier modifierName {
    color: purple;
  }
 
  @descendent descendentName {
    color: darkred;
  }
 
  @when stateName {
    color: yellow;
  }
}

In this instance, @component signifies our Block, @descendant our element, and @modifier is our modifier. When compiled, our CSS would look like this:

.ComponentName {
  color: cyan;
}
 
.ComponentName--modifierName {
  color: purple;
}
 
.ComponentName-descendentName {
  color: darkred;
}
 
.ComponentName.is-stateName {
  color: yellow;
}

The beauty of using BEM is that it helps to reduce or even avoid CSS specificity issues—although names are longer, we can combine both element and modifier names into one class, instead of having to apply three or more separate classes. Granted, there may be instances where we might have to apply a second class, but with careful planning we should be able to reduce this to a minimum.

Right, onwards we go: let's get stuck in to coding! Over the next few pages, we will take a look at implementing BEM styling in a simple demo, and see how we can use PostCSS to compile our code.

Creating simple message boxes

For our BEM demo, we're going to work through the CSS rules required to show some simple message boxes on screen, such as for displaying confirmation that a task has completed, or a warning when something isn't right.

Tip

The original version of this demo, by Rene Spronk, is available from http://www.cssportal.com/blog/css-notification-boxes/.

It's a simple demo, but shows off the principles behind BEM CSS perfectly—go ahead and extract a copy of the Tutorial8 folder, then run index.html to get a feel for what we will be producing. This version uses standard CSS; we will use this as a basis for converting to using BEM.

Let's make a start:

  1. We'll begin by extracting a copy of the Tutorial9 folder from the code download that accompanies this book—drop this into our project area.
  2. Next, in a new file, add the following CSS statements starting at line 1, and leaving a one-line gap between each—they should be fairly self-explanatory, but we will go through each block in turn.
  3. We kick off with the core styles for each dialog—this is a basis style for each dialog box:
    .dlgBox {
      border-radius: 0.625rem;
      padding: 0.625rem 0.625rem 0.625rem 2.375rem;
      margin: 0.625rem;
      width: 14.5rem
    }
  4. Next up comes a simple style for each <span> element—this turns the lead-in caption for each dialog to uppercase and sets it in bold text:
    span { font-weight: bold;text-transform: uppercase; }
  5. We now need to add our block element—it's the opening line that forms the basis for our styling:
    @component content {
  6. Next up comes the Element part of our style rule. These rules need to be added as nested (that is, indented) rules immediately underneath—using the PostCSS plugin, we add it in as a @descendent of our @component:
       @descendent alert {
         font-family: Tahoma, Geneva, Arial, sans-serif;
         font-size: 0.6875rem;
         color: #555;
         border-radius: 0.625rem; 
       }
  7. Up next comes the first of our status messages—we kick off with styling the Error message first; the main rule adds an error icon and styles the border. The :hover pseudo-element reduces the opacity when we hover over the box:
       @modifier error {
         background: #ffecec url("../img/error.png") no-repeat 0.625rem 50%;
         border: 0.0625rem solid #f5aca6; 
       }
    
          @modifier error:hover { opacity: 0.8; }
  8. This is swiftly followed by styling for the Success message:
       @modifier success {
         background: #e9ffd9 url("../img/success.png") no-repeat 0.625rem 50%;
         border: 0.0625rem solid #a6ca8a; 
       }
    
       @modifier success:hover { opacity: 0.8; }
  9. We can't forget the obligatory Warning message, so here's the style rule for that status:
       @modifier warning {
         background: #fff8c4 url("../img/warning.png") no-repeat 0.625rem 50%;
         border: 0.0625rem solid #f2c779; 
          }
    
          @modifier warning:hover { opacity: 0.8; }
  10. Last but by no means least, here's the final one, which is Notice; it includes the closing bracket for the BEM nesting:
          @modifier notice {
            background: #e3f7fc url("../img/info.png") no-repeat 0.625rem 50%;
            border: 0.0625rem solid #8ed9f6; 
          }
    
       @modifier notice:hover { opacity: 0.8; }
    }
  11. Save the file as style.scss into the src folder of our top-level project area (and not into the Tutorial8 folder!).

Our simple demo isn't going to set the world alight in terms of styling. If we were to preview it now, the results will of course not look great; let's fix that by setting up the compilation and linting tasks within PostCSS.

Note

If you are a SASS user, then you can see a version of this code suitable for that processor on GitHub—the code is available at: https://gist.github.com/alibby251/45eab822a6a619467279. Note how similar the results are when you compare the compiled version with the version we'll get in the next exercise!

Compiling and linting our code

Our code is in place, but the boxes won't look particularly appetizing—most of the styles are still written using PostCSS @-rules. We can fix that by compiling the code, so let's dive in and take a look at installing support for BEM.

Installing BEM support

Setting up BEM support in PostCSS is a cinch—we can make use of two plugins to compile and lint our code. The plugins we need for this task are postcss-bem (available from https://github.com/ileri/postcss-bem), and postcss-bem-linter (available from https://github.com/postcss/postcss-bem-linter). Both can be installed using the same process through Node.js.

Hopefully the process will be familiar by now, so without further ado, let's make a start:

  1. We'll begin by firing up a Node.js command prompt, and navigating to our working folder.
  2. At the command prompt, enter this command then press Enter:
    npm install --save-dev postcss-bem
    
  3. Node.js will install each of the elements required; if all is well, we should see this result, to indicate a successful installation:
    Installing BEM support
  4. Repeat the same process for postcss-bem-linter, using this command:
    npm install --save-dev postcss-bem-linter
    
    Installing BEM support
  5. Keep the command prompt session open, but minimized. We're going to make use of it again in a moment!

Now that the plugin is installed, we can go ahead and add support to our gulp task file, and begin to parse our code:

  1. First, go ahead and remove the existing gulpfile.js file at the root of our project area.
  2. In a new file, add the following lines and save it as gulpfile.js, at the root of our project area. We start with setting a number of variables that call each of the plugins:
    var gulp = require('gulp');
    var postcss = require('gulp-postcss');
    var bem = require('postcss-bem');
    var bemLinter = require('postcss-bem-linter');
    var reporter = require('postcss-reporter');
  3. The first task in the file checks the code for consistency with BEM standards, and displays any errors on-screen:
    gulp.task('lint', function() {
      return gulp.src('dest/*.css')
        .pipe(postcss([
          bemLinter({ preset: 'bem' }),
          reporter({ clearMessages: true })
        ]))
        .pipe(gulp.dest('dest/'));
    });
  4. The second task in the file compiles the BEM code to valid CSS:
    gulp.task('bem', function() {
      return gulp.src("src/*.css")
        .pipe(postcss([bem({
          style: 'bem',
          separators: { descendent: '__' }
        })]))
        .pipe(gulp.dest('dest/'));
    });
  5. This task is the default that is called when we run gulp from the command line; it calls each of the tasks in turn:
    gulp.task('default', ['bem', 'lint']);
  6. We finish the gulpfile.js with a watch facility, to kick in and compile our code when any changes are made to it:
    var watcher = gulp.watch('src/*.css', ['default']);
    watcher.on('change', function(event) {
      console.log('File ' + event.path + ' was ' + event.type + ', running tasks...');
    });
  7. We're going to replace the package.json file too—add these lines to a new file, and save it to the root of the project area. These simply tell gulp which versions of our plugins to use when compiling the code:
    {
      "name": "postcss",
      "version": "1.0.0",
      "description": "Configuration file for PostCSS",
      "main": "index.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      "author": "Alex Libby",
      "license": "ISC",
      "devDependencies": {
        "gulp": "^3.9.0",
        "gulp-postcss": "^6.0.0",
        "postcss-bem-linter": "^2.0.0",
        "postcss-reporter": "^1.3.0"
      }
    }
  8. From the code download that accompanies this book, go ahead and extract a copy of style.css from the css – completed version folder under Tutorial9—save this to the src folder under our project area.
  9. Revert back to the Node.js command prompt session we had before, then at the prompt, enter this command and press Enter:
    gulp
    
  10. If all is well, the code will be checked, and the results displayed on screen. You may see errors appear, such as those shown in this screenshot. If they do, they can be ignored for now (we will explore this in more detail later):
    Installing BEM support
  11. Go ahead and copy the contents of the dest folder into the css folder underneath Tutorial9—if all is well, we should see something akin to this screenshot when previewing the results in a browser:
    Installing BEM support

Our simple demo shows some useful message boxes that we can use as a basis for something more complex; it illustrates perfectly how we can use BEM to style our code, while keeping issues around CSS specificity at bay. We've covered a few useful techniques throughout this exercise, so let's take a moment to explore them in more detail.