Search code examples
csssassgulpgulp-sassgulp-task

Merge multiple files css into a one file by classes with gulp


Combine CSS files

Hi all, I'm working with a project in react and I use sass to process styles, I have several scss files and I group them using gulp, I use gulp-sass to generate the css and gulp-merge-css to join them, but they concatenate, not it combines.

Here's an example

In a file

.fooClass {
  background-color: black;
}

In another file

.fooClass {
  color: white;
}

These files should go to

.fooClass {
  background-color: black;
  color: white;
}

But it does not happen, only the content is combined but not combined, the result is

.fooClass {
  background-color: black;
 }
.fooClass {
  color: white;
 }

Is there any way to do what I want?

My gulp-task is:

const gulp = require('gulp');
const browserSync = require('browser-sync');
const sass = require('gulp-sass');
const postcss = require('gulp-postcss');
const autoprefixer = require('autoprefixer');
const mergeCSS = require('gulp-merge-css')
const cleanCSS = require('gulp-clean-css');

const conf = require('../conf/gulp.conf');

gulp.task('styles', styles);

function styles() {
  return gulp.src(conf.path.src('**/*.scss'))
    .pipe(sass.sync({outputStyle: 'compressed'})).on('error', conf.errorHandler('Sass'))
    .pipe(postcss([autoprefixer()])).on('error', conf.errorHandler('Autoprefixer'))
    .pipe(mergeCSS({ name: 'style.css' }))
    .pipe(cleanCSS({compatibility: 'ie8', multiplePseudoMerging: true}))
    .pipe(gulp.dest(conf.path.tmp()))
    .pipe(browserSync.stream());
}

Solution

  • I don't think there exists a plugin to achieve this, but I wouldn't recommend combining anyway, because combining CSS rules can change the precedence of the rules.


    Example

    Imagine a scenario where you have two elements, and two classes. The HTML code is:

    <div class="foo">Hello</div>
    <div class="foo bar">World</div>
    

    and the concatenated CSS looks like this:

    .foo {
      background: #000;
    }
    
    .bar {
      color: #999;
    }
    
    .foo {
      color: #FFF;
    }
    

    The result would be both divs having a background color of #000 and a text color of #FFF, because the definition of the text color for .foo comes after .bar.

    If you combine the rules, the CSS becomes this:

    .foo {
      background: #000;
      color: #FFF;
    }
    
    .bar {
      color: #999;
    }
    

    This changes the meaning, as both divs will still have a background color of #000, but the second div will now have a text color of #999, as .bar now takes precedence over .foo.