Giter VIP home page Giter VIP logo

node-css-mqpacker's Introduction

CSS MQPacker

Pack same CSS media query rules into one using PostCSS

SYNOPSIS

A well componentized CSS file may have same media queries that can merge:

.foo {
	width: 240px;
}

@media screen and (min-width: 768px) {
	.foo {
		width: 576px;
	}
}

.bar {
	width: 160px;
}

@media screen and (min-width: 768px) {
	.bar {
		width: 384px;
	}
}

This tool packs exactly same media queries:

.foo {
	width: 240px;
}

.bar {
	width: 160px;
}

@media screen and (min-width: 768px) {
	.foo {
		width: 576px;
	}
	.bar {
		width: 384px;
	}
}

INSTALL

$ echo @hail2u:registry=https://npm.pkg.github.com >> .npmrc
$ npm install --save-dev @hail2u/css-mqpacker

If you or your team member does not have GitHub account, you can install directly from the GitHub repository:

$ npm install --save-dev github:hail2u/node-css-mqpacker#<TAG>

<TAG> should be replaced with one of the available tags.

USAGE

Of course, this package can be used as PostCSS plugin:

const fs = require("fs");
const postcss = require("postcss");

postcss([
	require("@hail2u/css-mqpacker")()
]).process(fs.readFileSync("from.css", "utf8")).then(function (result) {
	console.log(result.css);
});

It is a recommended way to use this tool.

As standard Node.js package

This package is also a Node.js module. For example, you can read from.css, process its content, and output processed CSS to STDOUT:

const fs = require("fs");
const mqpacker = require("@hail2u/css-mqpacker");

console.log(mqpacker.pack(fs.readFileSync("from.css", "utf8"), {
	from: "from.css",
	map: {
		inline: false
	},
	to: "to.css"
}).css);

As CLI Program

This package also installs a command line interface.

$ node ./node_modules/.bin/mqpacker --help
Usage: mqpacker [options] INPUT [OUTPUT]

Description:
  Pack same CSS media query rules into one using PostCSS

Options:
  -s, --sort       Sort “min-width” queries.
      --sourcemap  Create source map file.
  -h, --help       Show this message.
      --version    Print version information.

Use a single dash for INPUT to read CSS from standard input.

Examples:
  $ mqpacker fragmented.css
  $ mqpacker fragmented.css > packed.css

When PostCSS failed to parse INPUT, CLI shows a CSS parse error in GNU error format instead of Node.js stack trace.

The --sort option does not currently support a custom function.

OPTIONS

sort

By default, CSS MQPacker pack and order media queries as they are defined (the “first win” algorithm). If you want to sort media queries automatically, pass sort: true to this module.

postcss([
	mqpacker({
		sort: true
	})
]).process(css);

Currently, this option only supports min-width queries with specific units (ch, em, ex, px, and rem). If you want to do more, you need to create your own sorting function and pass it to this module like this:

postcss([
	mqpacker({
		sort: function (a, b) {
			return a.localeCompare(b);
		}
	})
]).process(css);

In this example, all your media queries will sort by A-Z order.

This sorting function is directly passed to Array#sort() method of an array of all your media queries.

API

pack(css[, options])

Packs media queries in css.

The second argument is optional. The options are:

You can specify both at the same time.

const fs = require("fs");
const mqpacker = require("@hail2u/css-mqpacker");

const result = mqpacker.pack(fs.readFileSync("from.css", "utf8"), {
	from: "from.css",
	map: {
		inline: false
	},
	sort: true,
	to: "to.css"
});
fs.writeFileSync("to.css", result.css);
fs.writeFileSync("to.css.map", result.map);

NOTES

With CSS MQPacker, the processed CSS is always valid CSS, but you and your website user will get unexpected results. This section explains how CSS MQPacker works and what you should keep in mind.

CSS Cascading Order

CSS MQPacker changes rulesets’ order. This means the processed CSS will have an unexpected cascading order. For example:

@media (min-width: 640px) {
	.foo {
		width: 300px;
	}
}

.foo {
	width: 400px;
}

Becomes:

.foo {
	width: 400px;
}

@media (min-width: 640px) {
	.foo {
		width: 300px;
	}
}

.foo is always 400px with original CSS. With processed CSS, however, .foo is 300px if viewport is wider than 640px.

This does not occur on small project. However, this could occur frequently on large project. For example, if you want to override a CSS framework (like Bootstrap) component declaration, your whole CSS code will be something similar to above example. To avoid this problem, you should pack only CSS you write, and then concatenate with a CSS framework.

The “First Win” Algorithm

CSS MQPacker is implemented with the “first win” algorithm. This means:

.foo {
	width: 10px;
}

@media (min-width: 640px) {
	.foo {
		width: 150px;
	}
}

