Preprocessors

and

Postprocessors

Yevhen Isakov

Agenda

  • Magic and preprocessors
  • Preprocessor in wild nature
  • Native CSS
  • PostCss Rex
  • FAQ

Hard to maintain

bad css

Main goal: make our life simple

wild preproc

CSS preprocessor?

CSS preprocessor, meaning that it extends the CSS language, adding features that allow variables, mixins, functions and many other techniques that allow you to make CSS that is more maintainable, themable and extendable.

Dark magic behind preprocessors

preprocessors diagram

The truth is out there

preprocessors diagram

3 top CSS-Preprocessors

SASS

2007

LESS

2009

Alexis Sellier

@cloudhead

lesscss.org

less on Github

Last version: 4.1.1

Stylus

2010

TJ Holowaychuk

@tjholowaychuk

stylus-lang.com

Stylus on Github

Last version: 0.55.0 (28 Apr, 2016)

Pie of power (2016 a.d.)

preprocessors survay

Which to choose?

You know...

they are...

all good!

What the difference?

80/20

80% possibility SASS, LESS и Stylus equal,

20% difference.

Usage

How to install?

#1 Console!

  • Sass
    
                        npm install -g sass
    sass source/stylesheets/index.scss build/stylesheets/index.css
                    
  • Less
    
                          npm install -g less
    lessc styles.less styles.css 
                      
  • Stylus
    
                          npm install -g stylus
    stylus -w style.styl -o style.css 
                      

#2 Builders and task runners

Gulp, Webpack ...

#3 Online

  • CodePen
  • JSFiddle
  • Plunker
  • ...

Syntax

  • Less /  SCSS

    
            body {
          background-color: #efefef;
          font-size: 100% Helvetica, sans-serif;
            }
                      
  • SASS

    
            body
          background-color: #efefef
          font-size: 100% Helvetica, sans-serif
                      
  • Stylus

    
            body
          background-color #efefef
          font-size 100% Helvetica, sans-serif
                      

Stylus maintains both types

Similar:

  • Variables
  • Nesting
  • Imports
  • Calculations
  • Mixins
  • Colors
  • Loop...

Variables

Sass



$warning: #555;
$font-large: 24px;

div {
  color: $warning;
  font-size: $font-large;
}
      

LESS


@warning: #555; 
@font-large: 24px;

div {
  color: @warning;
  font-size: @font-large;
}
          

Stylus


warning = #555
font-large = 24px

div 
  color warning
  font-size font-large

          

Nesting

Sass


.block {
  display: block;

  &__element {
    padding: 10px 5px;

    &_modifier{
      color: pink;
    }
  }
  &_inline {
    display: inline-block;
  }
}
          

LESS


.block {
  display: block;

  &__element {
    padding: 10px 5px;

    &_modifier {
      color: pink;
    }
  }
  &_inline {
    display: inline-block;
  }
}
            

Stylus


.block 
  display block

  &__element 
    padding 10px 5px

    &_modifier
      color pink
    
  &_inline 
    display inline-block
  
            

@import

Sass


@import "reset.css";
@import "asset/variables.sass";
@import "component/nav/navbar.sass";
          

LESS


@import "reset.css"
@import "asset/variables.less"
@import "component/nav/navbar.less"
          

Stylus


@import "reset.css"
@import "asset/variables.styl"
@import "component/nav/navbar.styl"
          

Calculations

Sass, LESS, Stylus

One for all


            1cm * 1em => 1cm *em
            2in * 3in => 6in *in
            (1cm / 1em) * 4em => 4cm
            2in + 3cm + 2pc => 3.514in
            3in / 2in => 1.5
            ...
            p {
              margin: calc(1rem - 2px) calc(1rem - 1px);
            }
          

Mixins

Sass


@mixin bordered($width) {
  border: $width solid #ddd;

  &:hover {
      border-color: #999;
  }
}

div {
  @include bordered(5px);
}
          

LESS


.bordered(@width) {
  border: @width solid #ddd;

  &:hover {
      border-color: #999;
  }
}

div {
  .bordered(5px);
}
          

Stylus


bordered(width)
  border: width solid #ddd

  &:hover 
      border-color: #999

