Enabling Upcoming CSS Features with PostCSS

Share this article

Enabling Upcoming CSS Features with PostCSS

Picking up where we left off in the previous article, “The PostCSS Guide to Improving Selectors and Media Queries“, we will have a look at more PostCSS plugins that expand the horizons of CSS. The earlier article focused on improving the structure of your stylesheets through extending selectors and media queries. This one will concentrate on implementing new properties and values from upcoming specifications. The plugins covered in this article implement different functionality and can be effectively used both together and separately, depending on your needs.

We’ll start with my personal favorite.

Taking Resets to a New Level

CSS3 introduced two nice features: the initial value and the all property. The initial value used with values of inherit and unset allow you to reset a property to its original value. The all property serves as a shorthand property to reset every property to one of these three states. While each is interesting on their own, when used together, they allow you to quickly reset all styles for a particular element and prevent it from inheriting styles from parent elements of the page. Another step to writing modular CSS!

Sadly, both of these features are still not supported by IE. But, as you might have already guessed, there’s a plugin for that.

Postcss-initial adds support for the initial value and the all: initial combination. Here’s how it works:

.article {
  font-size: initial;
  color: initial;
  padding: initial;
  margin: initial;
}

Gets compiled into:

.article {
  font-size: medium;
  font-size: initial;
  color: #000;
  color: initial;
  padding: 0;
  padding: initial;
  margin: 0;
  margin: initial;
}

By default, it leaves the original properties with initial for browsers that natively support this feature.

The all property, in turn, will be translated into a long list of reset properties.

.container {
  all: initial;
}

Is transpiled into:

.container {
  animation: none 0s ease 0s 1 normal none running;
  backface-visibility: visible;
  background: transparent none repeat 0 0 / auto auto padding-box border-box scroll;
  border: medium none currentColor;
  border-collapse: separate;
  border-image: none;
  border-radius: 0;
  border-spacing: 0;
  bottom: auto;
  box-shadow: none;
  box-sizing: content-box;
  caption-side: top;
  clear: none;
  clip: auto;
  color: #000;
  columns: auto;
  column-count: auto;
  column-fill: balance;
  column-gap: normal;
  column-rule: medium none currentColor;
  column-span: 1;
  column-width: auto;
  content: normal;
  counter-increment: none;
  counter-reset: none;
  cursor: auto;
  direction: ltr;
  display: inline;
  empty-cells: show;
  float: none;
  font-family: serif;
  font-size: medium;
  font-style: normal;
  font-variant: normal;
  font-weight: normal;
  font-stretch: normal;
  line-height: normal;
  height: auto;
  hyphens: none;
  left: auto;
  letter-spacing: normal;
  list-style: disc outside none;
  margin: 0;
  max-height: none;
  max-width: none;
  min-height: 0;
  min-width: 0;
  opacity: 1;
  orphans: 2;
  outline: medium none invert;
  overflow: visible;
  overflow-x: visible;
  overflow-y: visible;
  padding: 0;
  page-break-after: auto;
  page-break-before: auto;
  page-break-inside: auto;
  perspective: none;
  perspective-origin: 50% 50%;
  position: static;
  right: auto;
  tab-size: 8;
  table-layout: auto;
  text-align: left;
  text-align-last: auto;
  text-decoration: none;
  text-indent: 0;
  text-shadow: none;
  text-transform: none;
  top: auto;
  transform: none;
  transform-origin: 50% 50% 0;
  transform-style: flat;
  transition: none 0s ease 0s;
  unicode-bidi: normal;
  vertical-align: baseline;
  visibility: visible;
  white-space: normal;
  widows: 2;
  width: auto;
  word-spacing: normal;
  z-index: auto;
  all: initial;
}

In case you are using BEM or Suit, this plugin works well with postcss-autoreset which will automatically reset styles for block and component-level elements.

Custom Properties

When working on a layout, we often have to share some values across the stylesheet. For example, your brand color might be used as a background for a button, a text color for a link or a border for a text block. Currently to achieve this, we would need to repeat the color multiple times in each place it is used. Such repetition makes it tedious to keep the color palette consistent when changing the colors across the application.

CSS preprocessors such as Less and Sass have solved this problem using variables. Fortunately, W3C are working on a similar concept called custom properties. Although addressing the same problem, they work differently from variables in preprocessors. Less and Sass variables are resolved at compilation time. When you compile your Less or Sass to CSS, the compiler will look for a variable declaration corresponding to the current compilation scope and replace each instance with the corresponding value. This means, that the resolved value of a variable depends solely on where it is used in the code. Custom properties, in turn, are defined for elements in the DOM and are accessible only to their child elements. This means that the value of a variable depends on the position of an element in the DOM and can only be resolved at run time.