.bar {
	width: 20px;
}

@media (min-width: 320px) {
	.bar {
		width: 200px;
	}
}

@media (min-width: 640px) {
	.bar {
		width: 300px;
	}
}

Becomes:

.foo {
	width: 10px;
}

.bar {
	width: 20px;
}

@media (min-width: 640px) {
	.foo {
		width: 150px;
	}
	.bar {
		width: 300px;
	}
}

@media (min-width: 320px) {
	.bar {
		width: 200px;
	}
}

This breaks cascading order of .bar, and .bar will be displayed in 200px instead of 300px even if a viewport wider than 640px.

I suggest defining a query order on top of your CSS:

@media (min-width: 320px) { /* Wider than 320px */ }
@media (min-width: 640px) { /* Wider than 640px */ }

If you use simple min-width queries only, the sort option can help.

Multiple Classes

CSS MQPacker works only with CSS. This may break CSS applying order to an elements that have multiple classes. For example:

@media (min-width: 320px) {
	.foo {
		width: 100px;
	}
}

@media (min-width: 640px) {
	.bar {
		width: 200px;
	}
}

@media (min-width: 320px) {
	.baz {
		width: 300px;
	}
}

Becomes:

@media (min-width: 320px) {
	.foo {
		width: 100px;
	}
	.baz {
		width: 300px;
	}
}

@media (min-width: 640px) {
	.bar {
		width: 200px;
	}
}

The result looks good. However, if an HTML element has class="bar baz" and viewport width larger than 640px, that element width incorrectly set to 200px instead of 300px. This problem cannot be resolved only with CSS, so be careful!

LICENSE

MIT

node-css-mqpacker's People

Contributors

ai avatar dependabot[bot] avatar hail2u avatar maks3w avatar mrmlnc avatar nschonni avatar subtronic avatar vast avatar vitkarpov avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

node-css-mqpacker's Issues

Reduce package size

Package contains unnecessary directories - .istanbul, test. I can do PR if your accept this issue.

Unexpected token error on line 139 of index.js

Grunt task is hanging on the following on line 139 of the index.js file: ...options. This looks like a new issue, as I haven't had problems until updating to the latest version.

Thanks for the plugin!

Order of media queries

Hello!
I can not understand how to do this, so that media requests are in descending order.
I added the CSS MQPacker to my webpack config

{
                                loader: 'postcss-loader',
                                options: {
                                    sourceMap: ! isProduction,
                                    plugins: (() => {
                                        return isProduction ? [
                                            require('autoprefixer')({
                                                browsers: ['last 2 versions']
                                            }),
					    require('css-mqpacker')({
						sort: true
                                            }),
                                            require('cssnano')({
                                                discardComments: {
                                                    removeAll: true
                                                }
                                            })
                                        ] : []
                                    })()
                                }
                            },

All media requests are collected at the end of the document. But they do not go in order. For example


@media screen and (max-width: 480px){
	
}

@media screen and (max-width: 320px){
	
}

@media screen and (max-width: 768px){
	
}

What have I done wrong, and how can I solve this problem?
Thank you!

CSS Mqpacker plugin not works with PostCSS Webpack loader (Webpack 2)

Hi there!

I'm using:

  • webpack v2.2.0-rc.2
  • postcss-loader v1.2.1
  • css-mqpacker v5.0.1

Here is a part of my webpack.config.babel.js:

export default {
    entry: './components/App/index.jsx',
    output: {
        path: path.join(process.cwd(), './public'),
        filename: 'main.[hash].js',
    },

    plugins: [
        new webpack.LoaderOptionsPlugin({
            options: {
                context: __dirname,
                postcss: [
                    cssnext({
                        browsers: ['last 2 versions', 'IE > 10'],
                    }),
                    cssMqpacker(),
                ],
            },
        }),

        new ExtractTextPlugin({
            filename: 'style.[hash].css',
            disable: false,
            allChanks: true,
        }),
    ],

    module: {
        loaders: [{
            test: /\.css$/,
            loader: ExtractTextPlugin.extract({
                fallbackLoader: 'style-loader',
                loader: 'css-loader?modules&localIdentName=[local]--[hash:base64:5]!postcss-loader',
            }),
        }],
    },
}

And postcss-cssnext and other plugins works good. But not css-mqpacker. When I'm building app I see the following CSS code:

.title--Njw1N {
    color: red
}
@media (max-width: 800px) {
    .title--Njw1N {
        color: darkred
    }
}
.title--13b4T {
    color: yellow
}
@media (max-width: 800px) {
    .title--13b4T {
        color: orange
    }
}
.title--FYL1K {
    color: green
}
@media (max-width: 800px) {
    .title--FYL1K {
        color: darkgreen
    }
}

