{"id":69165,"date":"2019-08-09T04:20:33","date_gmt":"2019-08-09T11:20:33","guid":{"rendered":"http:\/\/www.taterboy.com\/blog\/2019\/08\/handling-unused-css-in-sass-to-improve-performance\/"},"modified":"2019-08-09T04:20:33","modified_gmt":"2019-08-09T11:20:33","slug":"handling-unused-css-in-sass-to-improve-performance","status":"publish","type":"post","link":"https:\/\/www.taterboy.com\/blog\/2019\/08\/handling-unused-css-in-sass-to-improve-performance\/","title":{"rendered":"Handling Unused CSS In SASS To Improve Performance"},"content":{"rendered":"<link rel=\"canonical\" href=\"https:\/\/www.smashingmagazine.com\/2019\/08\/handling-unused-css-sass-performance\/\"><title>Handling Unused CSS In SASS To Improve Performance<\/title><\/p>\n<article>\n<header>\n<h1>Handling Unused CSS In SASS To Improve Performance<\/h1>\n<address>Luke Harrison<\/address>\n<p>                  <time datetime=\"2019-08-09T12:30:59+02:00\">2019-08-09T12:30:59+02:00<\/time><time datetime=\"2019-08-09T11:08:44+00:00\">2019-08-09T11:08:44+00:00<\/time><\/header>\n<p>In modern front-end development, developers should aim to write CSS which is scalable and maintainable. Otherwise, they risk losing control over specifics such as the cascade and selector specificity as the codebase grows and more developers contribute.<\/p>\n<p>One way this can be achieved is through the use of methodologies such as Object-Oriented CSS (OOCSS), which rather than organizing CSS around page context, encourages separating structure (grid systems, spacing, widths, etc.) from decoration (fonts, brand, colors, etc.).<\/p>\n<p>So CSS class names such as:<\/p>\n<ul>\n<li><code>.blog-right-column<\/code><\/li>\n<li><code>.latest_topics_list<\/code><\/li>\n<li><code>.job-vacancy-ad<\/code><\/li>\n<\/ul>\n<p>Are replaced with more reusable alternatives, which apply the same CSS styles, but aren\u2019t tied to any particular context:<\/p>\n<ul>\n<li><code>.col-md-4<\/code><\/li>\n<li><code>.list-group<\/code><\/li>\n<li><code>.card<\/code><\/li>\n<\/ul>\n<p>This approach is commonly implemented with the help of a SASS framework such as <a href=\"https:\/\/getbootstrap.com\/\">Bootstrap<\/a>, <a href=\"https:\/\/foundation.zurb.com\/\">Foundation<\/a>, or increasingly more often, a bespoke framework which can be shaped to better fit the project.<\/p>\n<div data-component=\"FeaturePanel\" data-audience=\"non-subscriber\" data-remove=\"true\"><\/div>\n<p>So now we\u2019re using CSS classes cherry-picked from a framework of patterns, UI components and utility classes. The below example illustrates a common grid system built using Bootstrap, which stacks vertically, then once the md breakpoint is reached, switches to a 3 column layout.<\/p>\n<pre><code><div class=\"container\">\n   <div class=\"row\">\n      <div class=\"col-12 col-md-4\">Column 1<\/div>\n      <div class=\"col-12 col-md-4\">Column 2<\/div>\n      <div class=\"col-12 col-md-4\">Column 3<\/div>\n   <\/div>\n<\/div><\/code><\/pre>\n<p>Programmatically generated classes such as <code>.col-12<\/code> and <code>.col-md-4<\/code> are used here to create this pattern. But what about <code>.col-1<\/code> through <code>.col-11<\/code>, <code>.col-lg-4<\/code>, <code>.col-md-6<\/code> or <code>.col-sm-12<\/code>? These are all examples of classes which will be included in the compiled CSS stylesheet, downloaded and parsed by the browser, despite not being in use.<\/p>\n<p>In this article, we\u2019ll start by exploring the impact unused CSS can have on page load speeds. We\u2019ll then touch upon some existing solution for removing it from stylesheets, following up with my own SASS oriented solution.<\/p>\n<h3>Measuring The Impact Of Unused CSS Classes<\/h3>\n<p>Whilst I adore Sheffield United, the mighty blades, their website\u2019s CSS is bundled into a single 568kb minified file, which comes to 105kb even when gzipped. That seems like a lot.<\/p>\n<figure><a href=\"https:\/\/i0.wp.com\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/996494e9-90d7-4c17-90d3-6013d9941c79\/sheffield-united-website.png?ssl=1\"><\/p>\n<p>    <img data-recalc-dims=\"1\" decoding=\"async\" srcset=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/08\/sheffield-united-website.png 400w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_800\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/996494e9-90d7-4c17-90d3-6013d9941c79\/sheffield-united-website.png 800w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1200\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/996494e9-90d7-4c17-90d3-6013d9941c79\/sheffield-united-website.png 1200w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1600\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/996494e9-90d7-4c17-90d3-6013d9941c79\/sheffield-united-website.png 1600w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_2000\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/996494e9-90d7-4c17-90d3-6013d9941c79\/sheffield-united-website.png 2000w\" src=\"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/08\/sheffield-united-website.png?w=900\" sizes=\"100vw\" alt=\"\"><\/a><figcaption>\n      This is <a href=\"https:\/\/www.sufc.co.uk\/\">Sheffield United\u2019s website<\/a>, my local Football team (that\u2019s Soccer for you lot over in the colonies ??). (<a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/996494e9-90d7-4c17-90d3-6013d9941c79\/sheffield-united-website.png\">Large preview<\/a>)<br \/>\n    <\/figcaption><\/figure>\n<p>Shall we see how much of this CSS is actually used by on their homepage? A quick Google search reveals plenty of online tools up to the job, but I prefer to use the <em>coverage<\/em> tool in Chrome, which can be run straight from Chrome\u2019s DevTools. Let\u2019s give it a whirl.<\/p>\n<figure><a href=\"https:\/\/i0.wp.com\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/ed7c7032-956d-432f-a951-99eb859d563d\/unused-css.png?ssl=1\"><\/p>\n<p>    <img data-recalc-dims=\"1\" decoding=\"async\" srcset=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/08\/unused-css.png 400w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_800\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/ed7c7032-956d-432f-a951-99eb859d563d\/unused-css.png 800w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1200\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/ed7c7032-956d-432f-a951-99eb859d563d\/unused-css.png 1200w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1600\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/ed7c7032-956d-432f-a951-99eb859d563d\/unused-css.png 1600w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_2000\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/ed7c7032-956d-432f-a951-99eb859d563d\/unused-css.png 2000w\" src=\"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/08\/unused-css.png?w=900\" sizes=\"100vw\" alt=\"\"><\/a><figcaption>\n      The quickest way to access the coverage tool in Developer Tools is to use the keyboard shortcut Control+Shift+P or Command+Shift+P (Mac) to open the command menu. In it, type <code>coverage<\/code>, and select the &#8216;Show Coverage&#8217; option. (<a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/ed7c7032-956d-432f-a951-99eb859d563d\/unused-css.png\">Large preview<\/a>)<br \/>\n    <\/figcaption><\/figure>\n<p>The results show that only <em>30kb<\/em> of CSS from the 568kb stylesheet is used by the homepage, with the remaining 538kb relating to the styles required for the rest of the website. This means a whopping <strong>94.8%<\/strong> of the CSS is unused.<\/p>\n<figure><a href=\"https:\/\/i0.wp.com\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/6aaf2c56-5ba3-49ec-826e-509946976aa3\/waiting-css.png?ssl=1\"><\/p>\n<p>    <img data-recalc-dims=\"1\" decoding=\"async\" srcset=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/08\/waiting-css.png 400w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_800\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/6aaf2c56-5ba3-49ec-826e-509946976aa3\/waiting-css.png 800w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1200\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/6aaf2c56-5ba3-49ec-826e-509946976aa3\/waiting-css.png 1200w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1600\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/6aaf2c56-5ba3-49ec-826e-509946976aa3\/waiting-css.png 1600w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_2000\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/6aaf2c56-5ba3-49ec-826e-509946976aa3\/waiting-css.png 2000w\" src=\"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/08\/waiting-css.png?w=900\" sizes=\"100vw\" alt=\"\"><\/a><figcaption>\n      You can see timings like these for any asset in Chrome in Developer Tools via Network -> Click on your asset -> Timing tab. (<a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/6aaf2c56-5ba3-49ec-826e-509946976aa3\/waiting-css.png\">Large preview<\/a>)<br \/>\n    <\/figcaption><\/figure>\n<p>CSS is part of a webpage\u2019s critical rendering path, which involves all the different steps a browser must complete before it can begin page render. This makes CSS a render-blocking asset.<\/p>\n<p>So with this in mind, when loading Sheffield United\u2019s website using a good 3G connection, it takes a whole 1.15s before the CSS is downloaded and page rendering can begin. This is a problem.<\/p>\n<p>Google has recognized this as well. When running a Lighthouse audit, online or via your browser, any potential load time and filesize savings which could be made by removing unused CSS are highlighted.<\/p>\n<figure><a href=\"https:\/\/i0.wp.com\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/579a8cce-e87c-452b-98dd-7d3e6fb57780\/lighthouse.png?ssl=1\"><\/p>\n<p>    <img data-recalc-dims=\"1\" decoding=\"async\" srcset=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/08\/lighthouse.png 400w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_800\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/579a8cce-e87c-452b-98dd-7d3e6fb57780\/lighthouse.png 800w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1200\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/579a8cce-e87c-452b-98dd-7d3e6fb57780\/lighthouse.png 1200w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1600\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/579a8cce-e87c-452b-98dd-7d3e6fb57780\/lighthouse.png 1600w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_2000\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/579a8cce-e87c-452b-98dd-7d3e6fb57780\/lighthouse.png 2000w\" src=\"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/08\/lighthouse.png?w=900\" sizes=\"100vw\" alt=\"\"><\/a><figcaption>\n      In Chrome (and Chromium Edge), you can right Google Lighthouse audits by clicking on the Audit tab in developer tools. (<a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/579a8cce-e87c-452b-98dd-7d3e6fb57780\/lighthouse.png\">Large preview<\/a>)<br \/>\n    <\/figcaption><\/figure>\n<h3>Existing Solutions<\/h3>\n<p>The goal is to determine which CSS classes aren\u2019t required and remove them from the stylesheet. Existing solutions are available which attempt to automate this process. They can typically be used via a Node.js build script, or via task runners such as Gulp. These include:<\/p>\n<ul>\n<li><a href=\"https:\/\/github.com\/uncss\/uncss\">UNCSS<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/purifycss\/purifycss\">PurifyCSS<\/a><\/li>\n<li><a href=\"https:\/\/www.purgecss.com\/\">PurgeCSS<\/a><\/li>\n<\/ul>\n<p>These generally work in a similar way:<\/p>\n<ol>\n<li>On bulld, the website is accessed via a headless browser (Eg: <a href=\"https:\/\/github.com\/GoogleChrome\/puppeteer\">puppeteer<\/a>) or DOM emulation (Eg: <a href=\"https:\/\/github.com\/jsdom\/jsdom\">jsdom<\/a>).<\/li>\n<li>Based on the page\u2019s HTML elements, any unused CSS is identified.<\/li>\n<li>This is removed from the stylesheet, leaving only what is needed.<\/li>\n<\/ol>\n<p>Whilst these automated tools are perfectly valid and I\u2019ve used many of them across a number of commercial projects successfully, I\u2019ve encountered a few drawbacks along the way which are worth sharing:<\/p>\n<ul>\n<li>If class names contain special characters such as \u2018@\u2019 or \u2018\/\u2019, these may not be recognized without writing some custom code. I use <a href=\"https:\/\/csswizardry.com\/2015\/08\/bemit-taking-the-bem-naming-convention-a-step-further\/\">BEM-IT<\/a> by Harry Roberts, which involves structuring class names with responsive suffixes like: <code>u-width-6\/12@lg<\/code>, so I\u2019ve hit this issue before.<\/li>\n<li>If the website uses automated deployment, it can slow down the build process, especially if you have lots of pages and lots of CSS.<\/li>\n<li>Knowledge about these tools needs to be shared across the team, otherwise there may be confusion and frustration when CSS is mysteriously absent in production stylesheets.<\/li>\n<li>If your website has many 3rd party scripts running, sometimes when opened in a headless browser, these don\u2019t play nicely and can cause errors with the filtering process. So typically you have to write custom code to exclude any 3rd party scripts when a headless browser is detected, which depending on your setup, may be tricky.<\/li>\n<li>Generally, these kind of tools are complicated and introduce a lot of extra dependencies to the build process. As is the case with all 3rd party dependencies, this means relying on somebody else&#8217;s code.<\/li>\n<\/ul>\n<p>With these points in mind, I posed myself a question:<\/p>\n<blockquote><p>Using just SASS, is it possible to better handle the SASS we compile so any unused CSS can be excluded, without resorting to just crudely deleting the source classes in the SASS outright?<\/p><\/blockquote>\n<p><strong>Spoiler alert:<\/strong> <em>The answer is yes. Here\u2019s what I\u2019ve come up with.<\/em><\/p>\n<div><\/div>\n<h3>SASS Oriented Solution<\/h3>\n<p>The solution needs to provide a quick and easy way to cherry-pick what SASS ought to be compiled, whilst being simple enough that it doesn\u2019t add any more complexity to the development process or prevent developers from taking advantage of things like programmatically generated CSS classes.<\/p>\n<p>To get started, there\u2019s a repo with build scripts and a few sample styles which you can clone from <a href=\"https:\/\/github.com\/WebDevLuke\/handlingunusedcss\/tree\/start\">here<\/a>.<\/p>\n<p><strong>Tip:<\/strong> If you get stuck, you can always cross-reference with the <a href=\"https:\/\/github.com\/WebDevLuke\/handlingunusedcss\/tree\/master\">completed version on master branch<\/a>.<\/p>\n<p><code>cd<\/code> into the repo, run <code>npm install<\/code> and then <code>npm run build<\/code> to compile any SASS into CSS as required. This should create a 55kb css file in the dist directory.<\/p>\n<p>If you then open <code>\/dist\/index.html<\/code> in your web browser, you should see a fairly standard component, which on click expands to reveal some content. You can also view this <a href=\"https:\/\/webdevluke.github.io\/handlingunusedcss\/dist\/index2.html\">here<\/a>, where real network conditions will be applied, so you can run your own tests.<\/p>\n<figure><a href=\"https:\/\/i0.wp.com\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/a87f2f54-8a55-449d-856e-4e5918e8961f\/expander-component.png?ssl=1\"><\/p>\n<p>    <img data-recalc-dims=\"1\" decoding=\"async\" srcset=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/08\/expander-component.png 400w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_800\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/a87f2f54-8a55-449d-856e-4e5918e8961f\/expander-component.png 800w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1200\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/a87f2f54-8a55-449d-856e-4e5918e8961f\/expander-component.png 1200w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1600\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/a87f2f54-8a55-449d-856e-4e5918e8961f\/expander-component.png 1600w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_2000\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/a87f2f54-8a55-449d-856e-4e5918e8961f\/expander-component.png 2000w\" src=\"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/08\/expander-component.png?w=900\" sizes=\"100vw\" alt=\"\"><\/a><figcaption>\n      We\u2019ll use this expander UI component as our test subject when developing the SASS-oriented solution for handling unused CSS. (<a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/a87f2f54-8a55-449d-856e-4e5918e8961f\/expander-component.png\">Large preview<\/a>)<br \/>\n    <\/figcaption><\/figure>\n<h4>Filtering At The Partials Level<\/h4>\n<p>In a typical SCSS setup, you\u2019re likely going to have a single manifest file (eg: <code>main.scss<\/code> in the repo), or one per page (eg: <code>index.scss<\/code>, <code>products.scss<\/code>, <code>contact.scss<\/code>) where framework partials are imported. Following OOCSS principles, those imports may look something like this:<\/p>\n<h5>Example 1<\/h5>\n<pre><code>\/*\nUndecorated design patterns\n*\/\n\n@import 'objects\/box';\n@import 'objects\/container';\n@import 'objects\/layout';\n\n\/*\nUI components\n*\/\n\n@import 'components\/button';\n@import 'components\/expander';\n@import 'components\/typography';\n\n\/*\nHighly specific helper classes\n*\/\n\n@import 'utilities\/alignments';\n@import 'utilities\/widths';<\/code><\/pre>\n<p>If any of these partials aren\u2019t in use, then the natural way of filtering this unused CSS would be to just disable the import, which would prevent it from being compiled.<\/p>\n<p>For example, if only using the expander component, the manifest would typically look like the below:<\/p>\n<h5>Example 2<\/h5>\n<pre><code>\/*\nUndecorated design patterns\n*\/\n\/\/ @import 'objects\/box';\n\/\/ @import 'objects\/container';\n\/\/ @import 'objects\/layout';\n\n\/*\nUI components\n*\/\n\/\/ @import 'components\/button';\n@import 'components\/expander';\n\/\/ @import 'components\/typography';\n\n\/*\nHighly specific helper classes\n*\/\n\/\/ @import 'utilities\/alignments';\n\/\/ @import 'utilities\/widths';<\/code><\/pre>\n<p>However, as per OOCSS, we\u2019re separating decoration from structure to allow for maximum reusability, so it\u2019s possible the expander could require CSS from other objects, component or utility classes to render correctly. Unless the developer is aware of these relationships by inspecting the HTML, they may not know to import these partials, so not all of the required classes would be compiled.<\/p>\n<p>In the repo, if you look at the expander\u2019s HTML in <code>dist\/index.html<\/code>, this appears to be the case. It uses styles from the box and layout objects, the typography component, and width and alignment utilities.<\/p>\n<h5><code>dist\/index.html<\/code><\/h5>\n<div>\n<pre><code><div class=\"c-expander\">\n   <div class=\"o-box o-box--spacing-small c-expander__trigger c-expander__header\" tabindex=\"0\">\n      <div class=\"o-layout o-layout--fit u-flex-middle\">\n         <div class=\"o-layout__item u-width-grow\">\n            <h2 class=\"c-type-echo\">Toggle Expander<\/h2>\n         <\/div>\n         <div class=\"o-layout__item u-width-shrink\">\n            <div class=\"c-expander__header-icon\"><\/div>\n         <\/div>\n      <\/div>\n   <\/div>\n   <div class=\"c-expander__content\">\n      <div class=\"o-box o-box--spacing-small\">\n       Lorum ipsum\n         <p class=\"u-align-center\">\n            <button class=\"c-expander__trigger c-button\">Close<\/button>\n         <\/p>\n      <\/div>\n   <\/div>\n<\/div><\/code><\/pre>\n<\/div>\n<p>Let\u2019s tackle this problem waiting to happen by making these relationships official within the SASS itself, so once a component is imported, any dependencies will also be imported automatically. This way, the developer no longer has the extra overhead of having to audit the HTML to learn what else they need to import.<\/p>\n<h4>Programmatic Imports Map<\/h4>\n<p>For this dependency system to work, rather than simply commenting in <code>@import<\/code> statements in the manifest file, SASS logic will need to dictate if partials will be compiled or not.<\/p>\n<p>In <code>src\/scss\/settings<\/code>, create a new partial called <code>_imports.scss<\/code>, <code>@import<\/code> it in <code>settings\/_core.scss<\/code>, and then create the following SCSS map:<\/p>\n<h5><code>src\/scss\/settings\/_core.scss<\/code><\/h5>\n<pre><code>@import 'breakpoints';\n@import 'spacing';\n@import 'imports';<\/code><\/pre>\n<h5><code>src\/scss\/settings\/_imports.scss<\/code><\/h5>\n<pre><code>$imports: (\n   object: (\n    'box',\n    'container',\n    'layout'\n   ),\n   component: (\n    'button',\n    'expander',\n    'typography'\n   ),\n   utility: (\n    'alignments',\n    'widths'\n   )\n);<\/code><\/pre>\n<p>This map will have the same role as the import manifest back in <a href=\"https:\/\/www.smashingmagazine.com\/articles\/#example-1\">example 1<\/a>.<\/p>\n<h5>Example 4<\/h5>\n<pre><code>$imports: (\n   object: (\n    \/\/'box',\n    \/\/'container',\n    \/\/'layout'\n   ),\n   component: (\n    \/\/'button',\n    'expander',\n    \/\/'typography'\n   ),\n   utility: (\n    \/\/'alignments',\n    \/\/'widths'\n   )\n);<\/code><\/pre>\n<p>It should behave like a standard set of <code>@imports<\/code> would, in that if certain partials are commented out (like the above), then that code shouldn\u2019t be compiled on build.<\/p>\n<p>But as we\u2019re wanting to import dependencies automatically, we should also be able to ignore this map under the right circumstances.<\/p>\n<div><\/div>\n<h4>Render Mixin<\/h4>\n<p>Let\u2019s start to add some SASS logic. Create <code>_render.scss<\/code> in <code>src\/scss\/tools<\/code>, and then add its <code>@import<\/code> to <code>tools\/_core.scss<\/code>.<\/p>\n<p>In the file, create an empty mixin called <code>render()<\/code>.<\/p>\n<h5><code>src\/scss\/tools\/_render.scss<\/code><\/h5>\n<pre><code>@mixin render() {\n\n}<\/code><\/pre>\n<p>In the mixin, we need to write SASS which does the following:<\/p>\n<ul>\n<li><strong>render()<\/strong><br \/>\u201cHey there <code>$imports<\/code>, fine weather isn\u2019t it? Say, do you have the container object in your map?&#8221;<\/li>\n<li><strong>$imports<\/strong><br \/><code>false<\/code><\/li>\n<li><strong>render()<\/strong><br \/>\u201cThat\u2019s a shame, looks like its won\u2019t be compiled then. How about the button component?\u201d<\/li>\n<li><strong>$imports<\/strong><br \/><code>true<\/code><\/li>\n<li><strong>render()<\/strong><br \/>\u201cNice! That\u2019s the button being compiled then. Say hi to the wife for me.\u201d<\/li>\n<\/ul>\n<p>In SASS, this translates to the following:<\/p>\n<h5><code>src\/scss\/tools\/_render.scss<\/code><\/h5>\n<pre><code>@mixin render($name, $layer) {\n   @if(index(map-get($imports, $layer), $name)) {\n      @content;\n   }\n}<\/code><\/pre>\n<p>Basically, check if the partial is included in the <code>$imports<\/code> variable, and if so, render it using SASS\u2019s <code>@content<\/code> directive, which allows us to pass a content block into the mixin.<\/p>\n<p>We would use it like so:<\/p>\n<h5>Example 5<\/h5>\n<pre><code>@include render('button', 'component') {\n   .c-button {\n      \/\/ styles et al\n   }\n\n   \/\/ any other class declarations\n}<\/code><\/pre>\n<p>Before using this mixin, there\u2019s a small improvement which we can make to it. The layer name (object, component, utility, etc.) is something we can safely predict, so we have an opportunity to streamline things a little.<\/p>\n<p>Before the render mixin declaration, create a variable called <code>$layer<\/code>, and remove the identically named variable from the mixins parameters. Like so:<\/p>\n<h5><code>src\/scss\/tools\/_render.scss<\/code><\/h5>\n<pre><code>$layer: null !default;\n@mixin render($name) {\n   @if(index(map-get($imports, $layer), $name)) {\n      @content;\n   }\n}<\/code><\/pre>\n<p>Now, in the <code>_core.scss<\/code> partials where objects, components and utility <code>@imports<\/code> are located, redeclare these variables to the following values; representing the type of CSS classes being imported.<\/p>\n<h5><code>src\/scss\/objects\/_core.scss<\/code><\/h5>\n<pre><code>$layer: 'object';\n\n@import 'box';\n@import 'container';\n@import 'layout';<\/code><\/pre>\n<h5><code>src\/scss\/components\/_core.scss<\/code><\/h5>\n<pre><code>$layer: 'component';\n\n@import 'button';\n@import 'expander';\n@import 'typography';<\/code><\/pre>\n<h5><code>src\/scss\/utilities\/_core.scss<\/code><\/h5>\n<pre><code>$layer: 'utility';\n\n@import 'alignments';\n@import 'widths';<\/code><\/pre>\n<p>This way, when we use the <code>render()<\/code> mixin, all we have to do is declare the partial name.<\/p>\n<p>Wrap the <code>render()<\/code> mixin around each object, component and utility class declaration, as per the below. This will give you one render mixin usage per partial.<\/p>\n<p>For example:<\/p>\n<h5><code>src\/scss\/objects\/_layout.scss<\/code><\/h5>\n<pre><code>@include render('button') {\n   .c-button {\n      \/\/ styles et al\n   }\n\n   \/\/ any other class declarations\n}<\/code><\/pre>\n<h5><code>src\/scss\/components\/_button.scss<\/code><\/h5>\n<pre><code>@include render('button') {\n   .c-button {\n      \/\/ styles et al\n   }\n\n   \/\/ any other class declarations\n}<\/code><\/pre>\n<p><strong>Note:<\/strong> For <code>utilities\/_widths.scss<\/code>, wrapping the <code>render()<\/code> function around the entire partial will error on compile, as in SASS you can\u2019t nest mixin declarations within mixin calls. Instead, just wrap the <code>render()<\/code> mixin around the <code>create-widths()<\/code> calls, like below:<\/p>\n<div>\n<pre><code>@include render('widths') {\n\n\/\/ GENERATE STANDARD WIDTHS\n\/\/---------------------------------------------------------------------\n\n\/\/ Example: .u-width-1\/3\n@include create-widths($utility-widths-sets);\n\n\/\/ GENERATE RESPONSIVE WIDTHS\n\/\/---------------------------------------------------------------------\n\n\/\/ Create responsive variants using settings.breakpoints\n\/\/ Changes width when breakpoint is hit\n\/\/ Example: .u-width-1\/3@md\n\n@each $bp-name, $bp-value in $mq-breakpoints {\n   @include mq(#{$bp-name}) {\n      @include create-widths($utility-widths-sets, @, #{$bp-name});\n   }\n}\n\n\/\/ End render\n}<\/code><\/pre>\n<\/div>\n<p>With this in place, on build, only the partials referenced in <code>$imports<\/code> will be compiled.<\/p>\n<p>Mix and match what components are commented out in <code>$imports<\/code> and run <code>npm run build<\/code> in the terminal to give it a try.<\/p>\n<h4>Dependencies Map<\/h4>\n<p>Now we\u2019re programmatically importing partials, we can start to implement the dependency logic.<\/p>\n<p>In <code>src\/scss\/settings<\/code>, create a new partial called <code>_dependencies.scss<\/code>, <code>@import<\/code> it in <code>settings\/_core.scss<\/code>, but make sure it\u2019s after <code>_imports.scss<\/code>. Then in it, create the following SCSS map:<\/p>\n<h5><code>src\/scss\/settings\/_dependencies.scss<\/code><\/h5>\n<pre><code>$dependencies: (\n   expander: (\n      object: (\n         'box',\n         'layout'\n    ),\n    component: (\n         'button',\n         'typography'\n    ),\n    utility: (\n         'alignments',\n         'widths'\n    )\n   )\n);<\/code><\/pre>\n<p>Here, we declare dependencies for the expander component as it requires styles from other partials to render correctly, as seen in <a href=\"https:\/\/www.smashingmagazine.com\/articles\/#dist-index-html\">dist\/index.html<\/a>.<\/p>\n<p>Using this list, we can write logic which would mean these dependencies would always be compiled along with their dependent components, no matter the state of the <code>$imports<\/code> variable.<\/p>\n<p>Below <code>$dependencies<\/code>, create a mixin called <code>dependency-setup()<\/code>. In here, we\u2019ll do the following actions:<\/p>\n<h5>1. Loop through the dependencies map.<\/h5>\n<div>\n<pre><code>@mixin dependency-setup() {\n   @each $componentKey, $componentValue in $dependencies {\n    \n   }\n}<\/code><\/pre>\n<\/div>\n<h5>2. If the component can be found in <code>$imports<\/code>, loop through its list of dependencies.<\/h5>\n<div>\n<pre><code>@mixin dependency-setup() {\n   $components: map-get($imports, component);\n   @each $componentKey, $componentValue in $dependencies {\n      @if(index($components, $componentKey)) {\n         @each $layerKey, $layerValue in $componentValue {\n\n         }\n      }\n   }\n}<\/code><\/pre>\n<\/div>\n<h5>3. If the dependency isn\u2019t in <code>$imports<\/code>, add it.<\/h5>\n<div>\n<pre><code>@mixin dependency-setup() {\n   $components: map-get($imports, component);\n   @each $componentKey, $componentValue in $dependencies {\n       @if(index($components, $componentKey)) {\n           @each $layerKey, $layerValue in $componentValue {\n               @each $partKey, $partValue in $layerValue {\n                   @if not index(map-get($imports, $layerKey), $partKey) {\n                       $imports: map-merge($imports, (\n                           $layerKey: append(map-get($imports,  $layerKey), '#{$partKey}')\n                       )) !global;\n                   }\n               }\n           }\n       }\n   }\n}<\/code><\/pre>\n<\/div>\n<p>Including the <code>!global<\/code> flag tells SASS to look for the <code>$imports<\/code> variable in the global scope, rather than the mixin\u2019s local scope.<\/p>\n<h5>4. Then it\u2019s just a matter of calling the mixin.<\/h5>\n<pre><code>@mixin dependency-setup() {\n   ...\n}\n@include dependency-setup();<\/code><\/pre>\n<p>So what we have now is an enhanced partial import system, where if a component is imported, a developer doesn\u2019t then have to manually import each of its various dependency partials as well.<\/p>\n<p>Configure the <code>$imports<\/code> variable so only the expander component is imported and then run <code>npm run build<\/code>. You should see in the compiled CSS the expander classes along with all of its dependencies.<\/p>\n<p>However, this doesn\u2019t really bring anything new to the table in terms of filtering out unused CSS, as the same amount of SASS is still being imported, programmatic or not. Let\u2019s improve on this.<\/p>\n<h4>Improved Dependency Importing<\/h4>\n<p>A component may require only a single class from a dependency, so to then go on and import all of that dependency\u2019s classes just leads to the same unnecessary bloat we\u2019re trying to avoid.<\/p>\n<p>We can refine the system to allow for more granular filtering on a class by class basis, to make sure components are compiled with only the dependency classes they require.<\/p>\n<p>With most design patterns, decorated or not, there exists a minimum amount of classes which need to be present in the stylesheet for the pattern to display correctly.<\/p>\n<p>For class names using an established naming convention such as <a href=\"https:\/\/css-tricks.com\/bem-101\/\">BEM<\/a>, typically the \u201cBlock\u201d and \u201cElement\u201d named classes are required as a minimum, with \u201cModifiers\u201d typically being optional.<\/p>\n<p><strong>Note:<\/strong> <em>Utility classes wouldn\u2019t typically follow the BEM route, as they\u2019re isolated in nature due to their narrow focus.<\/em><\/p>\n<p>For example, take a look at this media object, which is probably the most well-known example of object-oriented CSS:<\/p>\n<pre><code><div class=\"o-media o-media--spacing-small\">\n   <div class=\"o-media__image\">\n     <img decoding=\"async\" src=\"url\" alt=\"Image\">\n   <\/div>\n   <div class=\"o-media__text\">\n      Oh!\n   <\/div>\n<\/div><\/code><\/pre>\n<p>If a component has this set as a dependency, it makes sense to always compile <code>.o-media<\/code>, <code>.o-media__image<\/code> and <code>.o-media__text<\/code>, as that\u2019s the minimum amount of CSS required to make the pattern work. However with <code>.o-media--spacing-small<\/code> being an optional modifier, it ought to only be compiled if we explicitly say so, as its usage may not be consistent across all media object instances.<\/p>\n<p>We\u2019ll modify the structure of the <code>$dependencies<\/code> map to allow us to import these optional classes, whilst including a way to import <em>only<\/em> the block and element in case no modifiers are required.<\/p>\n<p>To get started, check the expander HTML in <a href=\"https:\/\/www.smashingmagazine.com\/articles\/#dist-index-html\">dist\/index.html<\/a> and make a note of any dependency classes in use. Record these in the <code>$dependencies<\/code> map, as per below:<\/p>\n<h5><code>src\/scss\/settings\/_dependencies.scss<\/code><\/h5>\n<pre><code>$dependencies: (\n   expander: (\n       object: (\n           box: (\n               'o-box--spacing-small'\n           ),\n           layout: (\n               'o-layout--fit'\n           )\n       ),\n       component: (\n           button: true,\n           typography: (\n               'c-type-echo',\n           )\n       ),\n       utility: (\n           alignments: (\n               'u-flex-middle',\n               'u-align-center'\n           ),\n           widths: (\n               'u-width-grow',\n               'u-width-shrink'\n           )\n       )\n   )\n);<\/code><\/pre>\n<p>Where a value is set to true, we\u2019ll translate this into \u201cOnly compile block and element level classes, no modifiers!\u201d.<\/p>\n<p>The next step involves creating a whitelist variable to store these classes, and any other (non-dependency) classes we wish to manually import. In <code>\/src\/scss\/settings\/imports.scss<\/code>, after <code>$imports<\/code>, create a new SASS list called <code>$global-filter<\/code>.<\/p>\n<h5><code>src\/scss\/settings\/_imports.scss<\/code><\/h5>\n<pre><code>$global-filter: ();<\/code><\/pre>\n<p>The basic premise behind <code>$global-filter<\/code> is that any classes stored here will be compiled on build as long as the partial they belong to is imported via <code>$imports<\/code>.<\/p>\n<p>These class names could be added programmatically if they\u2019re a component dependency, or could be added manually when the variable is declared, like in the example below:<\/p>\n<h5>Global filter example<\/h5>\n<pre><code>$global-filter: (\n   'o-box--spacing-regular@md',\n   'u-align-center',\n   'u-width-6\/12@lg'\n);<\/code><\/pre>\n<p>Next, we need to add a bit more logic to the <code>@dependency-setup<\/code> mixin, so any classes referenced in <code>$dependencies<\/code> are automatically added to our <code>$global-filter<\/code> whitelist.<\/p>\n<p>Below this block:<\/p>\n<h5><code>src\/scss\/settings\/_dependencies.scss<\/code><\/h5>\n<pre><code>@if not index(map-get($imports, $layerKey), $partKey) {\n\n}<\/code><\/pre>\n<p>&#8230;add the following snippet.<\/p>\n<h5><code>src\/scss\/settings\/_dependencies.scss<\/code><\/h5>\n<div>\n<pre><code>@each $class in $partValue {\n   $global-filter: append($global-filter, '#{$class}', 'comma') !global;\n}<\/code><\/pre>\n<\/div>\n<p>This loops through any dependency classes and adds them to the <code>$global-filter<\/code> whitelist.<\/p>\n<p>At this point, if you add a <code>@debug<\/code> statement below the <code>dependency-setup()<\/code> mixin to print out the contents of <code>$global-filter<\/code> in the terminal:<\/p>\n<pre><code>@debug $global-filter;<\/code><\/pre>\n<p>&#8230;you should see something like this on build:<\/p>\n<div>\n<pre><code>DEBUG: \"o-box--spacing-small\", \"o-layout--fit\", \"c-box--rounded\", \"true\", \"true\", \"u-flex-middle\", \"u-align-center\", \"u-width-grow\", \"u-width-shrink\"<\/code><\/pre>\n<\/div>\n<p>Now we\u2019ve got a class whitelist, we need to enforce this across all of the different object, component and utility partials.<\/p>\n<p>Create a new partial called <code>_filter.scss<\/code> in <code>src\/scss\/tools<\/code> and add an <code>@import<\/code> to tools layer\u2019s <code>_core.scss<\/code> file.<\/p>\n<p>In this new partial, we\u2019ll create a mixin called <code>filter()<\/code>. We\u2019ll use this to apply logic which means classes will only be compiled if included in the <code>$global-filter<\/code> variable.<\/p>\n<p>Starting off simple, create a mixin which accepts a single parameter \u2014 the <code>$class<\/code> which the filter controls. Next, if the <code>$class<\/code> is included in the <code>$global-filter<\/code> whitelist, allow it to be compiled.<\/p>\n<h5><code>src\/scss\/tools\/_filter.scss<\/code><\/h5>\n<pre><code>@mixin filter($class) {\n   @if(index($global-filter, $class)) {\n      @content;\n   }\n}<\/code><\/pre>\n<p>In a partial, we would wrap the mixin around an optional class, like so:<\/p>\n<pre><code>@include filter('o-myobject--modifier') {\n   .o-myobject--modifier {\n      color: yellow;\n   }\n}<\/code><\/pre>\n<p>This means the <code>.o-myobject--modifier<\/code> class would only be compiled if its included in <code>$global-filter<\/code>, which can either be set directly, or indirectly through what\u2019s set in <code>$dependencies<\/code>.<\/p>\n<p>Go through the repo and apply the <code>filter()<\/code> mixin to all optional modifier classes across object and component layers. When handling the typography component or the utilities layer, as each class is independent from the next, it\u2019d make sense to make them <em>all<\/em> optional, so we can then just enable classes as we need them.<\/p>\n<p>Here\u2019s a few examples:<\/p>\n<h5><code>src\/scss\/objects\/_layout.scss<\/code><\/h5>\n<pre><code>@include filter('o-layout__item--fit-height') {\n    .o-layout__item--fit-height {\n        align-self: stretch;\n    }\n}<\/code><\/pre>\n<h5><code>src\/scss\/utilities\/_alignments.scss<\/code><\/h5>\n<pre><code>\/\/ Changes alignment when breakpoint is hit\n\/\/ Example: .u-align-left@md\n@each $bp-name, $bp-value in $mq-breakpoints {\n    @include mq(#{$bp-name}) {\n        @include filter('u-align-left@#{$bp-name}') {\n            .u-align-left@#{$bp-name} {\n                text-align: left !important;\n            }\n        }\n\n        @include filter('u-align-center@#{$bp-name}') {\n            .u-align-center@#{$bp-name} {\n                text-align: center !important;\n            }\n        }\n\n        @include filter('u-align-right@#{$bp-name}') {\n            .u-align-right@#{$bp-name} {\n                text-align: right !important;\n            }\n        }\n    }\n}<\/code><\/pre>\n<p><strong>Note:<\/strong> When adding the responsive suffix classnames to the <code>filter()<\/code> mixin, you don\u2019t have to escape the &#8216;@&#8217; symbol with a &#8221;.<\/p>\n<p>During this process, whilst applying the <code>filter()<\/code> mixin to partials, you may (or may not) have noticed a few things.<\/p>\n<h5>Grouped Classes<\/h5>\n<p>Some classes in the codebase are grouped together and share the same styles, for example:<\/p>\n<h5><code>src\/scss\/objects\/_box.scss<\/code><\/h5>\n<pre><code>.o-box--spacing-disable-left,\n.o-box--spacing-horizontal {\n    padding-left: 0;\n}<\/code><\/pre>\n<p>As the filter only accepts a single class, it doesn\u2019t account for the possibility that one style declaration block may be for more than one class.<\/p>\n<p>To account for this, we\u2019ll expand the <code>filter()<\/code> mixin so in addition to a single class, it\u2019s able to accept a SASS arglist containing many classes. Like so:<\/p>\n<h5><code>src\/scss\/objects\/_box.scss<\/code><\/h5>\n<div>\n<pre><code>@include filter('o-box--spacing-disable-left', 'o-box--spacing-horizontal') {\n    .o-box--spacing-disable-left,\n    .o-box--spacing-horizontal {\n        padding-left: 0;\n    }\n}<\/code><\/pre>\n<\/div>\n<p>So we need to tell the <code>filter()<\/code> mixin that if either of these classes are in the <code>$global-filter<\/code>, you are allowed to compile the classes.<\/p>\n<p>This will involve additional logic to type check the mixin\u2019s <code>$class<\/code> argument, responding with a loop if an arglist is passed to check if each item is in the <code>$global-filter<\/code> variable.<\/p>\n<h5><code>src\/scss\/tools\/_filter.scss<\/code><\/h5>\n<pre><code>@mixin filter($class...) {\n    @if(type-of($class) == 'arglist') {\n        @each $item in $class {\n            @if(index($global-filter, $item)) {\n                @content;\n            }\n        }\n    }\n    @else if(index($global-filter, $class)) {\n        @content;\n    }\n}<\/code><\/pre>\n<p>Then it\u2019s just a matter of going back to the following partials to correctly apply the <code>filter()<\/code> mixin:<\/p>\n<ul>\n<li><code>objects\/_box.scss<\/code><\/li>\n<li><code>objects\/_layout.scss<\/code><\/li>\n<li><code>utilities\/_alignments.scss<\/code><\/li>\n<\/ul>\n<p>At this point, go back to <code>$imports<\/code> and enable just the expander component. In the compiled stylesheet, besides the styles from the generic and elements layers, you should only see the following:<\/p>\n<ul>\n<li>The block and element classes belonging to the expander component, but not its modifier.<\/li>\n<li>The block and element classes belonging to the expander\u2019s dependencies.<\/li>\n<li>Any modifier classes belonging to the expander\u2019s dependencies which are explicitly declared in the <code>$dependencies<\/code> variable.<\/li>\n<\/ul>\n<p>Theoretically, if you decided you wanted to include more classes in the compiled stylesheet, such as the expander components modifier, it\u2019s just a matter of adding it to the <code>$global-filter<\/code> variable at the point of declaration, or appending it at some other point in the codebase (As long as it\u2019s before the point where the modifier itself is declared).<\/p>\n<h5>Enabling Everything<\/h5>\n<p>So we now have a pretty complete system, which lets you import objects, components and utilities down to the individual classes within these partials.<\/p>\n<p>During development, for whatever reason, you may just want to enable everything in one go. To allow for this, we\u2019ll create a new variable called <code>$enable-all-classes<\/code>, and then add in some additional logic so if this is set to true, everything is compiled no matter the state of the <code>$imports<\/code> and <code>$global-filter<\/code> variables.<\/p>\n<p>First, declare the variable in our main manifest file:<\/p>\n<h5><code>src\/scss\/main.scss<\/code><\/h5>\n<pre><code>$enable-all-classes: false;\n\n@import 'settings\/core';\n@import 'tools\/core';\n@import 'generic\/core';\n@import 'elements\/core';\n@import 'objects\/core';\n@import 'components\/core';\n@import 'utilities\/core';<\/code><\/pre>\n<p>Then we just need to make a few minor edits to our <code>filter()<\/code> and <code>render()<\/code> mixins to add some override logic for when the <code>$enable-all-classes<\/code> variable is set to true.<\/p>\n<p>First up, the <code>filter()<\/code> mixin. Before any existing checks, we\u2019ll add an <code>@if<\/code> statement to see if <code>$enable-all-classes<\/code> is set to true, and if so, render the <code>@content<\/code>, no questions asked.<\/p>\n<h5><code>src\/scss\/tools\/_filter.scss<\/code><\/h5>\n<pre><code>@mixin filter($class...) {\n    @if($enable-all-classes) {\n        @content;\n    }\n    @else if(type-of($class) == 'arglist') {\n        @each $item in $class {\n            @if(index($global-filter, $item)) {\n                @content;\n            }\n        }\n    }\n    @else if(index($global-filter, $class)) {\n        @content;\n    }\n}<\/code><\/pre>\n<p>Next in the <code>render()<\/code> mixin, we just need to do a check to see if the <code>$enable-all-classes<\/code> variable is truthy, and if so, skip any further checks.<\/p>\n<h5><code>src\/scss\/tools\/_render.scss<\/code><\/h5>\n<div>\n<pre><code>$layer: null !default;\n@mixin render($name) {\n    @if($enable-all-classes or index(map-get($imports, $layer), $name)) {\n        @content;\n    }\n}<\/code><\/pre>\n<\/div>\n<p>So now, if you were to set the <code>$enable-all-classes<\/code> variable to true and rebuild, every optional class would be compiled, saving you quite a bit of time in the process.<\/p>\n<h3>Comparisons<\/h3>\n<p>To see what type of gains this technique is giving us, let\u2019s run some comparisons and see what the filesize differences are.<\/p>\n<p>To make sure the comparison is a fair one, we ought to add the box and container objects in <code>$imports<\/code>, and then add the box\u2019s <code>o-box--spacing-regular<\/code> modifier to the <code>$global-filter<\/code>, like so:<\/p>\n<h5><code>src\/scss\/settings\/_imports.scss<\/code><\/h5>\n<pre><code>$imports: (\n     object: (\n        'box',\n        'container'\n        \/\/ 'layout'\n     ),\n     component: (\n        \/\/ 'button',\n        'expander'\n        \/\/ 'typography'\n     ),\n     utility: (\n        \/\/ 'alignments',\n        \/\/ 'widths'\n     )\n);\n\n$global-filter: (\n    'o-box--spacing-regular'\n);<\/code><\/pre>\n<p>This makes sure styles for the expander\u2019s parent elements are being compiled like they would be if there were no filtering taking place.<\/p>\n<h4>Original vs Filtered Stylesheets<\/h4>\n<p>Let\u2019s compare the original stylesheet with all classes compiled, against the filtered stylesheet where only CSS required by the expander component has been compiled.<\/p>\n<table data-tablesaw-mode=\"swipe\" data-tablesaw-minimap>\n<thead>\n<tr>\n<th data-tablesaw-priority=\"persist\">Standard<\/th>\n<\/tr>\n<tr>\n<th>Stylesheet<\/th>\n<th>Size (kb)<\/th>\n<th>Size (gzip)<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Original<\/td>\n<td>54.6kb<\/td>\n<td>6.98kb<\/td>\n<\/tr>\n<tr>\n<td>Filtered<\/td>\n<td>15.34kb (72% smaller)<\/td>\n<td>4.91kb (29% smaller)<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<ul>\n<li><strong>Original:<\/strong> <a href=\"https:\/\/webdevluke.github.io\/handlingunusedcss\/dist\/index2.html\">https:\/\/webdevluke.github.io\/handlingunusedcss\/dist\/index2.html<\/a><\/li>\n<li><strong>Filtered:<\/strong> <a href=\"https:\/\/webdevluke.github.io\/handlingunusedcss\/dist\/index.html\">https:\/\/webdevluke.github.io\/handlingunusedcss\/dist\/index.html<\/a><\/li>\n<\/ul>\n<p>You may think that the gzip percentage savings mean this isn\u2019t worth the effort, as there\u2019s not much difference between the original and filtered stylesheets.<\/p>\n<p>It\u2019s worth highlighting that gzip compression works better with larger and more repetitive files. Because the filtered stylesheet is the only proof-of-concept, and only contains CSS for the expander component, there isn\u2019t as much to compress as there would be in a real-life project.<\/p>\n<p>If we were to scale up each stylesheet by a factor of 10 to sizes more typical of a website\u2019s CSS bundle size, the difference in gzip file sizes are much more impressive.<\/p>\n<table data-tablesaw-mode=\"swipe\" data-tablesaw-minimap>\n<thead>\n<tr>\n<th data-tablesaw-priority=\"persist\">10x Size<\/th>\n<\/tr>\n<tr>\n<th>Stylesheet<\/th>\n<th>Size (kb)<\/th>\n<th>Size (gzip)<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Original (10x)<\/td>\n<td>892.07kb<\/td>\n<td>75.70kb<\/td>\n<\/tr>\n<tr>\n<td>Filtered (10x)<\/td>\n<td>209.45kb (77% smaller)<\/td>\n<td>19.47kb (74% smaller)<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h4>Filtered Stylesheet vs UNCSS<\/h4>\n<p>Here\u2019s a comparison between the filtered stylesheet and a stylesheet which has been run through the UNCSS tool.<\/p>\n<table data-tablesaw-mode=\"swipe\" data-tablesaw-minimap>\n<thead>\n<tr>\n<th data-tablesaw-priority=\"persist\">Filtered vs UNCSS<\/th>\n<\/tr>\n<tr>\n<th>Stylesheet<\/th>\n<th>Size (kb)<\/th>\n<th>Size (gzip)<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Filtered<\/td>\n<td>15.34kb<\/td>\n<td>4.91kb<\/td>\n<\/tr>\n<tr>\n<td>UNCSS<\/td>\n<td>12.89kb (16% smaller)<\/td>\n<td>4.25kb (13% smaller)<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The UNCSS tool wins here marginally, as it\u2019s filtering out CSS in the generic and elements directories.<\/p>\n<p>It\u2019s possible that on a real website, with a larger variety of HTML elements in use, the difference between the 2 methods would be negligible.<\/p>\n<h3>Wrapping Up<\/h3>\n<p>So we\u2019ve seen how \u2014 using just SASS \u2014 you are able to gain more control over what CSS classes are being compiled on build. This reduces the amount of unused CSS in the final stylesheet and speeds up the critical rendering path.<\/p>\n<p>At the start of the article, I listed some drawbacks of existing solutions such as UNCSS. It\u2019s only fair to critique this SASS-oriented solution in the same way, so all the facts are on the table before you decide which approach is better for you:<\/p>\n<h4>Pros<\/h4>\n<ul>\n<li>No additional dependencies required, so you don\u2019t have to rely on somebody else\u2019s code.<\/li>\n<li>Less build time required than Node.js based alternatives, as you don\u2019t have to run headless browsers to audit your code. This is especially useful with continuous integration as you may be less likely to see a queue of builds.<\/li>\n<li>Results in similar file size when compared to automated tools.<\/li>\n<li>Out of the box, you have complete control over what code is being filtered, regardless of how those CSS classes are used in your code. With Node.js based alternatives, you often have to maintain a separate whitelist so CSS classes belonging to dynamically injected HTML aren\u2019t filtered out.<\/li>\n<\/ul>\n<h4>Cons<\/h4>\n<ul>\n<li>The SASS-oriented solution is definitely more hands-on, in the sense that you have to keep on top of the <code>$imports<\/code> and <code>$global-filter<\/code> variables. Beyond the initial setup, the Node.js alternatives we\u2019ve looked at are largely automated.<\/li>\n<li>If you add CSS classes to <code>$global-filter<\/code> and then later remove them from your HTML, you need to remember to update the variable, otherwise you\u2019ll be compiling CSS you don\u2019t need. With large projects being worked on by multiple devs at any one time, this may not be easy to manage unless you properly plan for it.<\/li>\n<li>I wouldn\u2019t recommend bolting this system onto any existing CSS codebase, as you\u2019d have to spend quite a bit of time piecing together dependencies and applying the <code>render()<\/code> mixin to a LOT of classes. It\u2019s a system much easier to implement with new builds, where you don\u2019t have existing code to contend with.<\/li>\n<\/ul>\n<p>Hopefully you\u2019ve found this as interesting to read as I\u2019ve found it interesting to put together. If you have any suggestions, ideas to improve this approach, or want to point out some fatal flaw that I\u2019ve missed entirely, be sure to post in the comments below.<\/p>\n<div>\n  <img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/08\/logo-red-8.png?w=900\" alt=\"Smashing Editorial\"><span>(dm, yk, il)<\/span>\n<\/div>\n<\/article>\n<p class=\"wpematico_credit\"><small>Powered by <a href=\"http:\/\/www.wpematico.com\" target=\"_blank\">WPeMatico<\/a><\/small><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Handling Unused CSS In SASS To Improve Performance Handling Unused CSS In SASS To Improve Performance Luke Harrison 2019-08-09T12:30:59+02:002019-08-09T11:08:44+00:00 In modern front-end development, developers should aim to write CSS which is scalable and maintainable. Otherwise, they risk losing control over specifics such as the cascade and selector specificity as the codebase grows and more developers&#8230;<a class=\"moretag\" href=\"https:\/\/www.taterboy.com\/blog\/2019\/08\/handling-unused-css-in-sass-to-improve-performance\/\"> Read the full article&#8230;<\/a><\/p>\n","protected":false},"author":4,"featured_media":69166,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"jetpack_post_was_ever_published":false},"categories":[371],"tags":[],"class_list":["post-69165","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-user-experience"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.0.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"Handling Unused CSS In SASS To Improve PerformanceHandling Unused CSS In SASS To Improve Performance Luke Harrison 2019-08-09T12:30:59+02:002019-08-09T11:08:44+00:00In modern front-end development, developers should aim to write CSS which is scalable and maintainable. Otherwise, they risk losing control over specifics such as the cascade and selector specificity as the codebase grows and more developers contribute. One\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Guest Contribution\"\/>\n\t<meta name=\"keywords\" content=\"user experience\" \/>\n\t<link rel=\"canonical\" href=\"https:\/\/www.taterboy.com\/blog\/2019\/08\/handling-unused-css-in-sass-to-improve-performance\/\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.0.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"en_US\" \/>\n\t\t<meta property=\"og:site_name\" content=\"Design for Immersive Technologies | User Experience for Games, Virtual Reality (VR) and Augmented\/Mixed Reality (AR\/MR)\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"Handling Unused CSS In SASS To Improve Performance | Design for Immersive Technologies\" \/>\n\t\t<meta property=\"og:description\" content=\"Handling Unused CSS In SASS To Improve PerformanceHandling Unused CSS In SASS To Improve Performance Luke Harrison 2019-08-09T12:30:59+02:002019-08-09T11:08:44+00:00In modern front-end development, developers should aim to write CSS which is scalable and maintainable. Otherwise, they risk losing control over specifics such as the cascade and selector specificity as the codebase grows and more developers contribute. One\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/www.taterboy.com\/blog\/2019\/08\/handling-unused-css-in-sass-to-improve-performance\/\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-08-09T11:20:33+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-08-09T11:20:33+00:00\" \/>\n\t\t<meta name=\"twitter:card\" content=\"summary\" \/>\n\t\t<meta name=\"twitter:title\" content=\"Handling Unused CSS In SASS To Improve Performance | Design for Immersive Technologies\" \/>\n\t\t<meta name=\"twitter:description\" content=\"Handling Unused CSS In SASS To Improve PerformanceHandling Unused CSS In SASS To Improve Performance Luke Harrison 2019-08-09T12:30:59+02:002019-08-09T11:08:44+00:00In modern front-end development, developers should aim to write CSS which is scalable and maintainable. Otherwise, they risk losing control over specifics such as the cascade and selector specificity as the codebase grows and more developers contribute. One\" \/>\n\t\t<script type=\"application\/ld+json\" class=\"aioseo-schema\">\n\t\t\t{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/08\\\/handling-unused-css-in-sass-to-improve-performance\\\/#article\",\"name\":\"Handling Unused CSS In SASS To Improve Performance | Design for Immersive Technologies\",\"headline\":\"Handling Unused CSS In SASS To Improve Performance\",\"author\":{\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/author\\\/guestcontribution\\\/#author\"},\"publisher\":{\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/#organization\"},\"image\":{\"@type\":\"ImageObject\",\"url\":\"https:\\\/\\\/i0.wp.com\\\/www.taterboy.com\\\/blog\\\/wp-content\\\/uploads\\\/2019\\\/08\\\/sheffield-united-website.png?fit=400%2C207&ssl=1\",\"width\":400,\"height\":207},\"datePublished\":\"2019-08-09T04:20:33-07:00\",\"dateModified\":\"2019-08-09T04:20:33-07:00\",\"inLanguage\":\"en-US\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/08\\\/handling-unused-css-in-sass-to-improve-performance\\\/#webpage\"},\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/08\\\/handling-unused-css-in-sass-to-improve-performance\\\/#webpage\"},\"articleSection\":\"User Experience\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/08\\\/handling-unused-css-in-sass-to-improve-performance\\\/#breadcrumblist\",\"itemListElement\":[{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog#listItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.taterboy.com\\\/blog\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/category\\\/user-experience\\\/#listItem\",\"name\":\"User Experience\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/category\\\/user-experience\\\/#listItem\",\"position\":2,\"name\":\"User Experience\",\"item\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/category\\\/user-experience\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/08\\\/handling-unused-css-in-sass-to-improve-performance\\\/#listItem\",\"name\":\"Handling Unused CSS In SASS To Improve Performance\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog#listItem\",\"name\":\"Home\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/08\\\/handling-unused-css-in-sass-to-improve-performance\\\/#listItem\",\"position\":3,\"name\":\"Handling Unused CSS In SASS To Improve Performance\",\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/category\\\/user-experience\\\/#listItem\",\"name\":\"User Experience\"}}]},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/#organization\",\"name\":\"Design for Immersive Technologies\",\"description\":\"User Experience for Games, Virtual Reality (VR) and Augmented\\\/Mixed Reality (AR\\\/MR)\",\"url\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/author\\\/guestcontribution\\\/#author\",\"url\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/author\\\/guestcontribution\\\/\",\"name\":\"Guest Contribution\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/08\\\/handling-unused-css-in-sass-to-improve-performance\\\/#authorImage\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/d2aad73eb0f48c67b141e9fc978a0e498969791ed623346e361d02d19775b0bb?s=96&d=mm&r=g\",\"width\":96,\"height\":96,\"caption\":\"Guest Contribution\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/08\\\/handling-unused-css-in-sass-to-improve-performance\\\/#webpage\",\"url\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/08\\\/handling-unused-css-in-sass-to-improve-performance\\\/\",\"name\":\"Handling Unused CSS In SASS To Improve Performance | Design for Immersive Technologies\",\"description\":\"Handling Unused CSS In SASS To Improve PerformanceHandling Unused CSS In SASS To Improve Performance Luke Harrison 2019-08-09T12:30:59+02:002019-08-09T11:08:44+00:00In modern front-end development, developers should aim to write CSS which is scalable and maintainable. Otherwise, they risk losing control over specifics such as the cascade and selector specificity as the codebase grows and more developers contribute. One\",\"inLanguage\":\"en-US\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/#website\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/08\\\/handling-unused-css-in-sass-to-improve-performance\\\/#breadcrumblist\"},\"author\":{\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/author\\\/guestcontribution\\\/#author\"},\"creator\":{\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/author\\\/guestcontribution\\\/#author\"},\"image\":{\"@type\":\"ImageObject\",\"url\":\"https:\\\/\\\/i0.wp.com\\\/www.taterboy.com\\\/blog\\\/wp-content\\\/uploads\\\/2019\\\/08\\\/sheffield-united-website.png?fit=400%2C207&ssl=1\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/08\\\/handling-unused-css-in-sass-to-improve-performance\\\/#mainImage\",\"width\":400,\"height\":207},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/08\\\/handling-unused-css-in-sass-to-improve-performance\\\/#mainImage\"},\"datePublished\":\"2019-08-09T04:20:33-07:00\",\"dateModified\":\"2019-08-09T04:20:33-07:00\"},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/\",\"name\":\"Design for Immersive Technologies\",\"description\":\"User Experience for Games, Virtual Reality (VR) and Augmented\\\/Mixed Reality (AR\\\/MR)\",\"inLanguage\":\"en-US\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/#organization\"}}]}\n\t\t<\/script>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"Handling Unused CSS In SASS To Improve Performance | Design for Immersive Technologies","description":"Handling Unused CSS In SASS To Improve PerformanceHandling Unused CSS In SASS To Improve Performance Luke Harrison 2019-08-09T12:30:59+02:002019-08-09T11:08:44+00:00In modern front-end development, developers should aim to write CSS which is scalable and maintainable. Otherwise, they risk losing control over specifics such as the cascade and selector specificity as the codebase grows and more developers contribute. One","canonical_url":"https:\/\/www.taterboy.com\/blog\/2019\/08\/handling-unused-css-in-sass-to-improve-performance\/","robots":"max-image-preview:large","keywords":"user experience","webmasterTools":{"miscellaneous":""},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.taterboy.com\/blog\/2019\/08\/handling-unused-css-in-sass-to-improve-performance\/#article","name":"Handling Unused CSS In SASS To Improve Performance | Design for Immersive Technologies","headline":"Handling Unused CSS In SASS To Improve Performance","author":{"@id":"https:\/\/www.taterboy.com\/blog\/author\/guestcontribution\/#author"},"publisher":{"@id":"https:\/\/www.taterboy.com\/blog\/#organization"},"image":{"@type":"ImageObject","url":"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/08\/sheffield-united-website.png?fit=400%2C207&ssl=1","width":400,"height":207},"datePublished":"2019-08-09T04:20:33-07:00","dateModified":"2019-08-09T04:20:33-07:00","inLanguage":"en-US","mainEntityOfPage":{"@id":"https:\/\/www.taterboy.com\/blog\/2019\/08\/handling-unused-css-in-sass-to-improve-performance\/#webpage"},"isPartOf":{"@id":"https:\/\/www.taterboy.com\/blog\/2019\/08\/handling-unused-css-in-sass-to-improve-performance\/#webpage"},"articleSection":"User Experience"},{"@type":"BreadcrumbList","@id":"https:\/\/www.taterboy.com\/blog\/2019\/08\/handling-unused-css-in-sass-to-improve-performance\/#breadcrumblist","itemListElement":[{"@type":"ListItem","@id":"https:\/\/www.taterboy.com\/blog#listItem","position":1,"name":"Home","item":"https:\/\/www.taterboy.com\/blog","nextItem":{"@type":"ListItem","@id":"https:\/\/www.taterboy.com\/blog\/category\/user-experience\/#listItem","name":"User Experience"}},{"@type":"ListItem","@id":"https:\/\/www.taterboy.com\/blog\/category\/user-experience\/#listItem","position":2,"name":"User Experience","item":"https:\/\/www.taterboy.com\/blog\/category\/user-experience\/","nextItem":{"@type":"ListItem","@id":"https:\/\/www.taterboy.com\/blog\/2019\/08\/handling-unused-css-in-sass-to-improve-performance\/#listItem","name":"Handling Unused CSS In SASS To Improve Performance"},"previousItem":{"@type":"ListItem","@id":"https:\/\/www.taterboy.com\/blog#listItem","name":"Home"}},{"@type":"ListItem","@id":"https:\/\/www.taterboy.com\/blog\/2019\/08\/handling-unused-css-in-sass-to-improve-performance\/#listItem","position":3,"name":"Handling Unused CSS In SASS To Improve Performance","previousItem":{"@type":"ListItem","@id":"https:\/\/www.taterboy.com\/blog\/category\/user-experience\/#listItem","name":"User Experience"}}]},{"@type":"Organization","@id":"https:\/\/www.taterboy.com\/blog\/#organization","name":"Design for Immersive Technologies","description":"User Experience for Games, Virtual Reality (VR) and Augmented\/Mixed Reality (AR\/MR)","url":"https:\/\/www.taterboy.com\/blog\/"},{"@type":"Person","@id":"https:\/\/www.taterboy.com\/blog\/author\/guestcontribution\/#author","url":"https:\/\/www.taterboy.com\/blog\/author\/guestcontribution\/","name":"Guest Contribution","image":{"@type":"ImageObject","@id":"https:\/\/www.taterboy.com\/blog\/2019\/08\/handling-unused-css-in-sass-to-improve-performance\/#authorImage","url":"https:\/\/secure.gravatar.com\/avatar\/d2aad73eb0f48c67b141e9fc978a0e498969791ed623346e361d02d19775b0bb?s=96&d=mm&r=g","width":96,"height":96,"caption":"Guest Contribution"}},{"@type":"WebPage","@id":"https:\/\/www.taterboy.com\/blog\/2019\/08\/handling-unused-css-in-sass-to-improve-performance\/#webpage","url":"https:\/\/www.taterboy.com\/blog\/2019\/08\/handling-unused-css-in-sass-to-improve-performance\/","name":"Handling Unused CSS In SASS To Improve Performance | Design for Immersive Technologies","description":"Handling Unused CSS In SASS To Improve PerformanceHandling Unused CSS In SASS To Improve Performance Luke Harrison 2019-08-09T12:30:59+02:002019-08-09T11:08:44+00:00In modern front-end development, developers should aim to write CSS which is scalable and maintainable. Otherwise, they risk losing control over specifics such as the cascade and selector specificity as the codebase grows and more developers contribute. One","inLanguage":"en-US","isPartOf":{"@id":"https:\/\/www.taterboy.com\/blog\/#website"},"breadcrumb":{"@id":"https:\/\/www.taterboy.com\/blog\/2019\/08\/handling-unused-css-in-sass-to-improve-performance\/#breadcrumblist"},"author":{"@id":"https:\/\/www.taterboy.com\/blog\/author\/guestcontribution\/#author"},"creator":{"@id":"https:\/\/www.taterboy.com\/blog\/author\/guestcontribution\/#author"},"image":{"@type":"ImageObject","url":"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/08\/sheffield-united-website.png?fit=400%2C207&ssl=1","@id":"https:\/\/www.taterboy.com\/blog\/2019\/08\/handling-unused-css-in-sass-to-improve-performance\/#mainImage","width":400,"height":207},"primaryImageOfPage":{"@id":"https:\/\/www.taterboy.com\/blog\/2019\/08\/handling-unused-css-in-sass-to-improve-performance\/#mainImage"},"datePublished":"2019-08-09T04:20:33-07:00","dateModified":"2019-08-09T04:20:33-07:00"},{"@type":"WebSite","@id":"https:\/\/www.taterboy.com\/blog\/#website","url":"https:\/\/www.taterboy.com\/blog\/","name":"Design for Immersive Technologies","description":"User Experience for Games, Virtual Reality (VR) and Augmented\/Mixed Reality (AR\/MR)","inLanguage":"en-US","publisher":{"@id":"https:\/\/www.taterboy.com\/blog\/#organization"}}]},"og:locale":"en_US","og:site_name":"Design for Immersive Technologies | User Experience for Games, Virtual Reality (VR) and Augmented\/Mixed Reality (AR\/MR)","og:type":"article","og:title":"Handling Unused CSS In SASS To Improve Performance | Design for Immersive Technologies","og:description":"Handling Unused CSS In SASS To Improve PerformanceHandling Unused CSS In SASS To Improve Performance Luke Harrison 2019-08-09T12:30:59+02:002019-08-09T11:08:44+00:00In modern front-end development, developers should aim to write CSS which is scalable and maintainable. Otherwise, they risk losing control over specifics such as the cascade and selector specificity as the codebase grows and more developers contribute. One","og:url":"https:\/\/www.taterboy.com\/blog\/2019\/08\/handling-unused-css-in-sass-to-improve-performance\/","article:published_time":"2019-08-09T11:20:33+00:00","article:modified_time":"2019-08-09T11:20:33+00:00","twitter:card":"summary","twitter:title":"Handling Unused CSS In SASS To Improve Performance | Design for Immersive Technologies","twitter:description":"Handling Unused CSS In SASS To Improve PerformanceHandling Unused CSS In SASS To Improve Performance Luke Harrison 2019-08-09T12:30:59+02:002019-08-09T11:08:44+00:00In modern front-end development, developers should aim to write CSS which is scalable and maintainable. Otherwise, they risk losing control over specifics such as the cascade and selector specificity as the codebase grows and more developers contribute. One"},"aioseo_meta_data":{"post_id":"69165","title":null,"description":null,"keywords":null,"keyphrases":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_custom_url":null,"og_image_custom_fields":null,"og_custom_image_width":null,"og_custom_image_height":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"location":null,"local_seo":null,"created":"2021-02-07 18:28:20","updated":"2026-09-01 19:49:29","focus_keyword":null,"additional_keywords":null,"truseo_locale":null,"primary_term":null,"og_image_url":null,"og_image_width":null,"og_image_height":null,"twitter_image_url":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"Article","isEnabled":true},"graphs":[]},"limit_modified_date":false,"ai":null,"breadcrumb_settings":null,"seo_analyzer_scan_date":null},"aioseo_breadcrumb":"<div class=\"aioseo-breadcrumbs\"><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.taterboy.com\/blog\" title=\"Home\">Home<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.taterboy.com\/blog\/category\/user-experience\/\" title=\"User Experience\">User Experience<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\tHandling Unused CSS In SASS To Improve Performance\n\t\t<\/span><\/div>","aioseo_breadcrumb_json":[{"label":"Home","link":"https:\/\/www.taterboy.com\/blog"},{"label":"User Experience","link":"https:\/\/www.taterboy.com\/blog\/category\/user-experience\/"},{"label":"Handling Unused CSS In SASS To Improve Performance","link":"https:\/\/www.taterboy.com\/blog\/2019\/08\/handling-unused-css-in-sass-to-improve-performance\/"}],"jetpack_publicize_connections":[],"jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p8wzr5-hZz","jetpack_featured_media_url":"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/08\/sheffield-united-website.png?fit=400%2C207&ssl=1","_links":{"self":[{"href":"https:\/\/www.taterboy.com\/blog\/wp-json\/wp\/v2\/posts\/69165","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.taterboy.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.taterboy.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.taterboy.com\/blog\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/www.taterboy.com\/blog\/wp-json\/wp\/v2\/comments?post=69165"}],"version-history":[{"count":0,"href":"https:\/\/www.taterboy.com\/blog\/wp-json\/wp\/v2\/posts\/69165\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.taterboy.com\/blog\/wp-json\/wp\/v2\/media\/69166"}],"wp:attachment":[{"href":"https:\/\/www.taterboy.com\/blog\/wp-json\/wp\/v2\/media?parent=69165"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.taterboy.com\/blog\/wp-json\/wp\/v2\/categories?post=69165"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.taterboy.com\/blog\/wp-json\/wp\/v2\/tags?post=69165"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}