PostCSS media queries
There’s a neat little plugin for postCSS called postcss-extract-media-query and I think it's awesome. It generates separate CSS files for every media query you specify you want to extract.
"If page speed is important to you chances are high you're already doing code splitting. If your CSS is built mobile-first (in particular if using a framework such as Bootstrap or Foundation) chances are also high you're loading more CSS than the current viewport actually needs."
When using postCSS without any options, it will look for a postcss.config file at the root of your project. In as in the example below, that is where you tell the plugin which queries specified in your css file that you want the plugin to act upon:
// gulp example:
.pipe(postcss()...
// gulp example:
.pipe(postcss()...
module.exports = {
plugins: {
"postcss-extract-media-query": {
output: {
path: path.join(__dirname, "public/css/optimized"),
},
queries: {
"screen and (min-width: 1024px)": "desktop",
},
stats: false,
},
},
};
module.exports = {
plugins: {
"postcss-extract-media-query": {
output: {
path: path.join(__dirname, "public/css/optimized"),
},
queries: {
"screen and (min-width: 1024px)": "desktop",
},
stats: false,
},
},
};
Using this config the plugin will extract all base styles and all desktop styles and put them in separate files:
base.css
base.min.css
base.desktop.min.css
Example - before
/* base.css */
.foo {
color: red;
}
@media screen and (min-width: 1024px) {
.foo {
color: green;
}
}
.bar {
font-size: 1rem;
}
@media screen and (min-width: 1024px) {
.bar {
font-size: 2rem;
}
}
/* base.css */
.foo {
color: red;
}
@media screen and (min-width: 1024px) {
.foo {
color: green;
}
}
.bar {
font-size: 1rem;
}
@media screen and (min-width: 1024px) {
.bar {
font-size: 2rem;
}
}
Example - after
/* base.css */
.foo {
color: red;
}
.bar {
font-size: 1rem;
}
/* base.css */
.foo {
color: red;
}
.bar {
font-size: 1rem;
}
/* base.desktop.css */
.@media screen and (min-width: 1024px) {
.foo {
color: green;
}
.bar {
font-size: 2rem;
}
}
/* base.desktop.css */
.@media screen and (min-width: 1024px) {
.foo {
color: green;
}
.bar {
font-size: 2rem;
}
}
Performance gain
Having two files means that devices with a resolution lower than what is specified in the media query will still download the resource, but the resource itself will not be render blocking since the browser knows that the resource doesn't need to be applied, and sets its priority level to lowest.
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Example</title>
<link rel="stylesheet" href="/css/optimised/base.min.css" />
<link
rel="stylesheet"
media="screen and (min-width:1024px)"
href="/css/optimised/base-desktop.min.css"
/>
</head>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Example</title>
<link rel="stylesheet" href="/css/optimised/base.min.css" />
<link
rel="stylesheet"
media="screen and (min-width:1024px)"
href="/css/optimised/base-desktop.min.css"
/>
</head>
Summary
I think this paragraph copied from their README sums it up quite nicely:
"If page speed is important to you chances are high you're already doing code splitting. If your CSS is built mobile-first (in particular if using a framework such as Bootstrap or Foundation) chances are also high you're loading more CSS than the current viewport actually needs."