minid.net:CSS → High performance CSS methodology

Minid the blog, April 07, 2019:

The Utilitarian CSS Methodology

Summary:

We have been programming CSS for a long time wrong. It's time to move forward. By using the Utilitarian CSS Methodology, the size of the CSS files is drastically reduced and the loading, rendering and painting speed of the websites is significantly increased. The projects acquire ease of maintenance and are easier to understand.

When I started writing CSS in 1996, I was truly excited: the entire presentation of an HTML document could be defined on a separate sheet and, consequently, every change I wanted to make reverberated everywhere on the website I was maintaining. This, as it sounds, was a great deal for us developers. Not having to edit thousands of HTML files by hand, always repeating the same changes, what a bless. But… we had a problem: back then, Internet Explorer 3 was the first browser to support the fully CSS 1 standard so the rest of the population were still using Netscape and, as you may suspect: people didn’t switch browsers at all like we do today. So we developers had to stick to shitty HTML editing until the majority of people switched or upgraded browsers. That was the reality around 1996. It is also true that, even if we only had rely on HTML, our biggest pain came from not having awesome content managers or includes or partials features, where you can create pieces of HTML and reuse them everywhere. Those who have not yet been taken by the grim reaper should know that long time ago developers used frames to do all this job. It was a very archaic and ugly way to develop, but it was the only thing we had. Today all these things are a kind of urban legend. We no longer have connection speeds issues, lacking of CSS support or serious compatibility issues between browsers. Almost everything we mention is quite –but not completely– solved but even with all this awesomeness, we created several other kind of problems.

We have created a monster

To understand how we have come to this monstrous point of programming CSS, we have to understand the path we have traveled thus far. I have always liked to refer to the 4 stages of web development to demonstrate the drastic changes we have made in only 25 years of life. The first stage comprises from 1995 to 2001. I call it “Dawn of HTML”. Lots of problems derived from this particular period because doing layouts required the abuse of the TABLE element like you never imagine. Really, like you never imagine. Among other things, we also had the worsts network connection ever; the crazy design styles of that time; the abuse of images –specially transparent GIFs– and other silly Internet trends making loading an entire homepage a sort of a family event. It was very close to an average of 15-20 seconds for each page, even more if you were located overseas. Yet, in this period of time, we have seen the rise of Macromedia Flash in 1997 and Flash 3 by the end of 2000. Even with all those crazy things, CSS wasn’t a big thing and only a few daring developers who started to blog about Web Standards used it; most of the projects in the web were done using tables over tables over tables.

When we get into 2001, we started to live the 2nd era of web development, as a call it “The Empire of Flash”. It went approximately from 2001 to late 2007 and –with total irruption of the Web Standards on the way– CSS & HTML didn’t found its place in developers hearts but more specially, managers, to fight against the Flash empire, a proprietary technology of Macromedia that allowed to create rich websites in animations and interactions. It took 7 years to overthrow the Flash monopoly and it wasn’t possible until the iPhone’s release to market in 2007 and specially, by the end of 2009: when Steve Jobs’s decided to kill Flash that the development standards took off high towards a new direction and without possible return.

In 2008 things began to change again at a dramatic pace. The irruption of smartphones, tablets and the death of Flash by Apple forced developers and managers to change their strategies. This 3rd period I call it as “The Rise of HTML 5”. Now developers started using CSS in an intensive and uncontrolled way. Thousands of classes to define everything and if we add the fact that it was necessary to develop methods for several browsers, the size of CSS files began to grow brutally. This great chaos brought attention of bigger companies, specially from the hand of companies such as Yahoo and others, who began to define the first CSS development methodologies, like OOCSS (object oriented CSS) or we can mention ACSS (atomic CSS), BEM (block, element, modifier) or SMACSS (scalable and modular architecture for CSS) among others. These methodologies helped to make the developers work in an orderly fashion, but they did not help reduce the size of the files that much. On the contrary, many of these methodologies ended up increasing the final size of the files as you can see in this graphic:

average css file size Created with Sketch. Average CSS file size (KB) for Spanish newspapers 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 0 100 200 300

In the fourth stage of the era of web development, around the end of 2012, if we need to name this period, I can say that “The Dominion of Methodologies and Frameworks” was the best title I could think of. An era where almost all developers use either a framework or a methodology. Here we can see two disastrous patterns: the first one, because the developers when using frameworks not only increase the size of the CSS file by default (they use all the components by default) but they add more code on top of it to overwrite the default styles that the frameworks offer at first. This can be seen without problems in many of the analyzed sites, where they use entire libraries for a few necessary styles. In the second case, the use of methodologies, the developers commit the sin of atomizing each component until it becomes useless, creating more and more components as the project grows. No matter how thought the architecture is, it shows that it does not work over time, creating more redundant code. It is not a matter of incompetence of the developer: it is the methodology that encourages the creation of components, modifiers and more modifiers to cover all unthinkable cases. This era is characterized by making the developer have tools to develop more comfortably instead of developing with more performance.

