The introduction of CSS preprocessors have solved a lot of problems. They have made CSS easier to maintain, update and modularise but they have also lead to a bloated CSS file when no attention is paid to the outputted CSS. A perfect example of this is the use of functions when in many cases the CSS attribute selector could and should be used, for more information on the attribute selector check out this awesome post on 24ways by Nathan Ford.

For example, here is some code I wrote without using the attribute selector:

.button(){
	.border-radius(20px);
	text-transform: uppercase;
}
.button-hollow(){
	.button();
	padding: 5px 20px;
	color: @red;
}
.button-full(){
	.button();
	border: 0;
	padding: 10px 25px;
	color: white;
}
.button-full-gray{
	.button-full();
	background-color: @gray;
}
.button-full-blue{
	.button-full();
	background-color: @blue;
}
.button-hollow-green{
	.button-hollow();
	border: 5px solid @green;
}
.button-hollow-blue{
	.button-hollow();
	border: 5px solid @blue;
}

which when compiled looks like this

.button-full-gray {
  -webkit-border-radius: 20px;
  -moz-border-radius: 20px;
  border-radius: 20px;
  border: 0;
  text-transform: uppercase;
  padding: 10px 25px;
  color: white;
  background-color: #b9b9b9;
}
.button-full-blue {
  -webkit-border-radius: 20px;
  -moz-border-radius: 20px;
  border-radius: 20px;
  border: 0;
  text-transform: uppercase;
  padding: 10px 25px;
  color: white;
  background-color: #84e1ff;
}
.button-hollow-green {
  -webkit-border-radius: 20px;
  -moz-border-radius: 20px;
  border-radius: 20px;
  border: 0;
  text-transform: uppercase;
  padding: 5px 20px;
  color: #ef4c76;
  border: 5px solid #55dbd4;
}
.button-hollow-blue {
  -webkit-border-radius: 20px;
  -moz-border-radius: 20px;
  border-radius: 20px;
  border: 0;
  text-transform: uppercase;
  padding: 5px 20px;
  color: #ef4c76;
  border: 5px solid #84e1ff;
}

For every full button there’s 7 lines of repeated CSS and for every hollow button there’s 6 lines of repeated CSS. This isn’t really a problem on smaller websites but imagine you’re building a web app with 30 different buttons – that is 195 lines of CSS you didn’t need. Now imagine you take this approach on 10 more components those lines begin to add up and all of a sudden you have nearly 2,000 lines of completely unneeded CSS! Worse, should someone come along in the future who is unfamiliar with your chosen preprocessor, or prefers to write CSS directly, they now have to contend with bloated unmodularized code.

The alternative is to use the CSS attribute selector so the above code refactored looks like this:

[class*=button]{
	.border-radius(20px);
	border: 0;
	text-transform: uppercase;
}
[class*=button-hollow]{
	padding: 5px 20px;
	color: @red;
}
[class*=button-full]{
	padding: 10px 25px;
	color: white;
}
.button-full-gray{
	background-color: @gray;
}
.button-full-blue{
	background-color: @blue;
}
.button-hollow-green{
	border: 5px solid @green;
}
.button-hollow-blue{
	border: 5px solid @blue;
}

and when compiled:

[class*=button] {
  -webkit-border-radius: 20px;
  -moz-border-radius: 20px;
  border-radius: 20px;
  border: 0;
  text-transform: uppercase;
}
[class*=button-hollow] {
  padding: 5px 20px;
  color: #ef4c76;
}
[class*=button-full] {
  padding: 10px 25px;
  color: white;
}
.button-full-gray {
  background-color: #b9b9b9;
}
.button-full-blue {
  background-color: #84e1ff;
}
.button-hollow-green {
  border: 5px solid #55dbd4;
}
.button-hollow-blue {
  border: 5px solid #84e1ff;
}

Now when adding a button of any type I only need one line of CSS compared with the 7 or 8 lines above. Not only is this code cleaner it is easier for somebody writing pure CSS to maintain and dramatically reduces the amount of CSS generated.

I am by no means advocating the abandoning of preprocessor functions. Functions are perfect for things like getting prefixes right and creating CSS circles. So a little thought into whether the function you are creating will be different in every case and if you and any future developers would be better served by using the attribute selector will make life much easier and cleaner.

Filed under:   clean   code   css   functions   howto   preprocessor   tools