div 
  bordered(5px)

          

Extend

Sass


.block {
  margin: 10px 5px;
}

p {
  @extend .block;
  border: 1px solid #eee;
}

ul, ol {
  @extend .block;
  color: #333;
  text-transform: uppercase;
}
          

LESS


.block {
  margin: 10px 5px;
}

p {
  &:extend(.block);
  border: 1px solid #eee;
}

ul, ol {
  &:extend(.block);
  color: #333;
  text-transform: uppercase;
}
          

Stylus


.block 
  margin 10px 5px

p 
  @extend .block
  border 1px solid #eee

ul, ol 
  @extend .block
  color #333
  text-transform uppercase
          

Extend


.awesome {
  width: 100%;
  height: 100%;
}
body {
  @extend .awesome;
}
p {
  @extend .awesome;
}
          

.awesome, body, p {
  width: 100%;
  height: 100%;
}
          

Mixin


@mixin awesome($w: 100%) {
  width: $w;
}
body {
  @include awesome(960px);
}
p {
  @include awesome;
}
          

body {
  width: 960px;
}
p {
  width: 100%;
}

Loops

Sass


@for $i from 1px to 3px {
  .border-#{i} {
      border: $i solid blue;
  }
}
          

LESS


.loop(@counter) when (@counter > 0) {
  .loop((@counter - 1));

  .border-@{counter} {
      border: 1px * @counter solid blue;
  }
}
          

Stylus


for num in (1..3)
  .border-{num}
      border 1px * num solid blue
          

Functions

Scss


$grid-columns: 12;
$grid-width: 960px;

@function calculate-column-width($cols) {
  @return $grid-width / $grid-columns * $cols / $grid-width * 100%
}
#container {
  margin: 0 auto;
  width: 100%;
}
article {
  float: left;
  width: calculate-column-width(8);
}
aside {
  float: right;
  width: calculate-column-width(4);
}
          

LESS


@grid-columns: 12;
@grid-width: 960px;
.calculate-column-width(@cols) {
  width: (((@grid-width / @grid-columns) * @cols / @grid-width) * 100%);
}
#container {
  margin: 0 auto;
  width: 100%;
}
article {
  float: left;
  .calculate-column-width(8);
}
aside {
  float: right;
  .calculate-column-width(4);
}
          

Stylus


grid-columns 12
grid-width 960px

calculate-column-width(cols)
  ((grid-width / grid-columns) * cols / grid-width) * 100%)
#container
  margin 0 auto
  width 100%
article
  float left
  width calculate-column-width(8)
aside
  float right
  width calculate-column-width(4)
          

Colors

Sass


saturate($color, $amount)
desaturate($color, $amount)
lighten($color, $amount)
darken($color, $amount)
adjust-hue($color, $amount)
opacity($color, $amount)
transperentize($color, $amount)
mix($color1, $color2[, $amount])
grayscale($color)
complement($color)
          

LESS


saturate(@color, @amount)
desaturate(@color, @amount)
lighten(@color, @amount)
darken(@color, @amount)
adjust-hue(@color, @amount)
opacity(@color, @amount)
transperentize(@color, @amount)
mix(@color1, @color2, @weight)
grayscale(@color)
complement(@color)
          

Stylus


red(color)
green(color)
blue(color)
alpha(color)
dark(color)
light(color)
hue(color)
saturation(color)
lightness(color)
          

Native CSS can do that!

or will can... some day...

Variables

CSS Custom Properties for Cascading Variables Module Level 1

              :root {
        --warning: #555;
        --font-large: 24px;
      }
  
  div {
        color: var(--warning);
        font-size: var(--font-large);
      }
          

@import

CSS Cascading and Inheritance Level 3

@import "mystyle.css";
@import url("mystyle.css");
          

Colors

CSS Color Module Level 4

