---
title: "Front-End Performance: Styles"
date: "2019-03-31T01:07:39+00:00"
summary:
image:
type: "article"
url: "/acquia-cloud-platform/help/91916-front-end-performance-styles"
id: "85c40084-2083-40cc-a62f-b13f28eb6db0"
---

The quest for improved page-load speed and website performance is constant. And it should be. The speed and responsiveness of a website have a significant impact on conversion, search engine optimization, and the digital experience in general.

In [part one](https://www.acquia.com/gb/blog/front-end-performance-strategy-image-handling) of this [series](https://www.acquia.com/blog/front-end-performance-strategy), we established the importance of front-end optimization on performance, and discussed how properly-handled images can provide a significant boost toward that goal. In this second installment, we'll continue our enhancements, this time by tackling CSS optimization.

We'll consider general best practices from both a front-end developer's and a themer's point of view. Remember, as architects and developers, it's up to us to inform stakeholders of the impacts of their choices, offer compromises where we can, and implement in smart and responsible ways.

Styles
------

Before we dive into optimizing our CSS, we need to understand how Drupal's performance settings for aggregation work. We see developers treating this feature like a black box, turning it on without fully grokking its voodoo. Doing so misses two important strategic opportunities: 1. Controlling where styles are added in the head of our document, and 2. Regulating how many different aggregates are created.

Styles can belong to one of three groups:

*   System - Drupal core
*   Default - Styles added by modules
*   Theme - Styles added in your theme

Drupal aggregates styles from each group into a single sheet for that group, meaning you'll see at minimum three CSS files being used for your page. Style sheets added by inclusion in a theme's â.info' file or a module's â.info' file automatically receive a âtrue' value for the _every\_page_ flag in the options array, which wraps them into our big three aggregates.

Styles added using [drupal\_add\_css](https://api.drupal.org/api/drupal/includes%21common.inc/function/drupal_add_css/7) automatically have the _every\_page_ flag set to âfalse.' These style sheets are then combined separately, by group, forming special one-off aggregate style sheets for each page.

When using _drupal\_add\_css_, you can use the optional âoptions' array to explicitly set the _every\_page_ flag to âtrue.' You can also set the group it belongs to and give it a weight to move it up or down within a group.

    <?php 
     drupal_add_css(drupal_get_path('module', 'custom-module') . '/css/custom-module.css', array('group' => CSS_DEFAULT, 'every_page' => TRUE));
    ?>

Style sheets added using Drupal's [_attached_](https://www.google.com/url?q=https%3A%2F%2Fapi.drupal.org%2Fapi%2Fdrupal%2Fincludes!common.inc%2Ffunction%2Fdrupal_process_attached%2F7&sa=D&sntz=1&usg=AFQjCNH932Z-m75UURHzbe33Y7HS3odG8g) property aren't aggregated unless they have the _every\_page_ flag set to âtrue.'

### Favoring _every\_page: true_

Styles added with the _every\_page_ flag set to _âfalse'_ (CSS added via _drupal\_add\_css_ without the true option, or without the option set at all, or added using the attached property) will only load on the pages that use the function that attaches, or adds, that style sheet to the page, so you have a smaller payload to build the page. However, on pages that do use the function that adds or attaches the style sheet with _every\_page: âfalse'_, an additional HTTP request is required to build that page. The additional requests are for the one-off aggregates per group, per page.

In more cases than not, I prefer loading an additional 3kb of styling in my main aggregates that will be downloaded once and then cached locally, rather than create a new aggregate that triggers a separate HTTP request to make up for what's not in the main aggregates.

Additionally, turning on aggregation causes Drupal to compress our style sheets, serving them Gzipped to the browser. Gzipped assets are [70%90% smaller](https://www.google.com/url?q=https%3A%2F%2Fdevelopers.google.com%2Fweb%2Ffundamentals%2Fperformance%2Foptimizing-content-efficiency%2Foptimize-encoding-and-transfer) than their uncompressed counterparts. That's a 500kb CSS file being transferred in a 100kb package to the browser.

### Preprocessing isn't a license for inefficiency

I love preprocessing my CSS. I use SASS, written in SCSS syntax, and often utilize Compass for its set of mixins and for compiling. But widespread adoption of preprocessing has led to compiled CSS files that tip the 1Mb limit ([which is way over the average](http://www.google.com/url?q=http%3A%2F%2Fwww.sitepoint.com%2Faverage-page-weight-increases-15-2014%2F&sa=D&sntz=1&usg=AFQjCNHwQe8Squ20KbIUftjwZa41LlsSkA)), or break the [IE selector limit of 4095](http://www.google.com/url?q=http%3A%2F%2Fblogs.msdn.com%2Fb%2Fieinternals%2Farchive%2F2011%2F05%2F14%2F10164546.aspx&sa=D&sntz=1&usg=AFQjCNFK-Ud6cyFf2kp_21XeLMJDVj5nKA). Some of this can be attributed to Drupal's notorious nesting of divs (ugly mark-up often leads to ugly CSS), but a lot of it is just really poor coding habits.

The number one culprit I've come across is [over nesting of selectors](http://www.google.com/url?q=http%3A%2F%2Fthesassway.com%2Fbeginner%2Fthe-inception-rule%23css-selector-nightmare&sa=D&sntz=1&usg=AFQjCNFu-pQpVFsYHPRS49PlE9djnPnzpw) in SASS files. People traverse the over nested DOM created by Drupal with SASS and spit out compiled CSS rules using [descendant](https://www.google.com/url?q=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FWeb%2FCSS%2FDescendant_selectors&sa=D&sntz=1&usg=AFQjCNHJ2KiUlSaLILJWZL_4gOmXNrcVkg) selectors that go five (sometimes even more) levels deep.

![Text document titled "Day 01 - Configuration Management in D8" with objectives, exercises, a tutorial link, and additional resources for Drupal 8.](https://acquia.widen.net/content/7d6b8c37-b377-45f7-9a20-7c14702f40cc/web/url_a3965bc17b2106275c07867ba3f52144.png)

I took the above example from the SASS inception page, linked above, and cleaned it up to what it should probably be:

![PHP code snippet defining a class "LastMigrationScenario" with functions to construct and delete leftover stubs from a database.](https://acquia.widen.net/content/2491aa67-a228-40a7-a91f-a4ec98362e7d/web/url_6b33baca6083f2c3aca0bad863804e5d.png)

The result? It went from 755 bytes to 297 bytes, a 60% reduction in size. That came from just getting rid of the extra characters added by the excess selectors. Multiply the savings by the 30 partials or so, and it's a pretty substantial savings in compiled CSS size.

Besides the size savings, the number and type of selectors directly impact the amount of time a browser takes to process your style rules. Browsers read styles from right to left, matching the rightmost key selector first, then working left, disqualifying items as it goes. Mozilla wrote a great [efficient CSS reference](https://www.google.com/url?q=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FWeb%2FGuide%2FCSS%2FWriting_efficient_CSS&sa=D&sntz=1&usg=AFQjCNGd2w3b6FyweEC-CIgLK9eZanenhw) years ago that is still relevant.

Conclusion
----------

Once again we've demonstrated how sloppy front-end implementations can seriously hamper Drupal's back-end magic. By favoring style sheet aggregation and reining in exuberant preprocessing, we can save the browser a lot of work.

In our next, and final, installment in this series, we'll expand our front-end optimization strategies even further, to include scripts.