Connect with us

Technology

The best way to Use PostCSS as a Configurable Various to Sass – SitePoint


Net builders love the Sass CSS preprocessor. In accordance with the Sass opinions within the State of CSS Survey, each developer is aware of what it’s, 89% use it commonly, and 88% have excessive satisfaction.

Many net bundlers embody Sass processing, however you might also be utilizing PostCSS with out realizing it. PostCSS is primarily recognized for its Autoprefixer plugin, which mechanically provides -webkit, -moz, and -ms vendor prefixes to CSS properties when required. Its plugin system means it may possibly achieve this way more … corresponding to compiling .scss recordsdata with out having to make use of the Sass compiler.

This tutorial explains the way to create a customized CSS preprocessor which compiles Sass syntax and dietary supplements it with additional options. It’s superb for anybody with particular CSS necessities who is aware of a little bit Node.js.

Fast Begin

An instance PostCSS mission could be cloned from GitHub. It requires Node.js, so run npm set up to fetch all dependencies.

Compile the demonstration src/scss/predominant.scss supply code to construct/css/predominant.css utilizing:

npm run css:dev

Auto-compile every time recordsdata are modified utilizing:

npm run css:watch

Then exit watching by urgent Ctrl | Cmd + C within the terminal.

Each choices additionally create a supply map at construct/css/predominant.css.map, which references the unique supply recordsdata within the developer instruments.

Manufacturing-level minified CSS with no supply map could be compiled utilizing:

npm run css:construct

Check with the README.md file for additional data.

Ought to You Substitute Sass with PostCSS?

There’s nothing unsuitable with the Sass compiler, however think about the next elements.

Module Dependencies

The newest Dart model of Sass could be put in globally utilizing the Node.js npm package deal supervisor:

npm set up -g sass

Compile Sass .scss code with:

sass [input.scss] [output.css]

Supply maps are mechanically generated (--no-source-map will change them off) or --watch could be added to auto-compile supply recordsdata after they change.

The newest model of Sass requires lower than 5MB of set up area.

PostCSS ought to require fewer assets and a primary Sass-like compiler with auto-prefixing, and minification wants lower than 1MB of area. In actuality, your node_modules folder will increase to greater than 60MB and enhance quickly as extra plugins are added. That is largely npm putting in different dependencies. Although PostCSS might not use them, it may possibly’t be thought-about as a light-weight various.

Nonetheless, in the event you’re already utilizing PostCSS for Autoprefixer or different functions, Sass might not be vital.

Processing Velocity

The gradual, Ruby-based Sass compiler has lengthy gone and the newest version makes use of a compiled Dart runtime. It’s quick.

PostCSS is pure JavaScript and, whereas benchmarks will differ, it may be thrice slower at compiling the identical supply code.

Nonetheless, this velocity distinction can be much less noticeable in the event you’re already operating PostCSS after Sass. A two-stage course of could be slower than utilizing PostCSS alone, since a lot of its work includes tokenizing CSS properties.

Customization

The Sass language contains a big set of options together with variables, nesting, partials, mixins, and extra. There are downsides:

  1. You can’t simply add new options.

    Maybe you’d like an possibility convert HSLA colours to RGB. It could be potential to write down a customized operate, however different necessities can be unattainable — corresponding to inlining an SVG as a background picture.

  2. You’ll be able to’t simply limit the function set.

    Maybe you’d choose your crew to not use nesting or @prolong. Linting guidelines will assist, however they gained’t cease Sass compiling legitimate .scss recordsdata.

PostCSS is significantly extra configurable.

By itself, PostCSS does nothing. Processing performance requires a number of of the many plugins accessible. Most carry out a single job, so in the event you don’t need nesting, don’t add a nesting plugin. If vital, you possibly can write your individual plugins in a regular JavaScript module that may harness the facility of Node.js.

Set up PostCSS

PostCSS can be utilized with webpack, Parcel, Gulp.js, and different construct instruments, however this tutorial exhibits the way to run it from the command line.