Please see the example here: https://github.com/azat-io/webpack2-css-modules-demo

group media-queries feature

To help manage CSS cascading order issues described here, it would be very useful to be able to define packing groups.

All media-queries belonging to these packing groups would then be merged and packed at the end of the group, independently of media-queries from other groups. This allows to control which media queries get merged together, and where they end-up in the final rendered CSS.

This would solve issues with modular CSS architectures where the specificity of the component selectors is very low (single classname selectors with a 0:1:0), and therefore the order of the component definitions (or types of components) is particularly important and should not be modified by merging and moving @media queries around.

For example, if you define classes at the end of your stylesheet in order to override rules defined in earlier in your stylesheet. If one of these previous styles uses media-queries, you can end-up with conflicts:

src/main.css

.module {
  margin-bottom: 10px;
}

@media (min-width: 800px)
{
  .module {
    margin-bottom: 20px;
  }
}

.nobottom {
  margin-bottom: 0;
}

Here is a suggested syntax to implement the grouping feature and preserve the wanted CSS cascading order:

src/main.css

/* somewhere in the beginning/middle of the src css file */

@mqpack
{
  .foo {
    margin-bottom: 10px;
  }

  @media (min-width: 800px)
  {
    .foo {
      margin-bottom: 20px;
    }
  }

  .bar {
    padding: 20px;
  }

  @media (min-width: 800px)
  {
    .bar {
      padding: 30px;
    }
  }
}

.nobottom {
  margin-bottom: 0;
}

dest/main.css

/* somewhere in the beginning/middle of the src css file */

.foo {
  margin-bottom: 10px;
}

.bar {
  padding: 20px;
}

@media (min-width: 800px)
{
  .foo {
    margin-bottom: 20px;
  }

  .bar {
    padding: 30px;
  }
}

.nobottom {
  margin-bottom: 0;
}

Break styles with directive supports

Sсss:

The styles that are placed in the directive of the supports, and later in the media query, are broken.

input:

@support (display: grid) {
  .e {
    width: 100px;

    @media (min-width: 1024px) {
      width: 500px;
    }
  }
}

current output:

@supports (display: grid) {
  .e {
    width: 100px;
  }
}

@media (min-width: 1024px){
  .e{
    width: 500px;
  }
}

need:

@supports (display: grid) {
  .e {
    width: 100px;
  }

  @media (min-width: 1024px) {
    .e {
      width: 500px;
    }
  }
}

or maybe

@supports (display: grid) {
  .e {
    display: block;
    width: 100px;
  }
}

@media (min-width: 1024px){
  @supports (display: grid) {
    .e{
      width: 500px;
    }
  }
}

Sorting (min-width) and (min-height)

Hi,

The sort option is working great with for query using only min-width (as you mention). However I quite often used min-width associated with min-height and in this case the sorting is not good.

@media all and (min-width: 62.5em) and (min-height: 57.5em)

is sorted before:

@media all and (min-width: 62.5em) and (min-height: 37.5em)

and even:

@media all and (min-width: 62.5em) and (min-height: 48.125em)

is sorted before a simple min-width query like:

@media all and (min-width: 62.5em)

Is there a way to make it work with min-height?

Thanks a lot for your help!

READMEが古い?

READMEがGitHub Packages を使う前のままになっていると思います。
require("css-mqpacker")はもう動かないです。
正しくは require("@hail2u/css-mqpacker")

How to exclude Bootstrap framework?

How can I exclude Bootstrap framework?
postcss.config.js file:

module.exports = { plugins: [ require('autoprefixer'), require('css-mqpacker'), require('cssnano')({ preset: [ 'default', { discardComments: { removeAll: true, } } ] }) ] }

