Crédit photo

Introduction to cssnext

From the official website:

cssnext is a CSS transpiler that allows you to use tomorrow's CSS syntax today. It transforms CSS specs that are not yet implemented in popular browsers into more compatible CSS.

#What does it mean?

Since CSS3, you may have heard that CSS is divided into several independent documents called "modules". Those modules can have different levels of stability and statuses. It can take quite some time for the browsers to implement those modules and even more for the W3C to give them the ultimate status of Recommandation.

With cssnext, you can use the syntax of CSS Module Level 4 such as custom properties or custom media queries. cssnext will transform this new strange syntax into something that the browser can actually understand.

In short, it makes you taste the future.

I don't know about you but speaking as someone who loves to experiment with cutting-edge technologies, I think this is pretty cool!

You should take a look at the feature list.

#What about my current CSS preprocessor?

Forget about the dangers of mixins, @extend and infinite nesting; mostly caused by overzealous use and/or misuse of such tools, but still.

Guess what, you don't really need this.

You should give cssnext a shot and go back to Vanilla CSS. And with a nice and clean touch of BEM syntax, you will feel alive again.


Let's take a look at the features that cssnext offers at the moment.

First of all, be sure to check out the playground on the official website.

#Automatic vendor prefixes

.h1 {
  transform: skewX(25deg);
  transition: transform 1s;

This will be transformed by cssnext via Autoprefixer in:

.h1 {
  -webkit-transform: skewX(25deg);
      -ms-transform: skewX(25deg);
          transform: skewX(25deg);
  -webkit-transition: -webkit-transform 1s;
          transition: transform 1s;

#Custom properties & var() limited to :root

Also known as the much awaited CSS variables.

:root {
  --primary-Color:                 #E86100;
  --secondary-Color:               #2c3e50;
  --r-Grid-baseFontSize:           1rem;

You can use them this way:

.h1 {
  color: var(--primary-Color);
.h1:hover {
  color: var(--secondary-Color);
body {
  font-size: var(--r-Grid-baseFontSize);

#Custom Media Queries

Simply-named and semantic aliases (check the specs).

@custom-media --viewport-medium (width <= 40rem);
@custom-media --viewport-large (max-width: 50em);


@media (--viewport-medium) {
  body { font-size: calc(var(--fontSize) * 1.2); }
@media (--viewport-large) {
  body { font-size: calc(var(--fontSize) * 1.4); }

For example, let's take:

:root {
  --fontSize: 1.2rem;

The output will be:

@media (max-width: 40rem) {
  body { font-size: 1.44rem; }
@media (max-width: 50em) {
  body { font-size: 1.68rem; }

#Custom selectors

Take a look at the specs first. Let's say we want to apply some styles to all headings.

@custom-selector :--heading h1, h2, h3, h4, h5, h6;

:--heading {
  margin-top: 0;

This will output the following:

h6 { margin-top; 0; }


A simple color function to apply color adjusters (hue, lightness, tint, and so on) to a base color.


.class {
  background-color: color(#2B88E6);
  color: color(#2B88E6 red(+30) green(-50) blue(6%) alpha(.65));
  border-top-color: color(#2B88E6 saturation(-8%) whiteness(+50%));
  border-right-color: color(#2B88E6 lightness(5%) blackness(-25%));
  border-bottom-color: color(#2B88E6 tint(80%));
  border-left-color: color(#2B88E6 shade(75%));

The code above will be transformed into...

.class {
  background-color: rgb(43, 136, 230);
  color: rgba(73, 86, 15, 0.65);
  border-top-color: rgb(181, 201, 222);
  border-right-color: rgb(3, 45, 87);
  border-bottom-color: rgb(213, 231, 250);
  border-left-color: rgb(11, 34, 58);

cssnext also offers the following color-related features.


From the specifications, HWB (Hue-Whiteness-Blackness) is similar to HSL but easier for humans to work with.

.title {
  color: hwb(125, 32%, 47%);


.title {
  color: rgb(33, 135, 42);


Grays are so cool they have a function of their own.

.section {
  background-color: gray(120, 50%);
  border-color: gray(17%, 25%);

This will output:

.section {
  background-color: rgba(120, 120, 120, 0.5);
  border-color: rgba(43, 43, 43, 0.25);


cssnext transforms the hexadecimal notations #RRGGBBAA and #RGBA into rgba().

body {
  color: #5c69;
  background-color: #C73D5C59;


body {
  color: rgba(85, 204, 102, 0.6);
  background-color: rgba(199, 61, 92, 0.34902);


Simply transforms the color rebeccapurple into rgb(102, 51, 153).

#filter properties

A whole new world of image modifications!

.awesome-Image {
  filter: sepia(.7) hue-rotate(23deg);

.awesome-Picture {
  filter: blur(8px);

Will be transformed into:

.awesome-Image {
  filter: url('data:image/svg+xml;charset=utf-8,<svg xmlns=""><filter id="filter"><feColorMatrix type="matrix" color-interpolation-filters="sRGB" values="0.5751000000000001 0.5383 0.1323 0 0 0.24429999999999996 0.7802000000000001 0.11760000000000001 0 0 0.1904 0.3738 0.39170000000000005 0 0 0 0 0 1 0" /><feColorMatrix type="hueRotate" color-interpolation-filters="sRGB" values="23" /></filter></svg>#filter');
  -webkit-filter: sepia(.7) hue-rotate(23deg);
          filter: sepia(.7) hue-rotate(23deg);

.awesome-Picture {
  filter: url('data:image/svg+xml;charset=utf-8,<svg xmlns=""><filter id="filter"><feGaussianBlur stdDeviation="8" /></filter></svg>#filter');
  -webkit-filter: blur(8px);
          filter: blur(8px);

#rem units

Nothing extraordinary here, it generates pixel fallback for rem units. Oh, come on! Do we really need an example for this one? Alright, here you go!

.section-Highlight {
  font-size: 2.5rem;


.section-Highlight {
  font-size: 40px;
  font-size: 2.5rem;

#Bonus features

The two following features are not really related to CSS specifications. However, they are definitely worth mentioning in this introduction.


What if you could import inline local files and modules (node_modules or web_modules) to output a bundled CSS file? Yes, I'm looking at you Sass users, ahem. Well, with cssnext, you can.


As you may have guessed, this is just an option to compress or not your output file. By the way, this option uses cssnano.


Below is a basic example of these two features. I used gulp-cssnext, one of the many plugins to help you start with cssnext.

var gulp = require('gulp'),
    cssnext = require("gulp-cssnext");

gulp.task('styles', function() {
    compress: true,  // default is false

Then, in my index.css file, I will have:

@import "normalize.css"; /* == @import "./node_modules/normalize.css/index.css"; */
@import "cssrecipes-defaults"; /* == @import "./node_modules/cssrecipes-defaults/index.css"; */
@import "project-modules/partner"; /* relative to css/ */
@import "typo"; /* same level as my main index.css located in css/ */
@import "highlight" (min-width: 25em);

And the final output will be:

/* content of ./node_modules/normalize.css/index.css */
/* content of ./node_modules/cssrecipes-defaults/index.css */
/* content of project-modules/partner.css */
/* content of typo.css */
@media (min-width: 25em) {
  /* content of highlight.css */

I know the feeling. Now you're in love too. :)

Well, just to wrap it up here, let's say that the main purpose of cssnext is to build things according to the W3C specifications keeping in mind that, theoretically, it can be removed later on (when not needed anymore).

Meanwhile, there is still work to do: here you can find a list of features that are waiting to be implemented.

Now it's your time to play. Be sure to check the GitHub repository, follow @cssnext on Twitter to get the latest news and join the cssnext room on Gitter if you have any questions.

Written by Macxim

Official spelling and grammar checker for Putain de code ! Incidentally, also a Front-End Web Developer.

2 contributors on this page