The importance of the CSS file size

In order to understand the impact of CSS in our lives, we need to take a good example of projects that lasted since 1995 –most of them died after couple years or after a decade–, to achieve this, I have found newspapers to be the perfect example group for this research. When I got the first data of the research, I saw the trend was very clear: each year –with some highs and lows, though– the size increased significantly and in a very similar pattern for each of the group subjects, but after a year of activity, the trend keep up every single year, including on 2019.

I already know exactly the reasons why that happened: First, the developers moved all the logic of building the UI to CSS hoping their CSS components will cover all needs to their websites but, over the time, they started to stack up more and more code, therefore, as the business and activity of these projects grew, so the CSS file did. Second, developers –having no longer the Browser’s War in their tables– began to use both new methodologies (such as BEM or OOCSS) and frameworks (such as YUI, Bootstrap, Foundation, etc.) by increasing the base code of each project, partly because the methodologies are very verbose-like, the tools offered in the preprocessors and all the constraints that frameworks bring to the scene, making developers go to technical debt unconsciously and with ease. Third, because there was an explosion of libraries that offered functionalities, such as the YUI or JQuery UI libraries, which allowed developers to easily include calendars and other components. These libraries inflated CSS size as I could check on more than one occasion.

By the end of 2018, we continue to see the same pattern of problems. But at this point, what I see is mostly the collateral effect of overturning all the responsibility of building the CSS architectures. As a fact, developers have spared no effort in reducing the code but rather in expanding it, ending with a kind of testament of all the structures that can not be changed due to the amount of necessary refactor on every new design and thus repeating thousands of times the same properties and values, as I can see, in the most read newspaper of all Spain, MARCA:

Times a property appears in the same CSS file
display color height font-size display padding margin
2029 1464 1416 1308 1249 942 902

In the previous table we can smell fire: the unnecessary repetition of classes and properties, increasing significantly the CSS file size. With the Internet connection speeds we have today, it may be a minor problem, but that problem does not lie in the transfer itself (which is, partly) but in the amount of code that has to be created and maintained, as well, reuse all those classes in future cases. When I said “the amount of code that has to be created” I didn’t wanted to say that, most of the developers write color: #ff0000 all the time manually. Of course this repetition comes thanks to the wonderful features of most of the CSS preprocessors, like mixins and extensions as well others. Most of the projects analyzed fell into these dilemmas: use what has been done or create more classes to avoid conflicts. In general, what I see is developers creating more and more CSS architecture and having a clear technical debt problem by thinking their architecture truly solves their problems: if you want to modify MARCA’s website, you need to really refactor +9000 lines of code of CSS, meaning that you also have to go through each component in their CMS platform and apply new redesigned classes, fixes and the list goes on.

That’s why these projects are really titanic, and probably would never be fully redesigned and refactored properly: the amount of stones in the backpack is too damn high, so the responsibility to take care of it. That’s why over these years I’ve been thinking how this problem can be solved, and I have found it under the wonderful Utilitarian CSS Methodology.

Utilitarian CSS methodology

Designed to be useful rather than decorative.

The Utilitarian CSS Methodology, from now on, “UCSS”, is a functional approach I established to solve the problem of programming, scaling and maintaining my CSS projects. It is not a new concept, in fact, people also call it as “functional CSS” or “inmutable CSS”. It bases everything with the creation of single class property utility rather than collection of classes than define entire components with some base styles that you will probably never. Each of these CSS properties represents a unique CSS property and its possibles values, like font-weight--bold or display--block. Every single CSS property can be built in our main CSS file, but instead of doing that, we just generate the needed properties and values for our projects, maintaining a strict weight on our CSS files. How the code would look like? Here’s an easy example:

Let’s say we have a hero component:

<div class="hero hero--homepage">
  <h1 class="hero__title hero__title--accent">Our wonderful startup idea</h1>
  <img src="/images/image.png" alt="" class="hero__image hero__image--centered"/>
</div>

In UCSS this JS component would be:

<div class="background-color--1 padding--32 text-align--center">
  <h1 class="font-size--64 color--2 margin-bottom--32">Our wonderful startup idea</h1>
  <img src="/images/image.png" class="display--block margin--auto" alt=""/>
</div>