If vital, initialize a brand new Node.js mission with npm init. Arrange PostCSS by putting in the next modules for primary .scss parsing with plugins for partials, variables, mixins, nesting, and auto-prefixing:

npm set up --save-dev postcss postcss-cli postcss-scss postcss-advanced-variables postcss-nested autoprefixer

Just like the instance mission, PostCSS and its plugins are put in regionally. This can be a sensible possibility in case your tasks are prone to have differing compilation necessities.

Observe: PostCSS can solely be run from a JavaScript file, however the postcss-cli module offers a wrapper that may be referred to as from the command line. The postcss-scss module permits PostCSS to learn .scss recordsdata however doesn’t rework them.

Autoprefixer Configuration

Autoprefixer makes use of browserslist to find out which vendor prefixes are required in keeping with your record of supported browsers. It’s best to outline this record as a "browserslist" array in package deal.json. The next instance provides vendor prefixes the place any browser has at the least 2% market share:

"browserslist": [
  "> 2%"
],

Your First Construct

You’ll sometimes have a single root Sass .scss file which imports all required partial/part recordsdata. For instance:



@import '_variables';
@import '_reset';
@import 'parts/_card';

Compilation could be began by operating npx postcss, adopted by the enter file, an --output file, and any required choices. For instance:

npx postcss ./src/scss/predominant.scss 
    --output ./construct/css/predominant.css 
    --env growth 
    --map 
    --verbose 
    --parser postcss-scss 
    --use postcss-advanced-variables postcss-nested autoprefixer

This command:

  1. parses ./src/scss/predominant.scss
  2. outputs to ./construct/css/predominant.css
  3. units the NODE_ENV atmosphere variable to growth
  4. outputs an exterior supply map file
  5. units verbose output and error messages
  6. units the postcss-scss Sass parser, and
  7. makes use of the plugins postcss-advanced-variables, postcss-nested, and autoprefixer to deal with partials, variables, mixins, nesting, and auto-prefixing

Optionally, you could possibly add --watch to auto-compile when .scss recordsdata are modified.

Create a PostCSS Configuration File

The command line rapidly turns into unwieldy for longer lists of plugins. You’ll be able to outline it as an npm script, however a PostCSS configuration file is a better possibility that provides further prospects.

PostCSS configuration recordsdata are JavaScript module recordsdata named postcss.config.js and sometimes saved within the mission’s root listing (or whichever listing you run PostCSS from). The module should export a single operate:


module.exports = cfg => {

  

};

It’s handed a cfg object with properties set by the postcss command. For instance:

{
  cwd: '/dwelling/identify/postcss-demo',
  env: 'growth',
  choices: {
    map: undefined,
    parser: undefined,
    syntax: undefined,
    stringifier: undefined
  },
  file: {
    dirname: '/dwelling/identify/postcss-demo/src/scss',
    basename: 'predominant.scss',
    extname: '.scss'
  }
}

You’ll be able to look at these properties and react accordingly — for instance, decide whether or not you’re operating in growth mode and processing a .scss enter file:


module.exports = cfg => {

  const
    dev = cfg.env === 'growth',
    scss = cfg.file.extname === '.scss';

  

};

The operate should return an object with property names matching the postcss-cli command line choices. The next configuration file replicates the lengthy fast begin command used above:


module.exports = cfg => {

  const
    dev = cfg.env === 'growth',
    scss = cfg.file.extname === '.scss';

  return {

    map: dev ? { inline: false } : false,
    parser:  scss ? 'postcss-scss' : false,
    plugins: [
      require('postcss-advanced-variables')(),
      require('postcss-nested')(),
      require('autoprefixer')()
    ]

  };

};

PostCSS can now be run utilizing a shorter command:

npx postcss ./src/scss/predominant.scss 
    --output ./construct/css/predominant.css 
    --env growth 
    --verbose