nav {
  background: color-mod(#79d3e2 hue(360) saturation(100%));
}
          

Calculations in CSS

CSS Values and Units Module Level 3

            1cm * 1em => 1cm *em
            2in * 3in => 6in *in
            (1cm / 1em) * 4em => 4cm
            2in + 3cm + 2pc => 3.514in
            3in / 2in => 1.5
            ...
            p {
              margin: calc(1rem - 2px) calc(1rem - 1px);
            }
          

Mixins

CSS @apply Rule (propose to draft)

A Collection of Interesting Ideas, 18 September 2016


            :root {
  --toolbar-theme: {
    background-color: hsl(120, 70%, 95%);
    border-radius: 4px;
    border: 1px solid var(--theme-color late);
  };
  --toolbar-title-theme: {
      color: green;
  };
}
.toolbar { 
  @apply --toolbar-theme;
}
.toolbar > .title {
  @apply --toolbar-title-theme;
}

          

Nesting

CSS Nesting Module

Editor’s Draft, 9 March 2019


        .block {
          display: block;
        
        @nest element {
          padding: 10px 5px;
        
          & modifier {
            color: pink;
          }
        }
          & inline {
            display: inline-block;
          }
        }
          

Extend

CSS Extend Rule (propose to draft)

A Collection of Interesting Ideas, 15 January 2015


.block, p, ul, ol {
  margin: 10px 5px;
}

p {
  border: 1px solid #eee;
}

ul, ol {
  color: #333;
  text-transform: uppercase;
}
          

Cons of preprocessors

Your code can not be run in the browser without processing


.accordion {
  $accordion-header-color: $primary-color;
  $accordion-padding: 1em;

  @extend %module;
  @include transition(all 0.3s ease-out);
  background: $accordion-header-color;
  padding: $accordion-padding;
}
          

Sometimes they make all complicated...


              .filters-block {
      $_filter-height: 20px;
        
          @mixin _note-size($value) {
          height: $value;
          line-height: $value;
          margin-top: -($value);
      }
      &__list {
          height: $_filters-height * 7;
          overflow: auto;
      }
      &__item {
          height: $_filter-height;
      }
      &__note {
          @include _note-size(30px);
      }
      @media screen and (max-width 1000px) {
          &__note {
              @include _note-size(40px);
          }
      }
  }
          

Preprocessors are not flexible!

PostCSS

PostCSS

2013

Andrey Sitnik

@andrey_sitnik

postcss.org

postcss on GitHub

Last version: 7.0.17 released (5 June, 2019)

How PostCSS work?

postcss diagram

What can I do with PostCSS?

  1. Polyfills
  2. Older browsers Support
  3. Extensions
  4. Optimization
  5. Syntax sugar
  6. Analytics
  7. ...

more than 90 plugins

  • Autoprefixer (adds vendor prefixes to CSS rules where it’s necessary)
  • StyleLint (proofreads and validates your CSS code)
  • CSSgrace (provides old browser support)
  • CSSnext (allows you to use future CSS syntax on current sites)
  • CSSNano (optimized and minified CSS files for a production site)

You can create plugins by yourself!


  module.exports = postcss.plugin('postcss-carl', function (opts) {
    return function (css, result) {
      css.walkRules(function(rule) {
        rule.selector = rule.selector + ', CARL';
      });
    };
  });
          

Usage

Gulp


              var postcss = require('postcss');
              
    postcss([
      require('autoprefixer'),
      require('stylelint')({
      syntax: 'scss'
      })
    ])
    .process(css)
    .then(result => console.log(result.css))
          

Webpack


              module.exports = {
          module: {
            loaders: [{
                test: /\.css$/,
                use: ExtractTextPlugin.extract({
                  use: [{
                      loader: 'css-loader',
                      options: { importLoaders: 1 },
                    },
                    'postcss-loader'
                  ]}),
              }]},
          plugins: {
            'postcss-import': {},
            'postcss-cssnext': {
              browsers: ['last 2 versions', '> 5%'],
            }},
        };
          

StyleLint for webpack

  • install -> npm install --save stylelint-webpack-plugin
  • configuration -> .stylelintrc
  • webpack.config.js ->

                var StyleLintPlugin = require('stylelint-webpack-plugin');

module.exports = {
  // ...
  plugins: [
    new StyleLintPlugin({
      /* Options */
      configFile: '.stylelintrc'
    }),
  ],
  // ...
}
              

Not enough?..

Combo!

Nowdays...

Ashley Nolan survay

It's all folks!

Links:

Thank You