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

Exploring the pitfalls of nesting

It has to be said that although nesting is a simple technique to understand, it can be difficult to get right, as shown in our SASS version of the demo:

Exploring the pitfalls of nesting

The issues we have here are twofold—the multiple levels of nesting result in a high level of code specificity; if we wanted to change the styling for .nav-panel ul li (the compiled version of line 125), it would likely break the appearance of our front end code. To see what I mean, let's take an example HTML page that any developer might create:

<body>
  <div class="container">
    <div class="content">
      <div class="articles">
        <div class="post">
          <div class="title">
            <h1><a href="#">Hello World</a>
          </div>
          <div class="content">
            <p></p>
            <ul>
              <li>...</li>
            </ul>
          </div>
          <div class="author">
            <a href="#" class="display"><img src="..." /></a>
            <h4><a href="#">...</a></h4>
            <p>
              <a href="#">...</a>
              <ul>
                <li>...</li>
              </ul>
            </p>
          </div>
        </div>
      </div>
    </div>
  </div>
</body>

Now, before you all scream, Yuk, I would never do that! at me, and claim (quite rightly) that we should use semantic elements such as <header>, <section>, <article>, and / or <footer> to provide context and meaning, instead of all of these <div> statements, then stop! There is a point in producing that ugly mix of code. Let me explain:

The example HTML we have just seen is likely to result in this nested CSS:

body {
  div.container {
    div.content {
      div.articles {
        & > div.post {
          div.title {
            h1 {
              a {
              }
            }
          }
          div.content {
            p { ... }
            ul {
              li { ... }
            }
          }
          div.author {
            a.display {
              img { ... }
            }
            h4 {
              a { ... }
            }
            p {
              a { ... }
            }
            ul {
              li { ... }
            }
          }
        }
      }
    }
  }
}

Some developers might think this is perfectly acceptable—after all, they know no different, so why should it be an issue, right? Wrong—this code, while it may technically fit the styles in our HTML document, has several issues with it:

  • It is awkward to read at best, and enough to give anyone a headache when trying to decipher it.
  • Try compiling it; it will result in a lot of duplicated parent selectors, with code stretching to around 20 lines.
  • Rendering performance is likely to be poor—if for example, a tool such as Google's Page Speed is installed, then it is likely to trigger the Prioritize Visible Content rule, where additional round trips are needed to render content on-screen above the fold.
  • Size is likely to be an issue—even though we live in an age of broadband connections, it is bad manners to take a cavalier attitude to content, and not create something in as small a footprint as possible.
  • Maintainability will become a problem—our example code has bound styles too tightly, which defeats the purpose of cascading style sheets, where we should be able to place common styles in a parent selector and allow these to cascade down to children, or be overridden as required.

How can we get around it? The simplest answer is to be sensible about the number of levels we use when nesting code—some developers argue no more than four; I would argue from experience that two should be sufficient (which in this case would be body div.content, had we compiled our monster CSS style sheet).

There is nothing to stop us from using four levels if we absolutely have no other way of achieving our desired result; if we're doing this regularly, then we clearly need to revisit our code!

Taking a better approach