webpack.config.js
{ test: /\.scss$/, use: [ 'style-loader', MiniCssExtractPlugin.loader, { loader: 'css-loader', //options: {sourceMap: true} }, { loader: 'postcss-loader', options: { //sourceMap: true, config: { path: 'assets/js/postcss.config.js' } } }, { loader: 'sass-loader', } ] }

double sourceMappingURL in output

Hi,
great job on this tool.

I have a problem with processors and a double sourceMappingURL (original + generated) in the output when using grunt-postcss.

The grunt configuration :

postcss: { //grunt-postcss
    options: {
        map: true,
        processors: [
            require('autoprefixer-core')({browsers: ['last 2 versions', 'ie 8', 'ie 9']}).postcss,
            require('css-mqpacker').postcss,
            require('csswring').postcss
        ]
    },
    // files
}          

And the output :

//rules
/*# sourceMappingURL=global.css.map */@media(min-width:768px){.header__logo{border-bottom-width:0;padding-bottom:20px}.body--scrolled .header__logo{display:block}.mobileNav{display:none}}
/*# sourceMappingURL=global.min.css.map */

If I remove "css-mqpacker" from the processor, no problem but I loose the media queries merging.
I tried to put it before autoprefixer, after csswring, same bug.

I have created an issue on postcss repository too (#106).

Install not working without GitHub token

This was the first time I tried to install an NPM package from GitHub and unfortunately it turned out more tricky than expected.

Running your example

$ echo @hail2u:registry=https://npm.pkg.github.com >> .npmrc
$ npm install --save-dev @hail2u/css-mqpacker

I got the following error:

vue % npm install --save-dev @hail2u/css-mqpacker
npm ERR! code E401
npm ERR! Unable to authenticate, need: Basic realm="GitHub Package Registry"

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/atreju/.npm/_logs/2020-08-27T17_30_54_056Z-debug.log

I was only able to resolve this by creating a Personal Access Token for my GitHub profile. Unfortunately, this makes the package almost unusable, if I have to share the code with other developers who might have no GitHub account (:scream:).

Maybe you are aware of the issue, just wanted to let you know.

Thanks!

This is such an great plugin. 🙏

input via stdin not working under windows?

Windows 10.
Node LTS - v4.6.0
I can't seem to run this package when feeding it via stdin......(see below)
The same test works ok when a file is named as the input.
Is this a bug?

cat index.css | .\node_modules.bin\mqpacker.cmd - > za
fs.js:549
return binding.open(pathModule._makeLong(path), stringToFlags(flags), mode);
^

TypeError: path must be a string
at TypeError (native)
at Object.fs.openSync (fs.js:549:18)
at Object.fs.readFileSync (fs.js:397:15)
at Object. (M:\A\My Documents\year12 outcomes_www_dev\node_modules\css-mqpacker\bin\mqpacker.js:118:12)
at Module._compile (module.js:409:26)
at Object.Module._extensions..js (module.js:416:10)
at Module.load (module.js:343:32)
at Function.Module._load (module.js:300:12)
at Function.Module.runMain (module.js:441:10)
at startup (node.js:139:18)

Doesn't working

Doesn't working.
gulp.task('postcss', function () {

        var plugins = [
            require('postcss-import'),
            require('postcss-nested'),
            require('postcss-simple-vars'),
            require('postcss-mixins')({
                mixinsDir: path.join(__dirname, '/src/css/mixins/')
            }),
            rfs(rfs_options),
            require("@hail2u/css-mqpacker")(),
       ];
    
        return gulp.src("./src/css/style.scss")
            .pipe(postcss(plugins, {
                parser: require('postcss-scss')
            }))
            .pipe(gulp.dest('./public_html_src/'));
    });

I don't see any changes in the file. If I will replace require("@hail2u/css-mqpacker") to another package require("postcss-sort-media-queries") it works at the same config.

Broken sort with `min-width: 0`

I realize this media query will always match, so it's a bit weird to even have it, but I do (for irrelevant reasons), and it doesn't seem to be sorted correctly.

I believe the issue is that this line checks !minWidth, so min-width: 0 is treated as though the min-width isn't specified at all.

Split stylesheets by media queries

Perhaps this is out of scope of your plugin and should be handled at the build tool level (webpack, fusebox), but it would be awesome if we could split stylesheets by media queries after grouping, such as in Google developers example:

<link rel="stylesheet" href="default.css">
<link rel="stylesheet" media="(max-width: 640px)" href="max-640px.css">
<link rel="stylesheet" media="(min-width: 640px)" href="min-640px.css">
<link rel="stylesheet" media="(orientation: portrait)" href="portrait.css">
<link rel="stylesheet" media="(orientation: landscape)" href="landscape.css">

Version 2.1 breaks API

You have removed old interfaces from 2fc2adf, so it breaks API. It would have been better to name it 3.0.0.

I was using .processor and requiring module with ^2.0.0, so now it breaks.

Related: iamvdo/pleeease#35

required node version

I noticed that mqpacker would like Node V5 and above. Is there a reason for this? I am currently using Node 4.4.5 which is the latest LTS version so I would have assumed would be supported.

Sorting order max-width

Hi!

Thanks for this nice code.

Just wondering if you have any plan to make this work out of the box with max-width?

Thanks

gulp/webpack support

Is there a way to run in in a gulp/webpack stack (with postcss-/style-/stylus-loader)?

Incorrect ordering

If I’m writing sass, I often add MQs inline, but this tool orders them incorrectly unless I use them in the correct order.

EG:

body {
    @include font-size(26);
    @media screen and (max-width: 414px) {
        @include font-size(18);
    }
}


h1 {
    left: 105px;
    right: auto;
    top: 138px;

    @media screen and (max-width: 768px) {
        left: 50px;
        right: 50px;
        top: 50px;
    }

    @media screen and (max-width: 414px) {
        left: 20px;
        right: 20px;
        top: 20px;
    }
}

This does not work correctly, it outputs:

 body {
    font-size: 26px;
    font-size: 2.6rem
}
h1 {
    left: 105px;
    right: auto;
    top: 138px
}
@media screen and (max-width:414px) {
    body {
        font-size: 18px;
        font-size: 1.8rem
    }
    h1 {
        left: 20px;
        right: 20px;
        top: 20px
    }
}
@media screen and (max-width:768px) {
    h1 {
        left: 50px;
        right: 50px;
        top: 50px
    }
}

This is wrong, the max-width rules should be in descending order, not in order of appearance.
If I add an extra max-width:414 rule that does nothing to the body above, e.g.:

body {
    @include font-size(26);
    @media screen and (max-width: 768px) {
        @include font-size(26);
    }
    @media screen and (max-width: 414px) {
        @include font-size(18);
    }
}


h1 {
    left: 105px;
    right: auto;
    top: 138px;

    @media screen and (max-width: 768px) {
        left: 50px;
        right: 50px;
        top: 50px;
    }

    @media screen and (max-width: 414px) {
        left: 20px;
        right: 20px;
        top: 20px;
    }
}

Then I get code that works:

body {
    font-size: 26px;
    font-size: 2.6rem
}
h1 {
    left: 105px;
    right: auto;
    top: 138px
}
@media screen and (max-width:768px) {
    body {
        font-size: 26px;
        font-size: 2.6rem
    }
    h1 {
        left: 50px;
        right: 50px;
        top: 50px
    }
}
@media screen and (max-width:414px) {
    body {
        font-size: 18px;
        font-size: 1.8rem
    }
    h1 {
        left: 20px;
        right: 20px;
        top: 20px
    }
}

Unsafe grouping

Hi,

I recently saw a couple of interesting comments about unsafe media query grouping. Correct me if I am wrong, but I think node-css-mqpacker is affected by this problem - I am not able to test for now -. There must be a way to solve this, by ensuring that media queries are not conflicted.

This is highly problematic as now the package may break website render and therefore is not suitable for production.

Issue in index.js ?

After installing the latest version - [email protected] via npm, there is an error when compiling in webpack:

SyntaxError: Unexpected token ...

specifically, on line 139 in index.js - node_modules/css-mqpacker/index.js:139

Commenting it out resolves the issue and everything appears to work.

module.exports = postcss.plugin(pkg.name, options => {
 const opts = {
   sort: false,
   // ...options // is this supposed to be here?
 };

Thanks for this plugin.

@import rules corrupted when the CSS is preprocessed by CSSWring

Hi, I've tried to add CSS MQPacker into my Grunt build via grunt-css-mqpacker, but it is removing @import rules as per this CSS (expanded for readability, this would usually appear on one line):

@charset "UTF-8";
@import;
@import;
@import;
@import;
@import;
@import;
@import;
@import;
@import;
@import;
@font-face {
    font-family: Clavo;
    src: url(../fonts/clavo/webfonts/2A25D0_0_0.eot);
    src: url(../fonts/clavo/webfonts/2A25D0_0_0.eot?#iefix) format("embedded-opentype"), url(../fonts/clavo/webfonts/2A25D0_0_0.woff) format("woff"), url(../fonts/clavo/webfonts/2A25D0_0_0.ttf) format("truetype")
}
@font-face {
    font-family: Clavo;
    src: url(../fonts/clavo/webfonts/2A25D0_1_0.eot);
    src: url(../fonts/clavo/webfonts/2A25D0_1_0.eot?#iefix) format("embedded-opentype"), url(../fonts/clavo/webfonts/2A25D0_1_0.woff) format("woff"), url(../fonts/clavo/webfonts/2A25D0_1_0.ttf) format("truetype");
    font-style: italic
}
@font-face {
    font-family: Clavo;
    src: url(../fonts/clavo/webfonts/2A25D0_3_0.eot);
    src: url(../fonts/clavo/webfonts/2A25D0_3_0.eot?#iefix) format("embedded-opentype"), url(../fonts/clavo/webfonts/2A25D0_3_0.woff) format("woff"), url(../fonts/clavo/webfonts/2A25D0_3_0.ttf) format("truetype");
    font-weight: 700
}
@font-face {
    font-family: Clavo;
    src: url(../fonts/clavo/webfonts/2A25D0_2_0.eot);
    src: url(../fonts/clavo/webfonts/2A25D0_2_0.eot?#iefix) format("embedded-opentype"), url(../fonts/clavo/webfonts/2A25D0_2_0.woff) format("woff"), url(../fonts/clavo/webfonts/2A25D0_2_0.ttf) format("truetype");
    font-weight: 700;
    font-style: italic
}
@font-face {
    font-family: FontAwesome;
    src: url(../../../bower_components/Font-Awesome/fonts/fontawesome-webfont.eot?v=4.1.0);
    src: url(../../../bower_components/Font-Awesome/fonts/fontawesome-webfont.eot?#iefix&v=4.1.0) format("embedded-opentype"), url(../../../bower_components/Font-Awesome/fonts/fontawesome-webfont.woff?v=4.1.0) format("woff"), url(../../../bower_components/Font-Awesome/fonts/fontawesome-webfont.ttf?v=4.1.0) format("truetype"), url(../../../bower_components/Font-Awesome/fonts/fontawesome-webfont.svg?v=4.1.0#fontawesomeregular) format("svg")
}
/* CSS continues here */

The previous step in the process is grunt-csswring (based on CSSWring). That outputs this CSS (expanded for readability, this would usually appear on one line):

@charset "UTF-8";
@import"//hello.myfonts.net/count/2a25d0";
@import"//hello.myfonts.net/count/2a529d";
@import"//hello.myfonts.net/count/280bdd";
@import"//cloud.typography.com/6385092/618064/css/fonts.css";
@import"../../../bower_components/normalize-css/normalize.css";
@import"../../../bower_components/royal-slider/royalslider.css";
@import"../../../bower_components/royal-slider/skins/default/rs-default.css";
@import"../../../bower_components/royal-slider/skins/minimal-white/rs-minimal-white.css";
@import"../../../bower_components/ct-jquery-ariaHiddenBreakrange/dist/ct-jquery-ariaHiddenBreakrange.css";
@import"../../../bower_components/ct-jquery-matchHeights/dist/ct-jquery-matchHeights.css";
@font-face {
    font-family: Clavo;
    src: url(../fonts/clavo/webfonts/2A25D0_0_0.eot);
    src: url(../fonts/clavo/webfonts/2A25D0_0_0.eot?#iefix) format("embedded-opentype"), url(../fonts/clavo/webfonts/2A25D0_0_0.woff) format("woff"), url(../fonts/clavo/webfonts/2A25D0_0_0.ttf) format("truetype")
}
@font-face {
    font-family: Clavo;
    src: url(../fonts/clavo/webfonts/2A25D0_1_0.eot);
    src: url(../fonts/clavo/webfonts/2A25D0_1_0.eot?#iefix) format("embedded-opentype"), url(../fonts/clavo/webfonts/2A25D0_1_0.woff) format("woff"), url(../fonts/clavo/webfonts/2A25D0_1_0.ttf) format("truetype");
    font-style: italic
}
@font-face {
    font-family: Clavo;
    src: url(../fonts/clavo/webfonts/2A25D0_3_0.eot);
    src: url(../fonts/clavo/webfonts/2A25D0_3_0.eot?#iefix) format("embedded-opentype"), url(../fonts/clavo/webfonts/2A25D0_3_0.woff) format("woff"), url(../fonts/clavo/webfonts/2A25D0_3_0.ttf) format("truetype");
    font-weight: 700
}
@font-face {
    font-family: Clavo;
    src: url(../fonts/clavo/webfonts/2A25D0_2_0.eot);
    src: url(../fonts/clavo/webfonts/2A25D0_2_0.eot?#iefix) format("embedded-opentype"), url(../fonts/clavo/webfonts/2A25D0_2_0.woff) format("woff"), url(../fonts/clavo/webfonts/2A25D0_2_0.ttf) format("truetype");
    font-weight: 700;
    font-style: italic
}
@font-face {
    font-family: FontAwesome;
    src: url(../../../bower_components/Font-Awesome/fonts/fontawesome-webfont.eot?v=4.1.0);
    src: url(../../../bower_components/Font-Awesome/fonts/fontawesome-webfont.eot?#iefix&v=4.1.0) format("embedded-opentype"), url(../../../bower_components/Font-Awesome/fonts/fontawesome-webfont.woff?v=4.1.0) format("woff"), url(../../../bower_components/Font-Awesome/fonts/fontawesome-webfont.ttf?v=4.1.0) format("truetype"), url(../../../bower_components/Font-Awesome/fonts/fontawesome-webfont.svg?v=4.1.0#fontawesomeregular) format("svg")
}
/* CSS continues here */

For reference my CSS Wring Grunt configuration is:

{
    "styles": {
        "options": {
            "banner": false,
            "map": false,
            "mapInline": false,
            "preserveHacks": true,
            "removeAllComments": true,
            "report": false
        },
        "files": [{
            "expand": true,
            "cwd": "<%= project.build.styles %>/",
            "src": [
                "*.css"
            ],
            "dest": "<%= project.build.styles %>/",
            "ext": ".css"
        }]
    }
}

and my MQ Packer Grunt configuration is:

{
    "styles": {
        "files": [{
            "expand": true,
            "cwd": "<%= project.build.styles %>/",
            "src": [
                "*.css"
            ],
            "dest": "<%= project.build.styles %>/",
            "ext": ".css"
        }]
    }
}

Thanks,
Dan

min-resolution dpi media queries ordering on top with default sort order

I have the following scss (I use SassMQ)

.c-banner__top {
  @include mq($from: desk) {
    .o-container {
      .bowling & {
        background-image: url(../images/ba-bowling-banner-1400.jpg);

        @media (min-resolution: 144dpi) {
          background-image: url(../images/ba-bowling-banner-2100.jpg);
        }
        @media (min-resolution: 192dpi) {
          background-image: url(../images/ba-bowling-banner-2800.jpg);
        }
      }
    }
  }
}

Once my sass has compiled, I use postcss to combine the media queries. However, with sort:true enabled, the output CSS puts the media queries with min-resolution above the ones without.

@media (min-width: 64em) and (-webkit-min-device-pixel-ratio: 2), (min-width: 64em) and (min-resolution: 192dpi){
  .bowling .c-banner__top .o-container{
    background-image: url(../images/ba-bowling-banner-2800.jpg); } }

@media (min-width: 64em) and (-webkit-min-device-pixel-ratio: 1.5), (min-width: 64em) and (min-resolution: 144dpi){
  .bowling .c-banner__top .o-container{
    background-image: url(../images/ba-bowling-banner-2100.jpg); } }

@media (min-width: 64em){
.bowling .c-banner__top .o-container{
    background-image: url(../images/ba-bowling-banner-1400.jpg); } }

Which means even though the 2x or 1.5x image should be used, because of CSS' cascade the lower quality 1400 is always selected.

If I use the custom sort function as detailed in the readme:

sort: function (a, b) {
  return a.localeCompare(b);
}

It works as I hoped and the higher quality image is displayed on those screens:

@media (min-width: 64em){
.bowling .c-banner__top .o-container{
    background-image: url(../images/ba-bowling-banner-1400.jpg); } }

@media (min-width: 64em) and (-webkit-min-device-pixel-ratio: 1.5), (min-width: 64em) and (min-resolution: 144dpi){
  .bowling .c-banner__top .o-container{
    background-image: url(../images/ba-bowling-banner-2100.jpg); } }

@media (min-width: 64em) and (-webkit-min-device-pixel-ratio: 2), (min-width: 64em) and (min-resolution: 192dpi){
  .bowling .c-banner__top .o-container{
    background-image: url(../images/ba-bowling-banner-2800.jpg); } }

I was just wondering why this custom sort function is not the default function? I'm sure someone else will come across this quirk in future. Or perhaps in future there could be a setting in the options to enable if you are using the combined min-resolution media queries?

Cheers

Source map support

To full source map support you need to set to option too.

Maybe instead of:

mqpacker.pack(original, 'file.css').css

you can use options:

mqpacker.pack(original, from: 'file.css', to: 'file.css', inlineMap: true).css

Crush on empty media query

Hello, I'm on Windows and got packer crash on this string

@media screen and (min-width: 1280px) { }

this code comes from SCSS

    @include respond-to("desktop") {
      // flex-grow: 1;
    }

where respond-to is mixin wich construct media query

The error message looks next

stream.js:94
      throw er; // Unhandled stream error in pipe.
            ^
TypeError: Cannot read property 'before' of undefined
    at C:\project\git\node_modules\css-mqpacker\lib\css-mqpacker.js:36:8
9
    at Root.Container.each (C:\project\git\node_modules\gulp-postcss\node_modules\postcss\lib\container.js:88:20)
    at _process (C:\project\git\node_modules\css-mqpacker\lib\css-mqpacker.js:27:7)
    at PostCSS.process (C:\project\git\node_modules\gulp-postcss\node_modules\postcss\lib\postcss.js:34:28)
    at DestroyableTransform.transform [as _transform] (C:\project\git\node_modules\gulp-postcss\index.js:49:26)
    at DestroyableTransform.Transform._read (C:\project\git\node_modules\gulp-postcss\node_modules\through2\node_modules\readable-stream\lib\_stream_transform.js:184:10)
    at DestroyableTransform.Transform._write (C:\project\git\node_modules\gulp-postcss\node_modules\through2\node_modules\readable-stream\lib\_stream_transform.js:172:12)
    at doWrite (C:\project\git\node_modules\gulp-postcss\node_modules\through2\node_modules\readable-stream\lib\_stream_writable.js:238:10)
    at writeOrBuffer (C:\project\git\node_modules\gulp-postcss\node_modules\through2\node_modules\readable-stream\lib\_stream_writable.js:228:5)
    at DestroyableTransform.Writable.write (C:\project\git\node_modules\gulp-postcss\node_modules\through2\node_modules\readable-stream\lib\_stream_writable.js:195:11)```

Does not work well after update

I use postcss-loader latest version as postcss plugin.

https://github.com/hail2u/node-css-mqpacker/blob/master/index.js#L182

sortQueryLists(queryLists, opts.sort).forEach((queryList) => {
    console.log(queryList);
    css.append(queries[queryList]);
});

For v5:

(min-width: 480px) and (max-width: 767px)                         
(min-width: 480px)
screen and (min-width: 600px) and (max-width: 782px)
(min-width: 768px) and (max-width: 991px)
(min-width: 768px)
(min-width: 768px) and (max-width: 767px)
screen and (min-width: 782px)
(min-width: 783px)
(min-width: 1296px), (max-width: 1199px) and (min-width: 1096px), (max-width: 991px) and (min-width: 876px)
(min-width: 992px)
(min-width: 992px) and (max-width: 1199px)
(min-width: 1200px)
screen and (-ms-high-contrast: active), (-ms-high-contrast: none)
screen and (-webkit-min-device-pixel-ratio: 0)
(max-width: 1199px)
(max-width: 767px)
screen and (min-width: 0 \0)
print
(-webkit-min-device-pixel-ratio: 1.1), (-webkit-min-device-pixel-ratio: 1.09375), (min-resolution: 105dpi), (min-resolution: 1.1dppx)
screen and (max-width: 1024px)
screen and (max-width: 767px)
(max-width: 479px)
(max-width: 991px)
(max-width: 600px)
(max-device-width: 480px) and (orientation: landscape)
(min-width: 0) and (max-width: 767px)
(min-width: 0) and (max-width: 767px) and (min-width: 480px)
(min-width: 0) and (max-width: 767px) and (min-width: 768px)
(min-width: 0) and (max-width: 767px) and (min-width: 992px)
(min-width: 0) and (max-width: 767px) and (min-width: 1200px)

For v6

print                                                             
(min-width: 768px)
(min-width: 992px)
(min-width: 1200px)
(min-width: 480px)
screen and (max-width: 767px)
screen and (-webkit-min-device-pixel-ratio: 0)
(max-width: 767px)
(min-width: 768px) and (max-width: 991px)
(min-width: 992px) and (max-width: 1199px)
(max-width: 479px)
(max-width: 991px)
(max-width: 600px)
(min-width: 783px)
(max-width: 1199px)
screen and (-ms-high-contrast: active), (-ms-high-contrast: none)
screen and (min-width: 0 \0)
(min-width: 768px) and (max-width: 767px)
(-webkit-min-device-pixel-ratio: 1.1), (-webkit-min-device-pixel-ratio: 1.09375), (min-resolution: 105dpi), (min-resolution: 1.1dppx)
screen and (max-width: 1024px)
screen and (min-width: 600px) and (max-width: 782px)
screen and (min-width: 782px)
(min-width: 480px) and (max-width: 767px)
(min-width: 1296px), (max-width: 1199px) and (min-width: 1096px), (max-width: 991px) and (min-width: 876px)
(max-device-width: 480px) and (orientation: landscape)
(min-width: 0) and (max-width: 767px)
(min-width: 0) and (max-width: 767px) and (min-width: 480px)
(min-width: 0) and (max-width: 767px) and (min-width: 768px)
(min-width: 0) and (max-width: 767px) and (min-width: 992px)
(min-width: 0) and (max-width: 767px) and (min-width: 1200px)

I try to investigate why it is happens.

Plugin generate not equal styles

The merging of queries means reordering of selectors.
So we will have not equal stylesheet on output.

Example:

.myClass {
    font-size: 50px;
}

@media (max-width: 1024px) {
    .myClass {
        font-size: 40px;
    }
}

.myClass_big {
    font-size: 76px;
}

@media (max-width: 1024px) {
    .myClass_bigOnMobile {
        font-size: 76px;
    }
}

After using of plugin code will look like this:

.myClass {
    font-size: 50px;
}

.myClass_big {
    font-size: 76px;
}

@media (max-width: 1024px) {
    .myClass {
        font-size: 40px;
    }
    .myClass_bigOnMobile {
        font-size: 76px;
    }
}

In the first case, element <div class="myClass myClass_big">Text</div> have font-size: 76px at any window width.
In the second case, block

@media (max-width: 1024px) {
    .myClass {
        font-size: 40px;
    }
}

have moved down, so selector with default styles for mobile devices now have higher priority than
selector with modificator big.
Therefore, text on phones will have font-size: 40px, not font-size: 40px.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.