By this point, you should frown or raise an eyebrow. If a value of a variable is only known at runtime, how can it be resolved by a PostCSS plugin? The truth is, it can’t. It does, however, provide a way to use a subset of that functionality. If we define all of our custom properties in the :root element, these properties will be accessible to all elements on the page. This means, that we can resolve them at compile time.

Here’s a simple example of how it may look:

:root {
  --text-color: red;
  --background: blue;
}

h1 {
  color: var(--text-color);
  font-size: var(--font-size, 20px);
}
button {
  background-color: var(--background);
}

Will be compiled into:

h1 {
  color: red;
  font-size: 20px;
}
button {
  background-color: blue;
}

Note that the --font-size variable is not defined, so it’s replaced with a fallback value of 20px. The important part here is to keep all of the custom properties inside of :root. The ones defined elsewhere will be ignored as they cannot be adequately handled by the plugin. You can start with that, and expand your usage when more browsers start to support it. Chrome already supports them starting from 49.

Logical Properties

If you have ever developed an international website that spans cultures with different writing directions, you know what is involved when maintaining several versions of the interface, such as left-to-right or right-to-left. To address this need, W3C introduced a new concept of logical properties. A way to abstract ourselves from thinking in terms of physical directions such as right or left, but rather in logical ones – start and end. The specification is still very much a work in progress, but you can already try some of this stuff out using the postcss-logical-props plugin.

It supports generating left-to-right and right-to-left versions of the website using certain logical properties, such as border-block-start and border-block-end, offset-block-start and offset-block-end. These properties are compiled into their left or right alternatives. You can instruct the plugin to compile both the LTR and RTL versions of the stylesheet and then switch them in the application when a user changes the language.

For example, if you have the following CSS:

.text {
  border-block-start: 1px solid blue;
  text-align: start;
  padding-block-end: 10px;
  margin-block-start: 20px;
}

Calling the plugin with options { dir: 'LTR' } would yield the following result:

.text {
  border-left: 1px solid blue;
  text-align: left;
  padding-right: 10px;
  margin-left: 20px;
}

While using { dir: 'RTL' } would give you a mirror image:

.text {
  border-right: 1px solid blue;
  text-align: right;
  padding-left: 10px;
  margin-right: 20px;
}

New Color Features

PostCSS provides a whole group of plugins that deliver new features for working with colors.

Color Adjustment

The postcss-color-function plugin implements the new color() function. This function allows you to modify a base color using one or multiple “color adjustor” functions. Each of the color adjustors can manipulate a color in a specific way.

Here are a few examples of how it can be used:

body {
  color: color(red green(50));
  color: color(red blue(50) a(50%));
  color: color(red tint(50%));
  color: color(red shade(50%));
}

Will be compiled into the following colors

body {
  color: rgb(255, 50, 0);
  color: rgba(255, 0, 50, 0.5);
  color: rgb(255, 128, 128);
  color: rgb(128, 0, 0);
}

A complete list of color adjusters can be found in the specification. This plugin can be extremely effective together with custom properties. You can define a set of base colors and calculate others based on them. This way if you’ll decide to change your base colors, the rest of the palette will be updated accordingly.

HWB Color Notation

HWB stands for Hue-Whiteness-Blackness, an alternative method for defining colors. It describes a color using a hue value from 0 to 360 and then adds a degree of whiteness and blackness from 0% to 100%. This notation is similar to HSL and somewhat easier to comprehend than RGB. The postcss-color-hwb plugin implements the new hwb() function which is used to define HWB colors. A couple of examples:

body {
  color: hwb(0, 0%, 0%);
  color: hwb(120, 40%, 20%);
  color: hwb(240, 0%, 100%, 0.5);
}

Will generate the following colors:

body {
  color: rgb(255, 0, 0);
  color: rgb(102, 204, 102);
  color: rgba(0, 0, 0, 0.5);
}

Gray() Function

The CSS colors module also introduced a handy gray() function. It can be used to generate gray colors without specifying any redundant information, such as all three channels in an RGB color. The postcss-color-gray plugin implements a polyfill for the function and is extremely straightforward to use:

