Lazy-loading CSS in your AngularJS app

Gerard Sans
Jan 29, 2015 · 4 min read

Download and inject stylesheets on demand using $route.resolve

Follow me on Twitter for latest updates @gerardsans.

Meet the monolithic stylesheet

It’s common practice to use one big CSS file for the whole application. This file is usually the result of various build steps: compilation, concatenation and minification. Tools such as Gulp or Grunt are great at this.

Relying on one big stylesheet is all good and fine for small projects but what happens when the website keeps growing and more rules are added to it? As you keep adding new sections and components, it gets bigger and bigger. One day it hits your desk… The first visit to your app is taking few seconds to load… You dig a little into it and find that there is a big monolithic CSS sitting in your browser.

What options are there for you now? Well, you clearly have to split your CSS into separate files. A sensible option would be to make a stylesheet for the different sections of your application.

This is just one of the reasons why you would want to cut down on CSS. Here’s some other scenarios why you should lazy-load your stylesheets:

In Angular your routes are a good place to start when chopping up your application into sections. Each route already loads its corresponding template and attaches the controller. It would make sense to also load stylesheets this way, but unfortunately that’s not supported. You could inject CSS into your template but then you will be missing out on browser caching and making your templates bigger.

Splitting CSS files using $route.resolve

In order to inject our CSS file while navigating to a new route we will use $route.resolve. We are going to use resolve in a way that navigation will only happen after we have injected our CSS. See $routeProvider.when() for more details.

We moved the actual code to a factory Service called injectCSS that contains a function set(id, url) returning a promise. This is the actual implementation of the service.

This code takes ideas from different sources and adds some personal choices in. See VIISON/RequireCSS and stackoverflow.

In order to inject our CSS we:

In case the CSS fails to load, Eg. network failure, it will keep on going after the browser adds an entry on styleSheets.


While working on the final solution I found out about a couple of things I didn’t know before:

Use this code with precaution as it has not been tested on all browsers.


Find an online workbench I used to try different configurations here. Have any questions? Ping me on Twitter @gerardsans.

Special mention

Thanks Gert Hengevelt for kindly reviewing this post and publishing it at Opinionated AngularJS.

Opinionated AngularJS

Practical tips and best practices for developing AngularJS…

Opinionated AngularJS

Practical tips and best practices for developing AngularJS applications

Gerard Sans

Written by

Developer Advocate | ex @AWSCloud | Just be AWSome | MC Speaker Trainer Community Leader | @fullstackcon @ReactiveConf @ngcruise @UphillConf

Opinionated AngularJS

Practical tips and best practices for developing AngularJS applications