Listed here are some issues to notice:

  • --verbose is non-obligatory: it’s not set in postcss.config.js.
  • Sass syntax parsing is barely utilized when the enter is a .scss file. In any other case, it defaults to plain CSS.
  • A supply map is barely output when --env is about to growth.
  • --watch can nonetheless be added for auto-compilation.

In the event you’d choose postcss.config.js to be in one other listing, it may be referenced with the --config possibility — corresponding to --config /mycfg/. Within the instance mission, the configuration above is positioned in config/postcss.config.js. It’s referenced by operating npm run css:primary, which calls:

npx postcss src/scss/predominant.scss 
    --output construct/css/predominant.css 
    --env growth 
    --verbose 
    --config ./config/

Including Additional Plugins

The next sections present examples of PostCSS plugins which both parse further .scss syntax or present processing past the scope of the Sass compiler.

Use Design Tokens

Design Tokens are a technology-agnostic method to retailer variables corresponding to corporation-wide fonts, colours, spacing, and many others. You would retailer token identify–worth pairs in a JSON file:

{

  "font-size": "16px",

  "font-main": "Roboto, Oxygen-Sans, Ubuntu, sans-serif",
  "lineheight": 1.5,

  "font-code": "Menlo, Consolas, Monaco, monospace",
  "lineheight-code": 1.2,

  "color-back": "#f5f5f5",
  "color-fore": "#444"

}

Then reference them in any net, Home windows, macOS, iOS, Linux, Android, or different utility.

Design tokens should not straight supported by Sass, however a JavaScript object with a variables property holding identify–worth pairs could be handed to the prevailing postcss-advanced-variables PostCSS plugin:


module.exports = cfg => {

  
  const variables = require('./tokens.json'); 

  const
    dev = cfg.env === 'growth',
    scss = cfg.file.extname === '.scss';

  return {

    map: dev ? { inline: false } : false,
    parser:  scss ? 'postcss-scss' : false,
    plugins: [
      require('postcss-advanced-variables')({ variables }), 
      require('postcss-nested')(),
      require('autoprefixer')()
    ]

  };

};

The plugin converts all values to international Sass $variables which can be utilized in any partial. A fallback worth could be set to make sure a variable is obtainable even when it’s lacking from tokens.json. For instance:



$color-back: #fff !default;

Token variables can then be referenced in any .scss file. For instance:

physique {
  font-family: $font-main;
  font-size: $font-size;
  line-height: $lineheight;
  shade: $color-fore;
  background-color: $color-back;
}

Within the instance mission, a token.json file is outlined, which is loaded and used when operating npm run css:dev.

Add Sass Map Help

Sass Maps are key–worth objects. The map-get operate can search for values by identify.

The next instance defines media question breakpoints as a Sass map with a reply mixin to fetch a named worth:


$breakpoint: (
  'small':  36rem,
  'medium': 50rem,
  'massive':  64rem
);


@mixin reply($bp) {
  @media (min-width: map-get($breakpoint, $bp)) {
    @content material;
  }
}

Default properties and media question modifications can then be outlined in the identical selector. For instance:

predominant {
  width: 100%;

  @embody reply('medium') {
    width: 40em;
  }
}

Which compiles to CSS:

predominant {
  width: 100%;
}

@media (min-width: 50rem) {

  predominant {
    width: 40em
  }

}

The postcss-map-get plugin provides Sass map processing. Set up it with:

npm set up --save-dev postcss-map-get

And replace the postcss.config.js configuration file:


module.exports = cfg => {

  
  const variables = require('./tokens.json');

  const
    dev = cfg.env === 'growth',
    scss = cfg.file.extname === '.scss';

  return {

    map: dev ? { inline: false } : false,
    parser:  scss ? 'postcss-scss' : false,
    plugins: [
      require('postcss-advanced-variables')({ variables }),
      require('postcss-map-get')(), 
      require('postcss-nested')(),
      require('autoprefixer')()
    ]

  };

};

Add Media Question Optimization

Since we’ve added media queries, it could be helpful to mix and kind them into mobile-first order. For instance, the next CSS:

@media (min-width: 50rem) {

  predominant {
    width: 40em;
  }

}

@media (min-width: 50rem) {

  #menu {
    width: 30em;
  }

}

could be merged to develop into:

@media (min-width: 50rem) {

  predominant {
    width: 40em;
  }

  #menu {
    width: 30em;
  }

}

This isn’t potential in Sass, however could be achieved with the PostCSS postcss-sort-media-queries plugin. Set up it with:

npm set up --save-dev postcss-sort-media-queries

Then add it to postcss.config.js:


module.exports = cfg => {

  
  const variables = require('./tokens.json');

  const
    dev = cfg.env === 'growth',
    scss = cfg.file.extname === '.scss';

  return {

    map: dev ? { inline: false } : false,
    parser:  scss ? 'postcss-scss' : false,
    plugins: [
      require('postcss-advanced-variables')({ variables }),
      require('postcss-map-get')(),
      require('postcss-nested')(),
      require('postcss-sort-media-queries')(), 
      require('autoprefixer')()
    ]

  };

};

Add Asset Processing

Asset administration isn’t accessible in Sass, however postcss-assets makes it simple. The plugin resolves CSS picture URLs, provides cache-busting, defines picture dimensions, and inlines recordsdata utilizing base64 notation. For instance:

#mybackground {
  background-image: resolve('again.png');
  width: width('again.png');
  top: top('again.png');
  background-size: dimension('again.png');
}

compiles to:

#mybackground {
  background-image: url('/photographs/again.png');
  width: 600px;
  top: 400px;
  background-size: 600px 400px;
}

Set up the plugin with:

npm set up --save-dev postcss-assets

Then add it to postcss.config.js. On this case, the plugin is instructed to find photographs within the src/photographs/ listing:


module.exports = cfg => {

  
  const variables = require('./tokens.json');

  const
    dev = cfg.env === 'growth',
    scss = cfg.file.extname === '.scss';

  return {

    map: dev ? { inline: false } : false,
    parser:  scss ? 'postcss-scss' : false,
    plugins: [
      require('postcss-advanced-variables')({ variables }),
      require('postcss-map-get')(),
      require('postcss-nested')(),
      require('postcss-sort-media-queries')(),
      require('postcss-assets')({   
        loadPaths: ['src/images/']
      }),
      require('autoprefixer')()
    ]

  };

};

Add Minification

cssnano units the usual for CSS minification. Minification can take extra processing time than different plugins, so it may be utilized in manufacturing solely.

Set up cssnano with:

npm set up --save-dev cssnano

Then add it to postcss.config.js. On this case, minification solely happens when NODE_ENV is about to something apart from growth:


module.exports = cfg => {

  
  const variables = require('./tokens.json');

  const
    dev = cfg.env === 'growth',
    scss = cfg.file.extname === '.scss';

  return {

    map: dev ? { inline: false } : false,
    parser:  scss ? 'postcss-scss' : false,
    plugins: [
      require('postcss-advanced-variables')({ variables }),
      require('postcss-map-get')(),
      require('postcss-nested')(),
      require('postcss-sort-media-queries')(),
      require('postcss-assets')({
        loadPaths: ['src/images/']
      }),
      require('autoprefixer')(),
      dev ? null : require('cssnano')() 
    ]

  };

};

Setting --env to prodution triggers minification (and removes the supply map):

npx postcss ./src/scss/predominant.scss 
    --output ./construct/css/predominant.css 
    --env prodution 
    --verbose

Within the instance mission, manufacturing CSS could be compiled by operating npm run css:construct.

Progress to PostCSS?

PostCSS is a robust and configurable instrument that may compile .scss recordsdata and improve (or limit) the usual Sass language. In the event you’re already utilizing PostCSS for Autoprefixer, you could possibly take away the Sass compiler solely whereas retaining the syntax you’re keen on.

Additional hyperlinks:

Click to comment

Leave a Reply

Your email address will not be published. Required fields are marked *