Search code examples
gruntjspostcss

How to use autoprefixer with postcss and Grunt on more than one file?


The title says it all. My postcss task is as follows:

    postcss: {

      options: {

          processors: [
              require('autoprefixer')({browsers: ['last 2 versions']}),
              require('cssnext')(),
              require('precss')()
            ]
      },
      dist: {
          src: '*.css',
          dest: 'style.css',
      }

    },

Currently I have another css file called style-human, which I want to prefix also. However, the task only prefixes the style.css file (the minified version).


Solution

  • The Problem

    The problem lies in your src: and dest: config. With src: '*.css' you are asking the postcss task to process all the .css files it finds, then with dest: style.css you ask for all the processed .css files to be output to one file called style.css. grunt-postcss only writes the last file it processed to style.css.

    Solutions

    There are several solutions to your problem.

    #1

    First if you don't specify a dest option grunt-postcss will process and update all the src files in place, overwriting the originals:

    postcss: {
      options: {
        processors: [
          require('autoprefixer')({browsers: ['last 2 versions']}),
          require('cssnext')(),
          require('precss')()
        ]
      },
      dist: {
        src: '*.css'
      }
    }
    

    not so good if you want to keep your src files.

    #2

    You could use the files option with expand.

    postcss: {
      options: {
        processors: [
          require('autoprefixer')({browsers: ['last 2 versions']}),
          require('cssnext')(),
          require('precss')()
        ]
      },
      dist: {
        files: [
          {
            src: '*.css',
            dest: 'build/',
            expand: true
          }
        ]
      }
    }
    

    This will process all your .css files, and output them to the build/ folder.

    #3

    Use grunt-contrib-copy to copy your css files to your output folder, like /build, then process them in place with grunt-postcss. A full example:

    module.exports = function(grunt) {
      grunt.loadNpmTasks('grunt-contrib-copy');
      grunt.loadNpmTasks('grunt-postcss');
      grunt.registerTask('css', ['copy:postcss', 'postcss']);
    
      grunt.initConfig({
        copy: {
          postcss: {
            files: [
              {
                src: 'css/*.css',
                dest: './build/',
                expand: true,
                flatten: true
              }
            ]
          }
        },
        postcss: {
          options: {
            map: true, // inline sourcemaps
    
            processors: [
              require('autoprefixer')({browsers: ['last 2 versions']}),
              require('postcss-cssnext')(),
              require('precss')()
            ]
          },
          dist: {
            files: [
              {
                src: 'build/*.css'
              }
            ]
          }
        }
      });
    };
    

    For an explanation of the expand and flatten options see the grunt docs on files.

    Here we use the copy task to copy the src css files to the build folder, then we use the postcss task to process them in place. I've created an alias task with grunt.registerTask('css', ['copy:postcss', 'postcss']); that you can call to run both steps with grunt css.

    #4

    If you want to concatenate your files into one css file (my preferred way of using postcss), then create a main.css file and either use precss's @import or postcss-import to pull all your other css files into main.css. Like so:

    postcss: {
      options: {
        processors: [
          require('autoprefixer')({browsers: ['last 2 versions']}),
          require('cssnext')(),
          require('precss')()
        ]
      },
      dist: {
        src: 'main.css',
        dest: 'build/main.css'
      }
    }
    

    main.css:

    @import "style.css";
    @import "style-human.css";
    

    Here postcss takes care of locating, processing and concatenating your css files, and the grunt task only has to worry about main.css.

    FYI

    You should use the postcss-cssnext package instead of cssnext as the cssnext package hasn't been updated in months.

    Also using postcss-cssnext and autoprefixer together is redundant because postcss-cssnext includes autoprefixer already.