No more external CSS

There is no need for external files in an Application

One day I woke up and decided to remove all external CSS from my websites. And every website I build consequentially will have no external CSS. No one noticed anything on my website except the speed increase.

Why we use external stylesheet?

The reason we use external stylesheets is because it helps separate logic from presentation. It's rare to see a website that is not dynamic in a sense. The majority of websites run using PHP or some dynamic language. This means, every time you make a request the web page is built from scratch.

There are many components that makes up a page. For a simple blog like this one, there is the header, the footer, the navigation, the blog content. Other website have different kind of widgets, like a side bar with the latest comments, or third party services and such.

Each of those have to be built and styled differently. Having external stylesheets allows us to keep these clean of CSS. Meaning, the HTML will be built in its own file, the logic that powers it will have its own, and the CSS that makes it appealing will have its own too.

This in theory makes it very organized, and allows for any developer to join your team and know where everything is located.

Why I ditched the external stylesheet.

Unfortunately, in the real world it does not work out this way. Every project I worked on had massive CSS files that everyone keep appending to with no real structure. At the end of the day, we have to create multiple CSS files to make it a tad bit more organized.

The problem arises when you load all these stylesheets into the document. For each request, the browser has to stop the rendering of the document and download the file. The page takes much longer to load and each end up downloading more stuff than are necessary to render properly.

For example, if you are on the content page, you end up downloading stuff from the about us page because it would be too hard to separate the stylesheet by section. Many people started using tools to minify the CSS, but it still leaves you with a disorganized CSS that still has to be downloaded separately.

Think for a moment about a feature you built, then your manager decides that the it should be removed. If it has many dependencies, it is nearly impossible to track all the places where you made changes to accommodate his request. Chances are you will leave some in the code since they don't break other parts of the website.

So I decided to reorganize the CSS to be modular, just like the rest of the website. Removing CSS is hard, because there is no easy way to track which page is using which CSS. One thing that made my life easier, is that long before, I had started to use the BEM scheme to write my CSS. So it is much easier for me to move CSS rules to different files.

Here is how I did it.

Every module on my website will specify which CSS it needs. For example, the default layout will say that it needs layout.css, the blog post page will say content.css, the comment section will say comment.css, and so on.

Here is an example of the website default layout:

<?php
/**
 * The main template for most of the website.
 */

// Let's start with CSS shall we?
$view->addCSS("Blog:Main:reset.css");
$view->addCSS("Blog:Main:general.css");
$view->addCSS("Blog:Main:layout.css");

// The current page template
$subTemplate = $view->render($render,array("content"=>$content));

// the page header template
$pageHeader = $view->render("Blog:Main:Widget/pageheader.html.php");

// the footer template
$footer = $view->render("Blog:Main:Widget/footer.html.php");
?><!doctype html>
<html lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title><?php echo $view->getSlot("title")?></title>
    <?php echo $view->getMeta();?>
    <link rel="shortcut icon" href="<?php echo ASSET_ROOT?>/favicon.ico" />
    <link rel="apple-touch-icon image_src" href="<?php echo ASSET_ROOT?>/apple-icon.png" />

    <meta name="viewport" content="width=device-width, initial-scale=1" />

    <!-- This is the method that processes all the CSS -->
    <?php $view->printCSS();?>

    <!-- #MIN-CSS -->
    <link type="text/plain" rel="author" href="http://idiallo.com/humans.txt" />
</head>
<body>
<?php echo $pageHeader;?>

<?php echo $subTemplate;?>

<?php echo $footer;?>
</body>
</html>

This in a nutshell is my website. Note that on top of the file, I add all the CSS necessary for this page:

$view->addCSS("Blog:Main:reset.css");
$view->addCSS("Blog:Main:general.css");
$view->addCSS("Blog:Main:layout.css");

Each CSS file has its purpose and using a static variables I make sure they are added only once. Further down, I call a function to render the page header and here is what it looks like:

$pageHeader = $view->render("Blog:Main:Widget/pageheader.html.php");

Inside the pageheader.html.php template, I also call the necessary CSS for that template.

<?php
$view->addCSS("Blog:Main:Widget/pageheader.css");
?>
<header class="master-header">
...

The advantage is, if I ever decide to create a new header, I can simple create a new file and add its own css. I don't have to hunt down its css rules in the CSS files.

When all the templates are added to my static variable, I simply process them with the printCSS() function and they are all printed directly on the page. I previously wrote about how to minify CSS in php so you can look it up for guidance.

Obviously recreating the same CSS on every request could slow the website down. So I decided to make it faster using memcached. I created a unique key based on the name of all the css files needed for that page. Here is the self explanatory code I used:

$signature = md5(implode("", array_keys(self::$cssFiles)));
$memcache = new MemCache();
$value = $memcache->get($signature);
if ($value !== false){
    $result = $value;
    return $result;
}
$result = "<style type=\"text/css\">".self::minifyCSS(self::implodeCSS())."</style>";
$memcache->set($signature, $result);
$memcache->set($signature,$result,self::CACHE_ONE_DAY);
return $result;

I create a key based on the file names, md5 it to be a short unique key and check if it exists. For my particular framework, I set the debug environment to not use memcached to make it easy for me to develop on my machine.

The pros

The CSS is organized. The files are not publicly accessible. I can easily add or delete files without bloating the CSS with unused rules. I don't need to make extra requests to fetch the CSS meaning the page loads exceptionally fast.

With BEM, there is no need to guess which CSS does what, each rules is named according to the template and CSS file they use. So there is very little confusion. Visually, the user won't notice the change.

The HTML and the CSS benefits from the gzip compression of the web server, making them overall smaller and faster to serve.

The Cons.

Since the CSS is a bunch of small files that are concatenated in a big one, you can't use chrome inspector tool or any browser tool to find the exact line number where the rule is. But this could be compensated by the fact that all the files are small and the naming convention allows you to find which file handles which rule.


Conclusion.

It used to make sense to separate each file into external stylesheet if you where building static pages. But now every website is an application, and we can make use of its dynamic to programmatically generate files.

This results is well organized css and faster web pages. Let me know what you think in the comment section.

Next up will be, removing external JavaScript files.


Comments

There are no comments added yet.

Let's hear your thoughts

For my eyes only