If we analyze both examples, we can see that in the first example, all the classes are descriptive, but relative to their form, not its true CSS properties. We do not know for sure what .hero or hero--homepage does. We can guess something, but we are not quite sure. We also don’t know if any of the classes present there is overwritten by another rule. We have little information.

In this first example we already imagine the problems that will come once the project goes forward in development. The use of classes to describe components causes us to end up forgetting the very nature of each one. Soon, we will start creating new classes to do the same things that we had already defined at the beginning. This is a common pattern in web development. It happens a lot: creating a class nav with its initial modifiers (like --principal, --aside or --categories) but as the project grows, we realize that not all modifiers can do the job and we end up creating different types of nav classes using synonyms (like buttons, options, etc.) because, it does not make sense to overwrite 100% of the navigation rules to create a new thing from scratch and because if we start reusing classes for another purposes we may find problems the day we want to change something. To do so, it supposes not only to create more instructions, also it supposes to keep to the problems of inheritance, therefore, we ended up creating new classes from scratch again because we want to avoid problems in the future, to get a cleaner code, with the right instructions to create other structures of navigation.

In the second example (the UCSS one), we have a clear understanding what is going on: everything is separated and explicit in purpose, meaning that, we can change anything in the JS module without having to edit 1 single line of our CSS file and we will have our changes instantly done. We also know all the behavior and that we don’t have any constraint to remove things or overwritten rules to watch for, no inheritance problems. That is utilitarianism at its best: in the first example, it has to share properties with other structures defined in the CSS, grossing the CSS file over the time and increasing technical debt. In the second, the CSS file is not engrossed, we just re-use all the properties in our JS module, when needed.

Then our next question is, why would you do that instead of using inline-css? My answer is simple: inline CSS is good, but it has its caveats:

UCSS means you can have both of the best worlds: inline power to apply whatever rule you need and the flexibility of classes. For example:

<div class="sm-display--none md-display--grid c-warning">
  <h3>This is a warning</h3>
  <p class="color--2">Your profile needs to be updated.</p>
</div>

In this example, we see that our sm-display--none only works for mobile, while md-display--grid will overwrite the previous class when we are using a bigger screen. We also spot something new: c-warning, and we know that c- belongs to “custom” class. This class is used to trigger stuff we cannot do as if we were programming with pure UCSS so, every time you see a custom class, you know it’s man-made, therefore, a change in behavior or property is happening outside the JS world. In this case, for example, c-warning in our custom.scss does this:

.c-warning:hover {
  background: map-get($colors, 1);
}

So now we can see that our custom class it’s there because we need to specify behavior, in this case :hover, and that’s all. Your custom class will be stored in one file, where you can quickly get to it and modified it. There’s no constraints what you can do with.

This approach give you all these benefits:

Utilities classes in CSS isn’t a new thing. You may be creating some for your projects. You may be using some for a long time if you were using Bootstrap or other custom made frameworks at your company, but for sure you didn’t fully used utilities in this particular way to convey an entire philosophy and architectural design as I designed it for UCSS. That’s why UCSS or functional CSS is quite new, even that you may encounter some projects that have more or less utilities –or the same functional approach–, these rely on their own naming conventions and none of these translate CSS as accurate and strictly as UCSS. Having said that, the ultimate goal of UCSS is to allow developers to concentrate the logic in the real components that bring logic and data (JS or your favorite language) rather than creating those things in a set of .css files. UCSS is compatible with anything you used, even if you want to use it partially, it will be always the minimum CSS needed. It is also compatible with your components, like forms or buttons.

I also encourage you to check other projects too, with the same philosophy like Basscss, Tachyons or Tailwind CSS.

Performance

As a general rule, any hit to the server delays the compilation of the website. Since HTML is the first doc served and processed by the browser, inline CSS (or styles in the HEAD) will be faster in performance that serving external CSS files. But sometimes this is not possible or it doesn’t scale as we want so we use external CSS file with caching rules. Without having this properly done, the page will be either white for a couple of seconds while the browser waits the CSS to be processed into a CSSOM. So, the faster this file is delivered to the browser, the faster will be the page rendered. UCSS will be always trumping over conventional CSS development: the files are really tiny that, in most cases, you will be putting it into the HEAD instead of serving it through external CSS files. Even taking the external option will result in faster delivery of CSS to the browser. Most of the files created with the UCSS framework (more below) do not surpass the 15KB of file size uncompressed.

