Ghost Themes
SimpleChat.Support - Open Source Live Chat App
0%
Tomorrow’s CSS syntax with cssnext
words - read.

Tomorrow’s CSS syntax with cssnext

As you probably know, nothing remains constant. All things need progress and improvement. The same is with CSS. For now, we have CSS in version 3 with all the cool stuff. But it also lacks many features which come with tools like preprocessors that are really necessary and useful. Although there isn't something like CSS4 right now, there are many new features in the works, which, with a little help, you can use nowadays. That’s just what you’ll learn in this article. You'll also learn how to use PostCSS and its plugins in a ready to use boilerplate.

Ok, but what new CSS features are we talking about? You have probably got used to things like variables in CSS. You probably use Sass or Less to achieve it, right? I bet you do! For now, this is impossible in plain old CSS3 in most major browsers, but in the future, you'll be able to do it. Another cool example is the new CSS selectors such as :matches, :not or :any-link. You'll also be able to nest your selectors and use many new CSS functions like color(), hwb() or grey(). How it is possible? We will use PostCSS and its cssnext plugin which will allow us to use these new features today.

If you don't know what PostCSS is, you should definitely go and read my other article: "Some things you may think about PostCSS... and you might be wrong" at the end of the article, you'll find many other links where you'll be able to learn more about PostCSS.

Let's take a look at what we'll cover here:

  • Some new CSS features in depth.
  • Cssnext installation guides and a ready to use boilerplate.
  • Additional PostCSS plugins to help you work.
  • Do I still need a preprocessor?

Some new CSS features in depth

For now, let's set aside the PostCSS and cssnext installation and descriptions. Here I want to take a closer look at some new CSS features that you probably use in your projects with tools like Sass or Less, but also some new features that are interesting and supported by the cssnext plugin.

1. CSS Variables

Let's start with variables. This is probably the most awaited feature in CSS land. You can find the whole specification here: https://www.w3.org/TR/css-variables/ What you need to know is how to use variables in plain CSS. This is a little bit different than in your favourite preprocessor, but I'm sure you can use to it very quickly. Let's see some code:

:root { 
  --mainColor: red; 
} 

a {  
  color: var(--mainColor); 
}
h1 {  
  color: var(--mainColor);
}

As you can see, we define our mainColor variable in the top level :root selector, then we can use it in many places in our codebase. This is really simple. You just need to use var() function.

2. CSS selectors nesting

Another cool feature is CSS nesting, a very useful tool. This also comes from tools like Sass or Less. You can nest your CSS selectors in plain CSS too. I think the code example will explain everything:

a {  
  & span { 
    color: #fff; 
  } 
  &.black {
    color: #000;
  }
}

As you can see, this is very similar to the nesting features from Sass. The same code in standard CSS will be:

a span {  
  color: #fff;
}
a.black {  
  color: #000;
}

You can read more about it here: http://tabatkins.github.io/specs/css-nesting/

3. Custom media queries and media queries ranges

I remember some plugins for preprocessors which are able to create simpler mixins for media queries. A good example could be Rupture for Stylus. It basically provides simple functions like +below(784px) etc., so you don't have to write long CSS media queries.

Here we can do a similar thing but all in plain CSS. Let's take a look at the code example:

@custom-media --small-viewport (max-width: 30em); 

@media (--small-viewport) { 
  /* styles for small viewport */ 
}

You can also create some easier-to-read media query ranges. It allows you to replace min-/max- with <= and >=.

@media (width >= 500px) and (width <= 1200px) { 
  /* your styles */ 
} 

/* or coupled with custom media queries */ 
@custom-media --only-medium-screen (width >= 500px) and (width <= 1200px); 

@media (--only-medium-screen) { 
  /* your styles */ 
}

4. Some new selectors

It appears that there is also a need for some new CSS selector and I think we can agree that these are necessary:

nav :any-link {  
  background-color: yellow; 
}
p:matches(:first-child, .special) {  
  color: red; 
} 
p:not(:first-child, .special) {  
  color: red; 
}

5. Some new functions

There are also some new functions:

a {  
  color: color(red alpha(-10%)); 
} 
a:hover {  
  color: color(red blackness(80%)); 
}
.foo {
  color: gray(85);
}
.bar {
  color: gray(10%, 50%);
}

You'll find a full list of all features on the cssnext website: http://cssnext.io/features/

Cssnext installation guides and a ready-to-use boilerplate.

Ok, all that new CSS stuff seems to be quite useful. Unfortunately, for now, there isn't good support of these features in the newest browsers. But don't worry - we have PostCSS and the cssnext plugin.
Cssnext is a tool which is written to be used as a PostCSS plugin. It supports all the aforementioned features and even more. It will read your CSS code written in new way and transpile it to the good, old CSS3. This is something similar to preprocessing. The main benefit here is that you use plain CSS, which will be someday supported by all browsers, so you can learn once just now and use it forever. You don't need to learn other tools' syntaxes. You don't even need to use preprocessors anymore. I could even say that cssnext is for CSS what Babel is for JavaScript.

So how do you start? There are many ways. It depends on what your workflow looks like. You will find a 'setup' section on the cssnext website: http://cssnext.io/setup/ . As you can see, we have many ways to use it with PostCSS. You can use Gulp, Grunt, Webpack, and even command line. Here I want to show you the Grunt boilerplate which I built a little while ago. It uses PostCSS, cssnext, and also some other cool stuff like Handlebars templates and all build processes like minification and concatenation. You can find it here: cssnext-grunt-boilerplate

