graphicpush

Thoughts on branding, design, writing and life by Kevin Potts. Established 2003.

Drink Your Medicine and Use CSSLint

So CSSLint is a great new tool to help you write more modular and efficient CSS. But it’s warnings can be a bit abstract, and offer no supporting explanation. Hopefully my interpretation will help. It is not perfect, and I encourage dissenting views on any of it.

The release of CSS Lint has brought a lot of great discussion to the web about what exactly are best practices for writing complex style sheets. Developed in part by Nicole Sullivan, who has her distinct take on what she calls object-oriented CSS, the tool parses a CSS file and outputs a slew of flashing red lights, hazard signs and doomsday sermons about how to make your shit CSS more efficient.

With CSS, like any language, there are many ways to say the same thing. As a developer becomes comfortable with syntax and capabilities, deep habits become ingrained, and Teflon-like resistance to change starts to form. We are, after all, fucking experts.

A lot of feedback has been predictably negative (example). I understand. I ran an old 100k stylesheet through the tool and received over 1,200 slaps in the face. My first reaction was “get off my lawn”.

But in working through complex CSS files for large sites recently, and looking at how I used to write styles compared to how I’m starting to write styles, the object-oriented approach makes a whole lot of sense. It’s not any different than graduating from a simple mailer script to a complex application using a server-side language: at the end of the day, you must find efficiency or you will mentally drown in a sea of repeating code and everyone on your team will want to pummel you like the printer from Office Space.

The object-oriented approach, frankly, is the right approach. Here are some thoughts on the more frequent warnings.

Don’t use IDs in selectors.

A major point of contention. This is not an error, but a warning — maybe the most commonplace. The thought-process behind this lays squarely in the concept of an object-oriented approach, which means building a CSS file of re-usable blocks with class names, not IDs. But why class names? Several reasons:

  • Classes can be repeated infinitely across the HTML. So you can have <div class="post"> and <div class="post lead"> and the styles for “post” will apply on both. “post” as a style becomes a building block — again, a tasty portion of reusable styles.
  • IDs are meant to identify unique sections of a document. In my opinion, they should be used only where a user could theoretically navigate to, not arbitrarily describing a section of the content.
  • IDs have a much higher weight than classes or element names in the chain of specifity, as explained very well in the article Taming Advanced CSS Selectors. When simple chains of classes are used, it becomes much easier to troubleshoot problems with the cascade.

This article by Oli Studholme also dispels several myths about using IDs as selectors in CSS.

X IDs in the selector, really?

Sort of conflicts with the above warning, but if you must use IDs as selectors (and that can certainly be argued until the sun goes supernova and swallows the earth), this is a valid flag. The concept behind IDs is that they are unique. Nesting them inside other unique elements is redundant. So this:

 #header #brand #logo { styles ... }
 

is, theoretically, the same as this:

 #logo { styles ... }
 

Writing a chain of selectors is comforting. By specifying this thing inside that other thing inside that even bigger thing, it creates a blanket of protection against conflicting styles. We have 100% confidence that nothing will fuck with #logo in the first example. When #logo stands alone, defenseless, we’re trusting ourselves not to break it further down the CSS file. This is hard. Because while we are experts, we’re also idiots, especially those other guys on your team jacking with your stylesheet.

Element (X) is over qualified

Specifying an element with a selector gains no speed improvement. (This is the opposite of jQuery, where specifying an element speeds up the selector engine.) When you over qualify a style’s selector, it also hamstrings its ability to be re-used.

My opinion: there are valid exceptions. For instance, say you have a form where required fields have an input and an associated label. If there is an error on the input, I typically generate a class of “error” for both the label and the field. The CSS, obviously, needs to be told which element to style, so it might look like this:

 .error { /* styles that apply to anything that gets an error */ }
 label.error { /* styles for just the label */ }
 input.error { /* styles for just the input */ }
  

Float can’t be used with display: inline.

Errors like this are the downside of dealing with robots. Of course a floated element can’t be an inline element; it makes no logical sense and the spec clearly states that anything floated is set to display: block; automatically. All browsers obey this rule, even IE6. However, back in the day, grumpy grandpa IE had the nasty double margin bug that was easily fixed by specifying display: inline; to the element.

So if you’re still supporting IE6, this is a mandatory hack for maintaining stable layouts. But if your agenda is to please the CSS Lint robot overlord, move any IE-specific rules to IE-specific style sheets.

Heading (h1-h6) should not be qualified / has already been defined.

Ideally, a website whose styles apply an object-oriented approach would treat each header level as a building block that is defined once, and is simply re-used across the rest of the site. So an <h3> in a sidebar looks the same as an <h3> in the center column. In theory, this is a Good Idea. In practice, it’s a Mid-East turf war.

Sometimes a header in a contextual area simply needs an altered appearance. The core font styles may be the same, but maybe it’s a different color, or slightly smaller. The HTML5 spec complicates this even more by allowing <h1> to be used more than once.

Too many floats (X), you’re probably using them for layout. Consider using a grid system instead.

This falls squarely into the object-oriented methodology. I ran a lint on a site I wrote and found 94 individually defined floats, which, in hindsight, is obscene, but is a natural byproduct of years of attrition. This is a relatively easy problem to fix, however, if you re-engineer a site. Using a predefined grid system like 960.gs is an option, but I opted for something much simpler:

 .wrap { overflow: hidden; }
 .left { float: left; }
 .right { float: right; }
  

This allows me to define any block as a wrapping shell, or something that should go to the right or left. Even in the most complex layout, this simple abstraction through classes has simplified my life ten-fold.

Conclusion: CSSLint is a high-maintenance bitch that demands adherence to its strict policies, but obeying leads to a shift in writing CSS that is ultimately lighter, less prone to galactic specificity battles, and much easier to maintain. Do the right thing.

