Advanced Invoice Layout Extension
This Magento Extension offers customizable templates for PDF invoices, shipments and creditmemos that can be send via email to your customers.
learn moreMagento/OpenMage has a default feature to merge all CSS files into one which was implemented back in the old days to reduce HTTP requests and therewith improve the performance for the client. Nowadays with HTTP/2 (or even HTTP/3) the number of requests is not that important anymore (and on the contrary a certain number of parallel asset downloads should be preferred), but there are many other ways the CSS asset delivery can be improved in Magento. Let's see how!
Chris / / last updated onThis blog post is a follow-up of my original description of the perfect Magento frontend in 2023. In that previous post I described several measures to improve the CSS in the Magento frontend like Critical Path optimization or the use of utility-based CSS classes which are all very important things.
Now we want to have a look at how to optimize CSS delivery by improving asset minification.
You may ask why it is still beneficial to minify the CSS files at all. Nowadays browsers and webservers like Apache, nginx or Litespeed are able to compress content via gzip
or brotli
before transmission very effectively.
But netherless by minifying and reducing the amount of CSS code on our side we are able to influence the performance even more than simply compressing files: imagine for example code comments which can be removed, rewrite and combine CSS statements to use less selectors/code and remove unused CSS selectors.
In addition optimizing CSS is very important especially for the Critical Path CSS as this influences all relevant performance metrics in Lighthouse like TTFB or LCP. CSS is one of the few elements that the browser definitely requires as early as possible in order to properly display your website. That's why the browser considers CSS as a blocking resource.
And of course the best code is the one that is not written (or not shipped to customer)!
I used the CSS pre-processor Sass for years extensively and liked it very much. The number one reason for this was nesting, so vanilla CSS was not able to do things like this which is absolutely required for component-based styling:
.card {
.header {
font-weight: bold;
}
}
Besides that there are many more useful Sass features like mixins, variables, calculations, etc. that made the overhead of compiling the Sass language into CSS a no-brainer.
But nowadays also the CSS world is not at a halt and we have lots of exciting new features in the CSS standard that allows to skip the additional pre-processing step in the build pipeline.
The main benefit of using a CSS post-processor instead of pre-processors: I favor to work with the pure CSS standard and getting to know upcoming CSS features as early as possible instead of learning a different pre-processor language.
Of course not all Sass features can be replicated in plain vanilla CSS that's why post-processors like the most popular PostCSS come into play.
In addition there is also the history-long problem of thousands of different browser versions and their implementation status of these CSS features. So it is also mainly a question of which browsers do you want to support for your users.
The following table shows my most-used Sass features together with their vanilla CSS equivalents (the same comparison which I already did for JavaScript as well):
Sass Feature | CSS Equivalent |
---|---|
Variables like $_color-dark: #000 |
CSS Variables with var(--color-dark) |
Mixins with @include svg-icon() |
PostCSS Mixin-Plugin using @mixin svg-icon |
Calculations | CSS calc() function |
For this purpose I can recommend the extension Aoe_JsCssTstamp which basically improves 2 things compared to original Magento behaviour:
s.2fd49f2ddcfae8a2536d440318d4f7cf.css
. This makes cache invalidation e.g. in a content delivery
network (CDN) or end user browser very easy.In general I would aim for generating only a single CSS file in our CSS asset pipeline for several reasons:
If we have versioned our assets (see point 1. above) we are able to improve the browser caching and set the maximum cache time of one year. This can be done by setting the following header, e.g. via .htaccess
file:
Cache-Control: max-age=31536000,immutable
This simply tells the browser that the asset won't be changed and it can cache it for a very long time. Every time we deploy a new version of the CSS file, a new version string is generated and the filename gets changed so the browser recognizes the change.
More useful tips on using cache headers can be found in this great article about best practices.
With the help of the second point we can build a local minification pipeline and then store the generated minified CSS files in a folder like minified/css
. Then we can configure the extension to use that folder for our minified versions. Keep in mind that the folder structure below minified/css
has to match the one in the skin
folder.
For the build pipeline I simply use grunt, but any other tool or simple script is also possible. First we have to install some dependencies:
npm i --save-dev grunt grunt-contrib-cssmin grunt-purgecss
In the Gruntfile
I simply use 2 tasks. The first one is the minification of the CSS files:
cssmin: {
skin_css: {
files: [{
expand: true,
cwd: 'src/vianetz/theme/src/',
src: ['skin/frontend/default/vianetz/**/*.css', '!**/*.min.css', '!**/_*.css'],
dest: 'htdocs/minified/css',
ext: '.min.css'
}]
}
},
The second task is the purging. Therefore I use the tool PurgeCSS which allows to scan HTML content (Magento's .phtml
template files) and CSS files and remove which CSS selectors are not in use. You can configure which selectors should not be purged even using regex.
In order not to purge CSS selectors that are in use in Magento CMS Blocks or Pages, there are several possibilities to choose from:
data/cms_blocks_pages_live.csv
and include that as content parameter for PurgeCSSSo this is the resulting sample Gruntfile.js
part:
purgecss: {
minified_css: {
options: {
content: ['./htdocs/app/design/frontend/base/default/template/**/*.phtml', './src/vianetz/**/*.phtml', './data/cms_blocks_pages_live.csv'],
dynamicAttributes: ["aria-selected"],
safelist: {
'standard': [
'kbd',
'blockquote'
],
'deep': [
/^body.*/,
/^address-select/,
/^checkout-step-*/
]
}
},
files: [{
expand: true,
src: ['htdocs/minified/css/skin/frontend/default/vianetz/css/**/*.min.css'],
dest: '.'
}]
}
}
By using this simple asset minification pipeline I was able to reduce the CSS size of the homepage of vianetz.com by nearly 30%. You're right the configuration for the purging is a bit tricky as you have to take care that no selectors are missed. So it takes some time to tweak the PurgeCSS safelist
config but a reduction of nearly a third of shipped CSS is definitely worth it.
Of course this heavily depends on your used CSS but as there are a lot of CSS frameworks like Bootstrap etc. used out there, the possibility is high that the percentage is a big one. So you should definitely try it!
After we have now reduced the CSS file sizes to a maximum, in one of the next blog posts we will have a look at how we can further improve CSS delivery by using the very interesting HTTP/2 Early Hints feature.
Post Comments to "Optimize CSS Styles in Magento"