Let's see how to use cssnext-grunt-boilerplate.

First of all, you need to have some knowledge about the Grunt build tool. You'll find many articles on the Internet about it but I assume that you know it a little bit. If you don't want to use Grunt, you’ll probably be able to move all that knowledge and adjust your favourite tool like Gulp or Webpack.

My boilerplate is configured to use PostCSS and cssnext, so you can run it and just work. Basically, it uses .hbs templates to build static .html files which could be then served by the BrowserSync server. So you get livereloads and also you can test on many devices. When you want to write your new files, just go to the app/templates folder and create new ones. We use grunt-assemble here. It is a tool which compiles the Handlebars templates. You can read more about it on its Readme file. If you want to write CSS in a cssnext way, you can go to app/postcss and create normal .css files with the new features described above in this article. You can also use CSS imports. You'll find some demo files in the repository.

Here are the steps when you want to work with cssnext-grunt-boilerplate.

$ git clone https://github.com/juliancwirko/cssnext-grunt-boilerplate.git
$ cd cssnext-grunt-boilerplate
$ npm install
$ npm start

When you run the app, all special .css from the app/postcss directory will be transpiled into normal CSS and put in the app/css folder. Also your all .hbs files in the app/templates folder will be compiled into .html files in main app folder. So by running npm start, you will run a BrowserSync server which will serve the files from the app folder.

The next step is to prepare all the files for production usage. All you need to do is to run npm run build. It will prepare all the files and copy them to the dist folder. From this folder, you can serve your production files. You can also run a server locally from the dist folder. To do this, run npm run server-dist from your command line.

Also check out the README.md file of the repository.

Ok, but where is the cssnext plugin configured?

This boilerplate uses grunt-postcss task. With this task, we can configure our PostCSS and all its plugins. It is done in the Gruntfile.js. You can find it in the code. Here is the PostCSS configuration in the Gruntfile.js:

(...) 
postcss: {  
  options: { 
    map: true, 
    processors: [ 
      require('postcss-import')(), 
      require('postcss-cssnext')({ 
        browsers: 'last 2 versions' 
      }), 
      require('postcss-reporter')() 
    ] 
  }, 
  dist: { 
    src: '<%= app %>/postcss/**/*.css', 
    dest: '<%= app %>/css/app.css' 
  } 
}, 
(...)

As you can see, we need to setup PostCSS and its processors (plugins). You can also pass some options to each plugin. We use the cssnext plugin but also others which we’ll talk about later. What is important here is that the postcss-cssnext plugin has Autoprefixer built in so you don't have to add it here. In fact, when you do include Autoprefixer, the postcss-cssnext plugin should inform you about the duplication.

You can of course go through the whole Gruntfile.js file to see what the boilerplate can do. The main point is that it is configured to create a workflow which will allow you to use cssnext, PostCSS with other plugins, and also Handlebars templates to create layouts, partials, and pages.

PostCSS additional plugins to help you work.

Here in the cssnext-grunt-boilerplate, we use not only the cssnext plugin but also postcss-import and postcss-reporter. The first is responsible for importing CSS files. This is also very similar to Sass or Less imports. The second one is responsible for logging all error messages to the console, which is really useful.

These additional plugins are just examples. You can use many other PostCSS plugins in this boilerplate. Just add them in the Gruntfile.js the same way you did for the other two. For example, as a complementary tool, you can use an awesome grid plugin called Lost, which gives you simple and very useful grid building options. So your PostCSS config could look like:

(...) 
postcss: {  
  options: { 
    map: true, 
    processors: [ 
      require('postcss-import')(), 
      require('postcss-cssnext')({ 
        browsers: 'last 2 versions' 
      }), 
      require('lost')(),
      require('postcss-reporter')() 
    ] 
  }, 
  dist: { 
    src: '<%= app %>/postcss/**/*.css', 
    dest: '<%= app %>/css/app.css' 
  } 
}, 
(...)

Of course remember to add it to the package.json file as a dependency and also run npm update.

You'll find an awesome PostCSS plugin base at: http://postcss.parts/ and also on the GitHub page.

Do I still need a preprocessor?

The answer is, it depends. In my opinion, you don't need a preprocessor, but I know that it isn't easy to give up all your old habits. Also, there are many ready-to-use tools written in Sass or Less. So if you want, you can drop preprocessors and use only the PostCSS stack with cssnext and other plugins. You can also use your favourite preprocessor next to PostCSS. In our cssnext-grunt-boilerplate, if we want Sass or Less or even Stylus, this wouldn't be very hard to integrate. We just need to add the proper Grunt task. This allows you to do a simple transition from preprocessors to PostCSS and cssnext.
There are also different parsers for PostCSS so you can use your old .scss files and compile them using some of PostCSS plugins. For example, take a look at my experiment where I use PostCSS to compile Bootstrap 4 .scss files in Meteor: meteor-bootstrap-postcss-test.

As you can see, PostCSS workflows are very flexible. You can use only PostCSS and chosen plugins, but you can also use it with preprocessors if you really want to or you have some old code base.

I encourage you to play with cssnext-grunt-boilerplate and with cssnext as well. Try different configurations with PostCSS plugins and let me know what you think in the comments. If you want to contact me, catch me on Twitter (@juliancwirko) or at julian.cwriko@gmail.com. Thanks!

Comments

comments powered by Disqus