Why Your CSS Code Is a Slow, Broken, and Hard-to-Manage Mess
CSS: A Source of Trouble
CSS plays a vital role in creating web apps. Despite its simplicity, working and maintaining large CSS codebases is becoming a headache for most developers.
In this article, I explain the CSS mistakes that lead to slow loading, and unresponsive and unmaintainable code bases of web apps. We will discuss how to avoid those mistakes and the tools which help to overcome these mistakes.
Why CSS Code is Slow?
Unoptimized CSS can lead to slower web pages. Consider this graph.
In this case, the conversation rate is inversely proportional to the page speed. The more unoptimized CSS there is, the slower the page loads, and the lower the page traffic and conversation rate.
Larger CSS Files
The larger the stylesheet, the longer it takes to download and process into a CSS Object Model. Larger CSS files contain more data, resulting in increased file sizes. When a user accesses a web app, their browser needs to download the CSS file associated with that app. The larger the file, the more time it takes to transfer over the network, especially on slower internet connections.
In this example
The smallest CSS file in this list fonts.css
, which has a size of 627 bytes, took 69 milliseconds to load. The other CSS files took more than 100 milliseconds to load.
Reduce CSS File Size Using PostCSS
PostCSS is a tool for transforming styles with JavaScript plugins. It operates on parsed CSS through a series of plugins.
Let's see an example of optimizing a css file using PostCSS. This is a css file with a size of 269 bytes.
body { font-family: 'Arial', sans-serif; } .container { width: 100%; max-width: 1200px; margin: 0 auto; } .button { background-color: #3498db; color: #ffffff; padding: 10px 20px; border: none; border-radius: 5px; }
To Minifying this CSS file, First, install and configure PostCSS
npm install postcss --save-dev
Configure the plugin in the project
module.exports = { module: { rules: [ { test: /\.css$/, use: ['style-loader', 'postcss-loader'], }, { test: /\.jsx?$/, use: ['babel-loader', 'astroturf/loader'], } ] } }
Now run the PostCSS command for the css filestyles.css
npx postcss styles.css -o styles.min.css
The file size is now 179 bytes, down from 269 bytes. This means that PostCSS removed 90 bytes from the original file, a 33.46% reduction.
Let's consider a larger css file having a size of 1kb
The optimized size of this same file is
The larger the file, the larger the changes. For faster load time make the CSS files smaller.
Unused Styles
Browsers need to parse and process the entire CSS file to create the CSS Object Model (CSSOM) and render the app. Including unused styles increases the processing overhead, as the browser spends time analyzing and applying styles that have no impact on the visible content.Which gradually leads to the slow rendering of the app. We can reduce the file size by removing unused styles. The best and easiest way to find out how many CSS styles from a stylesheet is used in your code from Chrome DevTools.
- Go to your website or web app.
- Open the Chrome dev tool using
ctrl+shfit+i
. - Then open the command palette using
ctrl+shift+p
. - Now press the refresh button.
- Engage with your page so that all possible CSS are loaded and used.
You can see the percentage of unused code in the coverage panel.
For this project, 93.5% of css styles are not used for the current page.
What we can do is split the larger stylesheet into smaller bundles and use it on appropriate apps.
Split CSS based on Media Queries
One approach for solving the above problem is to split the larger css stylesheet into smaller chunks based on media queries. PostCSS has plugins for this, such as node-css-mqpacker.
<link rel="stylesheet" href="index.css" media="all" /> <link rel="stylesheet" href="mobile.css" media="(max-width:44.9375rem)" /> <link rel="stylesheet" href="table.css" media="(min-width: 45rem)" />
The browser will load the appropriate stylesheet based on the device screen size.
For example, on mobile screens, it loads mobile.css
first and other css files later.
In the desktop, the desktop.css
loads first
Why does CSS break on Different Screens?
Mobile First
It's usually better to start building for mobile screens than desktop screens. According to this statistic,
More than 50% of users access web content from mobile devices. A survey conducted by Experience Dynamics says 48% of users say they feel frustrated and annoyed when on sites that are poorly optimized for mobile.
Decide the Layout System
It is best to choose a proper layout system for your web app in the early stages of development. Both flexbox and grid layout systems have their purposes and uses. The question now is when to use Flexbox and when to use a grid system.
A simple one-dimensional Layout using Flexbox
In this first example, I am using Flexbox to lay out a set of boxes. I have five child items in my container, and I have given the flex properties values so that they can grow and shrink from a flex-basis of 150 pixels.
<div class="wrapper"> <div>One</div> <div>Two</div> <div>Three</div> <div>Four</div> <div>Five</div> </div>
* { box-sizing: border-box; } .wrapper { border: 2px solid #f76707; border-radius: 5px; background-color: #fff4e6; } .wrapper > div { border: 2px solid #ffa94d; border-radius: 5px; background-color: #ffd8a8; padding: 1em; color: #d9480f; } .wrapper { width: 500px; display: flex; flex-wrap: wrap; } .wrapper > div { flex: 1 1 150px; }
Result:
As you can see four and five are wrapped into a new line. And it shares the available space in the bottom row. In flexbox, the space distribution happens across the flex line.
A simple two-dimensional Layout using a grid
Let's implement the same layout using the grid system. The HTML remains the same. In CSS add grid layout inside the .wrapper
selector.
/* ... existing css */ .wrapper { display: grid; grid-template-columns: repeat(3, 1fr); }
Result:
As you can see they stay in a strict grid, lining up in rows and columns.
Flexbox is excellent for arranging items in a single row or column. It's well-suited for creating flexible and dynamic layouts along a single axis. On the other side, the grid system is designed for both rows and columns, making it powerful for creating complex, two-dimensional layouts.
If you wish to control the layout along either rows or columns, use Flexbox.
If you wish to control the layout using both rows and columns simultaneously, use Grid.
Why CSS Code is Hard to Maintain?
CSS code can become challenging to maintain for various reasons, and these challenges often arise as web projects grow in complexity. Some of the better ways to maintain css are:
CSS Variables
Using CSS variables can make stylesheets more maintainable and allow for easier theming.
Without CSS Variables
.card { background-color: #3498db; color: #ffffff; border: 1px solid #2980b9; } .card:hover { background-color: #2980b9; }
With CSS Variables
:root { --main-color: #3498db; --text-color: #ffffff; --border-color: #2980b9; } .card { background-color: var(--main-color); color: var(--text-color); border: 1px solid var(--border-color); } .card:hover { background-color: var(--border-color); }
CSS variables (--main-color, --text-color, --border-color)
are defined at the :root
level, making them accessible throughout the document. If we want to change the color scheme we only need to update the value in :root
level.
Shorthand Properties
Using shorthand properties helps keep your CSS code concise and improves maintainability. Here are some examples of using shorthand properties:
body { background-color: #f5f5f5; background-image: url('background.jpg'); background-repeat: no-repeat; background-position: center center; }
The background properties in this css block can condense into single-line:
body { background: #f5f5f5 url('background.jpg') no-repeat center center; }
Same for applying transitions
button { transition-property: background-color, color; transition-duration: 0.3s; transition-timing-function: ease-in-out; }
With shorthand properties, we can simplify into:
button { transition: background-color color 0.3s ease-in-out; }
Tools For Better CSS Management
There are various tools available to handle your css styles efficiently some of the tools are:
Purge CSS
PurgeCSS will help to figure out and remove the unused styles. It analyzes your HTML, JavaScript, or other files to identify which CSS classes are not being used and then removes them from your stylesheets. Purge CSS can also plug with PostCSS. Find more about purge CSS here.
Emmet
Emmet is another open-source web development toolkit which simplifies developers' workflow. It provides a set of abbreviations and shortcuts that allow developers to quickly generate HTML and CSS code with less typing. For example, if you want to generate a shorthand property for border do bd1-s#f.5
This will expand into:
border: 1px solid rgba(255, 255, 255, 0.5).
- Find more information about Emmet here.
- Emmet also has a VS Code extension.
Styelint VSCode Extension
Styelint VS Code extension helps to avoid css errors and enforce conventions.
Stylelint helps to figure out:
- Invalid things, e.g. malformed grid areas.
- Valid things that are problematic, e.g. duplicate selectors.
- Unknown things, e.g. misspelled property names.
Find more about stylelint here.
Conclusion
Cascading Style Sheets (CSS) may appear to be simple at first glance, but once you start working with them, you'll discover that there are a lot of rules and complexities involved. The best way to deal with these complications is to start by simplifying CSS, optimizing it, and properly maintaining it from the start of the project. There are a variety of tools available to assist you in better CSS management. The more effectively you handle CSS, the smoother your web app development will be.
Reference
Flexbox - Learn web development | MDN Grid - CSS: Cascading Style Sheets | MDN Shorthand properties - CSS: Cascading Style Sheets | MDN Mobile experience survey