Disclaimer: This intent of this document is to discuss ways to improve upon existing build tools in a pragmatic but positive manner. If anything is unclear or if you have any questions, please raise them as a Github issue.
The loose decoupled nature of HTML and CSS makes it difficult to safely remove unused rules and determine what rules may conflict with each other. Not only that, but various browsers vendors such as Internet Explorer and Safari either lag behind the latest standards by half a decade or implement a feature erroneously, which pushes additional development effort to the website or web app developer.
We don't only want this tool to solve the above problems, but solve them well. This means a few things:
We want to solve this problem in a way that will be a good fit for both large JavaScript build tool projects as well as for a time and budget-constrained work.
If you aren't aware, to get an idea of the time constraints some web developers are under, especially beginners, Im talking about projects that have about 45-90 hours of total budget. That means a CMS backend with modules or plugins needs to be setup, the frontend needs to be built and then finally all that code needs to be put on a remote server in 2 weeks.
Another consideration is quick quoted work that can take anywhere between 1 to 6 hours. If you quote a client with 6 hours of work, then you most likely aren't going to be able to prioritize HTML and CSS cleanliness if you underestimated the effort. However, having a tool that just tells you what's unused or that could just cleanup unused rules for you, would save a lot of time and improve readability.
Before considering building yet another tool, we should look around and see if there's anything out there that will be able to solve the problems we have.
One common thing I've listed as a "Con" below is the reliance on a JavaScript build tools. The reason for this is that in my experience when doing budget-constrained work, you don't have time to deal with the inertia and unreliability that comes from using these tools.
Here are a list of tools or resources that help assist you in finding what CSS rules are being used.
A tool built-in to the Chrome web browser which can help you discover unused CSS styles.
Pros
Cons:
Tools that integrate with a JavaScript Build System and generate identifiers so that when a CSS rule is removed, a variable will become undefined thats tied to that CSS rule.
Implementations:
Pros:
Cons:
Pros:
Cons:
Here are a list of practices or tools that were designed to stop CSS classnames from conflicting with each other and that also keep CSS specificity low, which helps reduce cognitive complexity.
Pros
Cons
Pros
Cons
Here are a list of tools or resources that help assist you in finding what HTML is valid and what CSS rules are supported.
A website that tells you whether your HTML is correct or not.
Pros
Cons
A website that will tell you what features are either partially or fully supported in a browser.
Pros
Cons
Now that we've defined at least some problems, let's looks at some things that our tool will need to be able to solve.
In a legacy HTML or CSS project, nested CSS is definitely going to exist in the project. By nested CSS, we mean a selector such as ".myElement .myOtherElement". Due to the nature of various legacy systems and also with how Wordpress works, this tool is going to need to be able to reason about how templates include other templates so that it is able to build an accurate model of the varying HTML structures to see if that CSS rule is used or not.
This becomes more complicated as different backend configurations could completely change what CSS classes get rendered. If a user has a website wherein a client is configuring CSS classes directly and storing them in a database, we are limited in how much an external tool can reason about what is used / unused.
ie.
<div class="<?php echo $myClasses; ?>"></div>
$myClass came from a MySQL database or something that we have no control over.
One solution to this problem is that a user could add additional code so that a tool could reason about what classes exist in scope.
<?php
$classesAvailable = [
“button” => true,
“button-primary” => true,
];
// Split string of classes into an array of class names.
$classes = preg_split('/\s+/', $myClasses, -1, PREG_SPLIT_NO_EMPTY);
$myClassesValidated = “”;
foreach ($classes as $class) {
if (isset($classesAvailable[$class])) {
$myClassesValidated .= $class;
}
}
?>
<div class=”<?php echo $myClassesValidated; ?>”>
</div>
By doing the more verbose approach above, we've given the compiler enough information to know that $myClassesValidated can only have up to 2 classes, "button" and "button-primary".
Another solution is that within our CSS, we simply add a note that states that we don't want the compiler to check if that rule is used or not. This would also be useful for stateful CSS classes that the tool might not be able to reason about. Ie. JavaScript applied classes
// fel:unchecked
.button {
display: block;
}
Linting tools such as TypeScript Lint allow you to ignore rules certain properties / patterns with a code comment.
Finally, we could avoid needing to get an accurate model of the HTML by forcing developers to use something like BEM or CSS Modules, wherein they keep rules simply by only targeting 1 class without nesting.
There should be built-in rules to stop users from using incorrect HTML tags. For example, using an anchor link as a button should be banned by default, ie.
<a href="#" class="btn"></a>
Would recommend you switch to:
<button type="button" class="btn"></button>
or at the very least, apply the button role.
<a href="#" class="btn" role="button"></a>
There could also either be built-in or user-defined CSS rules that assist with:
Use cases for our tool
To keep code written in this tool stable and reliable with minimal complexity, simply reading or validating multiple file formats seems out of the question. New features are being added to PHP, JavaScript and TypeScript all the time which could break the parser of our hypothetical tool. If this tool is to have strong backwards compatibility, it will most likely need its own format for templating that can at least target PHP, JavaScript and TypeScript. Ideally it would give it's users the ability to target whatever esoteric template language it needs to.
However, just because we may need our own template parser, that doesn't mean it needs to be its own special esoteric syntax or language. Infact, just using HTML with something simple like Mustache template syntax might be all we want.