Another frequently ignored point is resource loading into the browser, which means how much time the browser takes to understand the HTML, JS, CSS and other resources you provided. This time spent by the browser usually is milliseconds but sometimes it could grow up above the second, this means that the browser will be stuck for that time blocking the rendering and painting jobs. As a fact: any CSS file that is bloated in selectors and properties will load slower. Due the nature of BEM and other methodologies, file sizes ends with an incredible amount of rules, so much as over 9.000 rules or even higher numbers, as I’ve mentioned above. This adds an extra time loading the CSS and processing it to render the CSS tree. When I started this project, I’ve made several tests loading different types of CSS files and their equivalent to UCSS in order to test the loading performance and the results were pretty shocking. The MARCA analysis, as an example, gave me these results after loading their (compiled) CSS resources 100 times:

CSS Processing speed comparison
Compiled Marca.com Compiled UCSS
84,3ms 8,4ms

The last and most important point to mention in this performance section is rendering time. Once the browser has built the CSSOM –in the loading job–, the rendering instructions begins its job to deliver the painting process. Lots of things can affect the rendering time: JS code and webfonts (specially), CSS effects (like box-shadow, filters, background images, fonts, etc.) amount of resources to load, slow selectors and pseudo selectors, etc. UCSS outperforms any other methodology: it is so explicit that render times are greatly improved. In all tests with different projects in complexity, I’ve got performance gains from an average of 175ms to a mere 17ms. That’s insanely fast. This is given because of the explicit nature of the single class CSS and the lack of all the rules in play at that moment. In a test in the lab, we have found that even un-styled pages aren’t that faster than the same HTML styled with UCSS due the nature of the CSS provided on the default browser’s CSS stylesheets. So amazing as that.

The framework

UCSS has a framework of my own. It is written in SCSS, so it can be practically adopted in any project, even on those with PostCSS. The major differences of this framework are:

One of the dilemmas that has always bothered me is the use of normalizer. Everyone installs normalizer, but few comment on the sections they will never use, therefore, each project already dedicates 6 KB to styles that will never be used. The UCSS framework has a normalizer module, which complies with all normalizer rules, but these are activated according to what you need. To start using it, you need to go to the config_normalizer.scss file and start changing the variables to true so that it automatically takes effect. No more cost of KBs without impact on the site. You can have your customizer, as I recommend as a philosophy to have the best CSS code: only the classes that are needed.

The most important part of the framework is the property configuration file. In order to have the perfect CSS –or the closest thing to this concept– you have to configure the properties file so that it only builds the necessary properties. The default framework has all the properties configured as false. That means that, throughout your development, if you want for example to have the possibility of having a class that brings the color, you must first go to the file of config_css.scss and look in the configuration for the line config-color. In this way, the preprocessor in the next construction will build the class .color - that you need, with the color that you specify in the variables file file, of course. In this way, you will always have strict control of what is produced and not what is not. If you stop using the color property, then you can go to the configuration file and turn the property to false. The idea of UCSS is that you always have the necessary classes, no more, no less. As an example, this website, was built 100% entirely with UCSS framework and the final size compressed is 1.142 bytes. That is almost nothing, nothing as 4 KBs of code that I directly put in the HEAD of the each document. No delays. We go from 55ms processing to 5ms.

Once we know which CSS property we want to use, for example: display, word-break, etc. now we only need to finish configuring the values that we will need for each of these properties. To do this, we need to open the _vars.scss file where we will find the Sass maps with the possible values for each CSS property. For example, for display we will see:

$displays: (
  // none,
  block,
  // inline,
  // inline-block,
  // flex,
  grid
  );

In the variable file, we will find the map displays with these values. In this example, displays has the values none, inline, inline-block, flex commented and has block, grid enabled. If we uncomment any of the display property in the configuration file, the framework will process everything and generate these classes:

.display--block {
  display: block
}

.display--grid {
  display: grid
}

If we want to enable flex, you simply need to remove the comment from the //flex line, and the Sass generator will compile it in the next build. It’s that simple: in the variable file you can also create your own values, both for the colors and for the scales of padding and margin among other properties. It is a convenient way to activate and deactivate property values and have total control of them.

This framework doesn’t output nice forms, or headers or hero sections. You have to build them using the set of classes on your own. This is freedom. You will never have to overwrite dozens of lines of preset CSS to achieve your design, in fact, you will be astonish how tiny the CSS will become and how easy to mantain your project will be.

Were we are now

Creating this methodology requires data, a lot of data to be sure of its effectiveness. In the last 6 months, I have created code with UCSS both in projects for clients and as examples to measure the performance between the real example and my example of UCSS. I would like developers to use UCSS in their projects so that this project continues to grow and become more solid over time. The more examples we have of UCSS, the more we can understand the possible problems that it may have (although I do not find too many). If you have a project that is using UCSS, let me know.


Previous: January 05, 2016
Next: Jan 05