Magento Stack Exchange is a question and answer site for users of the Magento e-Commerce platform. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I'm trying to load CSS files async, I've managed to load all the JS async by adding the param async to some xml files but I do not find where do I need to change the xml files.

share|improve this question
    
How much CSS do you have that can wait until the page has fully loaded before being processed? A standard Magento store is unlikely to have any ... – Ben Lessani - Sonassi Oct 1 '15 at 17:22
    
a lot, I have a lot of plugins, why? – Victor Oct 1 '15 at 19:17
    
Well the point being that why would you load CSS at all if it wasn't required? You don't delay the loading of assets if they aren't required, you just don't load them. – Ben Lessani - Sonassi Oct 1 '15 at 22:19
    
they are required, of course. – Victor Oct 1 '15 at 23:44

There is a way to do this that is not completely backwardly compatible (IE doesn't support it, and it comes with downsides).

In short, you need to do the following:

  • Move the CSS into the beginning of the <body> tag
  • Mark the CSS as lazyload, e.g. <link rel="stylesheet" href="style.css" lazyload>

Most modern browsers will async the CSS for one of the previous two preconditions.

However, this is probably not desirable. There are downsides:

  • FOUT
  • Maintenance is problematic as to locate this in a sane way you're likely rewriting a module to do so

Best of luck!

share|improve this answer
    
async won't work, right? – Victor Oct 1 '15 at 20:32

There is no de facto way of loading css async "out the box" without using some kind of js loader to do it.

http://codepen.io/Tigt/post/async-css-without-javascript is an excellent article on this subject but the long and short of it is you would need to add a new block before the footer that either allows css to be added directly or through a javascript loader.

share|improve this answer

I am implementing this right now, using https://github.com/filamentgroup/loadCSS.

Split CSS into initial CSS and async CSS

My site runs the Magento RWD theme. Stylesheets are edited in SCSS and compiled to one file, styles.css. The SCSS to CSS transformation had to be redefined in order to create two new output files: styles-initial.css, which would load the old-fashioned way, and styles-async.css, which would be loaded asynchronously using the JavaScript function as shown below.

styles-initial.css contains only enough information to display the site homepage without having a FOUT. Essentially the framework, the header, and the homepage.

styles-async.css contains everything else and is much bigger than the initial CSS.

Installation of loadCSS.js

loadCSS.js is placed in /js/lib somewhat arbitrarily; you could put it in /skin/frontend/x/y/js if that makes more sense for you.

Including loadCSS in theme

In app/design/frontend/x/y/layout/page.xml, I added inside the head block:

<action method="addJs"><script>lib/loadCSS.js</script></action>

Calling loadCSS

At the beginning of /skin/frontend/x/y/js/app.js I added the lines:

// Load CSS
loadCSS('skin/frontend/x/y/css/styles-async.css');

Although it would make more sense to inline this in the HTML head, as shown below. That way, the browser has one less HTTP request it needs to make.

A more systematic approach

A better implementation of this would be to create a new method, AddAsyncCss that can encode the names of a stylesheet into the HTML output in some way that app.js can read from the HTML which stylesheets to load asynchronously.

A more systematic approach that doesn't include making a module

We can probably do even better and do this in a new block template stored in app/design/frontend/x/y/template/page/html/. That way, we don't have to go through the hassle of creating a new module, or a core override in app/code/local/Mage.

Yet another improvement: Follow Filament Group's Recommendation

This is probably as close as we can get to a correct way, until a standard for asynchronous CSS has been established.

From http://filamentgroup.github.io/loadCSS/test/preload.html:

<html>
    <head>
        <link rel="preload" href="test/slow-css.php" as="style" onload="this.rel='stylesheet'">
        <noscript><link rel="stylesheet" href="test/slow-css.php"></noscript>
        <script>
            /*! loadCSS: load a CSS file asynchronously. [c]2016 @scottjehl, Filament Group, Inc. Licensed MIT */
            // 77 lines of JavaScript

            /* CSS rel=preload polyfill. Depends on loadCSS function */
            // 34 lines of JavaScript
        <script>
        <style>
            /* Some initial CSS styles */
        </style>
        <script></script><!-- here to ensure a non-blocking load still occurs in IE and Edge, even if scripts follow loadCSS in head -->
    </head>
    <body>
...

In the example, slow-css.php is a PHP script that waits 5 seconds, then outputs CSS code. This is a good opportunity for us to remind ourselves that PHP does not have to be used to generate HTML. This was done in the demo so that when the asynchronous CSS finished loading, the colors on the page would change.

The ideal Magento-based solution

would be a module that implements the above with two new method calls, addAsyncCss and addInlineCss. They would be called from layout XML files in the head block, the same way that addCss and addJs are used.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.