If, when working on code, we are forced to regularly use nested styles that are more than two or three levels deep, then there are some tricks we can use to reduce both the CSS specificity over time, and the need to use nesting more than two to three levels deep. Let's take a look at a few:

  • Can you give yourself the class you need? Specificity can creep in if we're overriding an existing selector:
    .section-header {
      /* normal styles */
    }
    
    body.about-page .section-header {
      /* override with higher specificity */
    }

    To avoid specificity, can a class be emitted through the use of server-side code or functions, which we can use to style the element instead?

    <header class="<%= header_class %>">

    Which could output one class, or both, as desired:

    </header>
    .section-header {
      /* normal styles */
    }
    
    .about-section-header {
      /* override with same specificity */
      /* possibly extend the standard class */
    }
  • The order of your style sheets can play an important role here, even though you might use a single class to override styles:
    <header class="section-header section-header-about">
    ...
    </header>

    Your existing class may be overriding your override; both selectors have the same specificity, so the last rule(s) to be applied will take precedence. The fix for this is simply to rework the order in which your style rules are applied, so that overriding classes can be applied later.

  • Consider reducing the specificity of the element you're trying to style; can the element be replaced, or removed in its entirety? If, however, it's being used within JavaScript (or jQuery) code, then it is preferable to leave it as-is, and add a second class (or use an existing class already applied, if one exists).
  • Where possible, aim to use as flat a structure as possible for your code; it is too easy to style an element such as this:
    .module > h2 {
    
    }

    In this example, we're styling all h2 elements that are direct children of the parent .module class. However, this will work until we need to assign a different style for the h2 element. If the markup looks similar to this example:

    <div class="module">
      <h2 class="unique">
        Special Header
      </h2>
    </div>

    …it will be difficult to apply styles easily, due to CSS specificity creeping in:

    .module > h2 {
      /* normal styles */
    }
    .unique {
      /* I'm going to lose this specificity battle */
    }
    .module .unique {
      /* I'll work, but specificity creep! */
    }
  • To avoid this, using as flat a structure as possible is recommended—it will be worth the extra effort required to set it up:
    <div class="module">
      <h2 class="module-header">
      </h2>
      <div class="module-content">
      </div>
    </div>
  • Consider using an established pattern library, or atomic design (such as the one at http://patternlab.io/), to help guide you through how a site should be built—they are likely to be built using minimal CSS specificity, and with hopefully little need to override existing code.
  • Be careful if you decide to use cascading when applying CSS styles—if we apply a base style to an element (or class) that is reused multiple times, this will cause issues. To avoid this, try to avoid using cascading if it isn't really needed; consider limiting it to 2-3 levels only, to reduce risk of odd or unexpected styles being applied.
  • Sometimes code is outside of your control—in instances such as this, we have to work with it; we can either try using low specificity selectors where possible, or use the !important keyword to override the code. For now, we may have to leave comments in the code to explain why the selectors are set as such; in an ideal world, we would try to contact the authors to see if they can update or alter the code to remove these issues.
  • As a last resort, if you must get into the realms of CSS specificity, then try to only apply a light touch, and not take the sledgehammer approach, such as using a selector ID or !important.

    We can try applying a single class to an existing tag, but this may not feel right for some; an alternative is to use two classes:

    .nav .override {
    }
    .override .override {
    }
    .nav {
    }

    The key here, though, is to not use more than one additional class!

  • Nesting styles can lead to writing overly specific selectors in our code—some developers discourage its use for this reason, even though nesting can help make our code visually easier to read and digest. Instead of using compound selectors, we can emulate a form of name-spacing by using the ampersand symbol:
    .somestyle {
        color: darkred;
       &-so {
          color: blue;
          &-ever {
            color: green;
          }
       }
    }

    …which will compile to this:

    .somestyle { color: darkred; }
    . somestyle-so { color: blue; }
    .somestyle-so-ever { color: green; }
  • If your style is overriding a style that is already an override—stop: Why are you doing this? Overriding a class or selector element can be an efficient way of styling, but applying a second override will only cause confusion.

We've seen a number of ways of avoiding, or reducing CSS specificity issues that are inherent with nesting; the key message, though, is that we are not forced to have to nest our code, and that, to paraphrase the front-end architect Roy Tomeij—nested code doesn't create bad code; bad coders do!

Tip

You can see the original article by Roy Tomeij at http://www.thesassway.com/editorial/sass-doesnt-create-bad-code-bad-coders-do

There is one method, though, that we've not touched on, and for good reason: it's a route many developers new to using processing will likely take for the first time. Intrigued? It has something to do with using conversion tools, and more specifically, how we use them to convert from plain CSS to code suitable for compiling using PostCSS.

Reconsidering our code

Imagine this scenario, if you will:

You've taken over a website, and are keen to make use of PostCSS to help with maintaining your code. The code uses plain vanilla CSS, so as a step to converting it, you happen to know of a number of sites that will convert plain CSS to SASS. After all, there are some similarities between PostCSS and SASS code, so why not?

You extract the results into a text file, save it, and put it through a SASS compilation process. Out comes some newly compiled CSS, which you drop into the relevant location on your server, and voilà! You have a working site that now uses SASS. A working site, and a perfect basis for converting to PostCSS…or is it?

The short answer should be no, but the longer one is that it will depend on your code. Let me explain why:

Simply pushing code through a conversion process isn't enough—granted, it will give you code that works, but unless it is very simple, it is likely not to give code that is concise and efficient. To see what I mean, take a close look at the CSS style sheet from Tutorial5—and specifically, the style rules for .nav-panel, from around line 132.

Tip

For reasons of space, the style sheet is too long to print in full—I would recommend taking a look at the file from the code download in a text editor!

A conversion process will have no problem processing it to produce valid SASS, but it won't look pretty—as an example, try copying lines 114 to 197 into the converter hosted at http://css2sass.herokuapp.com/. Doesn't look great, does it? There is definitely room for improvement—I've already made some changes to the code, but we can do more; let's take a look at what can be done to improve the code.

Updating our code

When using a CSS to SASS convertor, the one key point that should always be at the back of our minds is that the converted code should not be considered the final article.

It doesn't matter how simple or complex your code is—it should be the first step in our conversion process. It's just a matter of how little or how much we have to do, once the code has been through the converter! As an example, take a look at this block of code:

Updating our code

It's a direct copy of lines 234 to 239 of the compiled version of the pen by Nikolay, which we used as a basis for our earlier demos. Now take a quick look at the equivalent code that I tweaked from the original and used in my version:

Updating our code

Notice any differences? The vendor prefix version of the transform attribute has been stripped out—most modern browsers (certainly within the last year to eighteen months), should handle this code without the need for vendor prefixes. The original version also suffered from a high degree of CSS specificity—this will become even more apparent if the code is nested!

To improve it, I've switched in .nav-panel ul li as a direct replacement for .nav-panel ul .nav-btn—the code is relatively simple in that it does not need a second class to identify elements for styling purposes. The next logical step is to break up the large nesting block within the source file; it is tempting to include a single large block, but this will be at the expense of readability, maintenance, and performance.

We could potentially go even further, and consider removing the leading .nav-panel; not only will it make the code infinitely easier to read, but it will also reduce the issues around CSS specificity. Of course, this kind of change will depend on what is in your code; the point here is to examine your code thoroughly, and look to reduce any CSS specificity as much as possible, so that your nesting won't look so bad!

There is an alternative means we can use though, which removes issues around CSS specificity—using Block Element Modifier notation (or BEM for short). It's a great way to systematically style elements using CSS, and it is worth taking time to get accustomed to how it works. Let's dive in and take a look.