commentary + criticism

Isofarro

wrote the following on Thursday July 21, 2011

> but I opted for something much simpler:
> .wrap { overflow: hidden; }
> .left { float: left; }
> .right { float: right; }

Seriously? You optimised your CSS for CSSLint and compromised a clear separation of content and presentation.

Now you need to have a class of left on every element that needs to be floated left. If you then decide to float one of those right, instead of changing the one true source of style – the CSS, you now have to modify the HTML?

What happens when everything that’s floated left must change to being floated right, are you going to go through every HTML page and template changing the class of left to a class of right, or are you going to change the stylesheet to leave yourself with .left { float: right; } ?

Frankly, this is exactly the scenario I feared with inadequately thoughtout tools like CSSLint. You’ve fallen right into the nasty pit CSSLint has opened.

I’d strongly suggest spending more time learning about CSS from reputable sources (like Eric Meyer, Ian Pouncey) than trusting a tool like CSSLint without critical thought.

Stuart Charlton

wrote the following on Thursday July 21, 2011

Nice piece Kevin.

In my experience, after years of reaching for an unobtainable standards nirvana it’s requiring a bit of an ideological leap to embrace Nicole’s approach.

I’m still not sold on all of it (the bits I choke hardest on are the presentational slant to the classes). But I do see value in the pragmatism, and there are clear gains to be had if it’s used in the right context.

Cedric Dugas

wrote the following on Thursday July 21, 2011

Using a grid systeme is fine when you don’t work in an agency with fancy designers that don’t want to be put on a grid and still have pixel perfect templates

I think the biggest problem with csslint is not the tool itself, its the name, its not oocsslint, its called csslint like the defacto standard tool you need to check your css with, like with jslint.

And also, the ‘messages’ provided are really poor (or was the last time I checked?), like you use too many floats after 10… heuuu ok.. why is that?

As for ID’s.. I think this is a ridiculous discussion, I use ID’s parsingly, did relatively big websites, with multiple front-end devs and still had no maintenance problem.

You would have exactly the same problem with .conainter > .anotherContainer > .something

I think its highly likely that if your abusing the ids you will have the SAME problem with class’s

Kevin

wrote the following on Thursday July 21, 2011

Isofarro — perhaps I was not clear. The wrap/left/right thing is something I started to do about two years ago, not something I did to optimize for CSSLint. I have not rewritten anything for CSSLint, actually. But using three simple classes allows me to easily structure blocks without using a complex grid system, and my entire CSS file only defines floats once instead of 90 times. It is just my way of applying simple abstraction. I understand that it’s not perfect, but it works.

Stuart — it’s taken me a long time to come around to classes, but three things reinforce my decision:

# it’s precisely what the class attribute is for, versus IDs being fragment identifiers # I find myself avoiding specificity wars, and writing much less duplicative styles. I would rather the page weight have a few bytes more of class information than the CSS file have kilobytes of repetitive styles # other people reading my work can much more easily understand how things are being styled

If there’s one thing I hate, it’s trying to reach standards nirvana. The real work world does not have time for religious zealotry. But I do try to constantly adopt practices that work for me, and objected-oriented CSS, after a bit of brain rearrangement, works.

Isofarro

wrote the following on Thursday July 21, 2011

> But using three simple classes allows me to easily
> structure blocks without using a complex grid system,
> and my entire CSS file only defines floats once
> instead of 90 times. It is just my way of applying
> simple abstraction. I understand that it’s not
> perfect, but it works.

The use of .left { float: left; } is not an abstraction, that’s just one step the other way, closer toward inline styles, which is the farthest point from an abstraction you can get in CSS.

An abstraction is a higher level concept above CSS. So it should add meaning, not take it away. What you’ve done is remove a meaningful abstraction to one where you seem to have a one-to-one mapping of a class name and a specific instance of a style property.

I’m fairly sure this is not what Nicole Sullivan intended when she decided that lots of floats were a problem. Her advice for reducing floats was to use an abstraction, as in, find the commonality of reason why these elements are floated, and create a meaningful structured layer to express that commonality of purpose. Like a structured layout strategy using a family of related classes.

Doing the opposite isn’t an abstraction. You have a system where every element needs to indicate it wants to be floated left without considering the broader pattern in effect. You are moving in the wrong direction, and suggesting to others to do likewise.

It is the purpose of the apparent pattern that drives the abstraction. The class names that come out of this will be things like “grid-column-unit” and “pullout”. These are reasons for groups of elements to be floated, and thus be part of an abstraction to compose those features into a common reusable set.

To be fair, this is not entirely your fault. You’ve just stumbled across a badly thought-out and implemented tool in CSS Lint that suggests it justifies what you consider to be an abstraction.

Kevin

wrote the following on Friday July 22, 2011

Isofarro — You make great points, and I understand your argument. “Abstraction” is not the correct term; let’s try “simplification.”

I find zero difference in applying a class of “left” versus a class of “container_12” or whatever from a grid system. Both dictate structure versus semantics; they describe how the block is positioned on the page, not what the block is. If I were using 960.gs and wanted to shift a set of blocks over, I would have to change or add styles to everything to do that. Same problem.

Let me give you an example of where this comes in handy. Imagine a CMS, where a site manager edits content, curates photos, etc. So they want to insert a photo or diagram into the flow of a column of text. I’ve built them a set of styles they can apply to the image to do that, and all they have to do is add something like class=“inset-pic right” OR class=“inset-pic left” and it all magically works.

In my defense, using left/right/wrap classes is really the only time I apply this type of going-in-the-opposite-direction-of-true-abstraction “simplification”. I try to make everything else semantically sound, and cleaner. I completely understand your argument; this is simply a strategy that works for me and may not be applicable to everyone else.