body {
  color: gray(0);
  color: gray(25);
  color: gray(50%);
  color: gray(128, 20%);
}

This code above will generate different shades of gray:

body {
  color: rgb(0, 0, 0);
  color: rgb(25, 25, 25);
  color: rgb(127, 127, 127);
  color: rgba(128, 128, 128, 0.2);
}

Wrapping It All Up

This is by all means not a complete list of CSS plugins available, but rather a selection of some the more interesting ones. You can explore more of them at postcss.parts.

CSS is booming and PostCSS is booming with it. Yes, we are all eagerly waiting for native browser support for these new features, but PostCSS gives us a promising opportunity to adopt and evaluate these features early. The general advice here would be to try to take a step back from the familiar usage of preprocessors and take a fresh perspective on writing stylesheets. Try to come up with a list of available features that would make you more productive and use them in your workflow. You might soon realize that these are the exact features you were missing all along.

Frequently Asked Questions about Enabling Upcoming CSS Features with PostCSS

What is the purpose of PostCSS in CSS development?

PostCSS is a powerful tool in CSS development that allows developers to use future CSS features before they are officially implemented in browsers. It is a post-processor for CSS that uses JavaScript plugins to transform styles. These plugins can support variables and mixins, transpile future CSS syntax, inline images, and more. PostCSS essentially future-proofs your CSS, making it more efficient and maintainable.

How does PostCSS differ from other CSS processors like Sass or Less?

Unlike other pre-processors like Sass or Less, PostCSS is a post-processor. This means it allows you to write in pure CSS, then it processes your code to add the features you’ve used that are not yet supported in CSS. This can include things like variables, nesting, and mixins. It’s a more flexible and powerful tool, allowing for a wider range of transformations.

How can I start using PostCSS in my projects?

To start using PostCSS, you need to install it via npm (Node Package Manager). Once installed, you can use it in your build process with tools like Gulp or Webpack. You can also configure it to use the plugins you need for your project. There are many plugins available that can help you write more efficient and future-proof CSS.

What are some of the most popular PostCSS plugins?

There are many PostCSS plugins available, each serving different purposes. Some of the most popular ones include Autoprefixer, which automatically adds vendor prefixes to your CSS; cssnext, which allows you to use future CSS features today; and cssnano, which minifies your CSS for production.

How does the ‘margin-block-start’ property work in CSS?

The ‘margin-block-start’ property in CSS is a logical property that defines the margin at the start of an element’s block. It’s used in writing modes where the block flow direction is vertical. The value of ‘margin-block-start’ overrides any value set on the ‘margin-top’ property.

What is the ‘css-text-wrap-balance’ feature?

The ‘css-text-wrap-balance’ feature is a proposed CSS property that aims to improve the balance of text when it wraps across multiple lines. It’s not yet widely supported in browsers, but can be used with PostCSS to ensure it works in all browsers.

How can I use the ‘css-text-wrap-balance’ feature with PostCSS?

To use the ‘css-text-wrap-balance’ feature with PostCSS, you need to install and configure the appropriate plugin. Once configured, you can use the ‘css-text-wrap-balance’ property in your CSS, and PostCSS will ensure it works in all browsers.

What is the ‘caniuse’ website and how can it help me with CSS development?

The ‘caniuse’ website is a valuable resource for web developers. It provides up-to-date information on the browser support for various web technologies, including CSS features. By checking ‘caniuse’, you can see which CSS features are supported in which browsers, helping you make informed decisions about which features to use in your projects.

How can I ensure my CSS is compatible with all browsers?

Ensuring your CSS is compatible with all browsers can be a challenge due to the varying levels of support for different CSS features. Tools like PostCSS can help by allowing you to use future CSS features today, with plugins that ensure they work in all browsers. It’s also important to regularly check resources like ‘caniuse’ for updates on browser support.

What are some best practices for using PostCSS in my projects?

When using PostCSS in your projects, it’s important to carefully select and configure your plugins to suit your needs. It’s also recommended to use a build tool like Gulp or Webpack to automate your CSS processing. Regularly updating your plugins and checking ‘caniuse’ for browser support updates will also help ensure your CSS is efficient and compatible.

Pavels JelisejevsPavels Jelisejevs
View Author

Pavels is a software developer from Riga, Latvia, with a keen interest for everything web-related. His interests range from back-end to front-end development, as well as analysis and automation. If you have something to discuss, you can always reach him via Facebook or LinkedIn.

patrickcpost-processorPostCSS
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week