Stylesheet Code Style Commandments

2015-01-17 | #css, #styleguide

*Work in progress (still being expanded and linked to other guides)*

Like always, the General Codestyle Commandments (see links) apply before and in addition to the rules described in this article.


I: Thou shalt keep your selectors readable

body table > tbody td .text > em.marked

That's a very mediocre selector. Select a semantic entry point, such as a speaking class or id, then work your way to the element without being to specific or descending more than about three elements.

.article-detail-sheet .text .marked

That's better.


II: Thou shalt keep order in your attributes

Styles know lots of attributes and rules. As with everything else in life it helps if your attributes have a general order. This way you can always see at a glance what's defined (and how) and what's not. Even without fully reading the whole rule.

My attribute hierarchy for example is as follows:

1. display attributes

2. position

3. dimensions

4. box model

5. text

6. background

7. specials

8. browser-specific stuff / fixes

So a full fledged (nonsensical) rule might look like this:

#thatoneveryspecialthing {

display: block;

visibility: visible;

position: absolute;

z-index: 9999;

float: left;

top: 0;

right: 0;

bottom: 0;

left: 0;

width: 100%;

height: 100%;

padding: 20px;

margin: 10px 0;

border: 1px solid #fff;

font-family: arial, sans-serif;

font-weight: bold;

line-height: 1.25;

color: #000;

background: transparent url(../img/bg.jpg) no-repeat center center;

background-size: cover;

cursor: pointer;

-webkit-transform: translateZ(0)

}

Additionally you should keep the order of attributes approximately the same everywhere.


III: Thou shalt write identifiers and classes like the rest of the world

class="wonderFulClassX wonderful_class_x Wonderful-Class-X" and

id="Thing", id="tHing" or id="thing_thing"

are NOT acceptable.

Do write all classes and identifiers in small letters and seperate parts with dashes, not underscores!

There is no definite rule if you should separate words with dashes or use those for other semantic emphasis, just be consistent.


IV: Thou shalt use a preprocessor whenever possible

Complex CSS is getting pretty ugly pretty fast. Not to mention all the doubled values and missing automation. So, whenever you have the possibility to use a preprocessor as LESS, SASS or Stylus, please do so. Even though I'm not a big fan of LESS I'd rather edit complex LESS-sheets then those classical CSS-monsters any day. Basically any empowered syntax is better then pure CSS in terms of readability and expandability.

And the nice thing is: at the end it's pure CSS again and doesn't need any special stuff on the server. Just make sure to prepare and document the way to compile your sheets, so that others can follow up on you.


V: Thou shalt target all browsers equally, if possible

There are many modern rules, that currently operate with vendor prefixes on different browsers. Some of those browsers are some generations old, but are nonetheless still used. Those browsers need their prefixes or otherwise your pretty effects just won't show although the browser is very well able to do so.

caniuse.com is a good source to look up all those nifty variants for those prefixed CSS2 and CSS3 rules. As a rule of thumb: if it's from the last 5 years it'll most definitely have some prefixes besides the basic prefix-less variant.

When you define a rule having prefixes it's imperative to define those rules _additionally_ to the basic variant. Also, the order is important: since there are browsers accepting the _same_ rule in different prefixed and non-prefixed variants, you'll always want the non-prefixed one _last_, to always apply the most recent version:

.not-a-square {

-webkit-border-radius: 10px;

-moz-border-radius: 10px;

border-radius: 10px;

}

If this all seems sadly complicated and convoluted, just use "autoprefixer", which uses caniuse.com's database to automatically apply vendor prefixes to rules, defined by a target browser set. It's available for almost every build system out there and removes almost any headaches, that occur while targeting browser feature sets.


VI: Thou shalt define your styles semantically

There are defined levels of semantics in styles like in every other aspect of development. People tend to forget this. Every preprocessor and even CSS itself offer modularity through imports, so please use it to split your styles into logical, manageable pieces anyone would still want to read.

What might be good logical selectors to divide styles by? Well, first of all we always have basic definitions for basic tags like html, body, main, h1-h6, a and so forth, that might be a good starting point. Then your website will, most likely have some kind of basic, global layout, defining how stuff in the header, main and footer generally behaves. You could even define that separately. Then you might have different page types for example. You'll most likely also have some kind of self written widgets or modular pieces, you'll use at different places.

There you go. One import for each of those points imported into a main stylesheet and you've got a workable set of stylesheets, where it should be clear where to search for what.


VII: Thou shalt keep DRY

Don't Repeat Yourself. This is a general rule as well, but I'll include this here again, because styles, especially without a preprocessor, aren't as easy to put into this paradigm as a programming language. As a general rule of thumb: if you are writing the same selector twice, you're likely to do something wrong. If you are styling a part of the page, that you also specifically styled somewhere else, you should ask yourself if this has a good reason (like building a theme by overwriting something consciously) or you are just being a lazy bastard, not wanting to search for the right spot and making the sheet a pain to read and edit for anyone else.

There is a very fine line between "this is by design" and "this is terribly irritating and mostly bullshit". Always ask yourself critically if someone else could still understand your structure, know where to search for things and most importantly: find all the relevant spots to redefine something. Expert tip: if you need the search function to comb the stylesheets you are doing it very wrong.


VIII: Thou shalt keep in mind the specificity of selectors

To determine which rules apply to which element and which rules are more important than others, browsers use something called specificity. In simple terms: each style gets a number saying just how specific or special that rule is, determined by adding certain values for each component of the rule. A tag gives 1 point, an attribute value such as a class gives 10 and and id is worth a 100 points. So "body p.foo.bar" would be worth 22 points. This already shows a problem: using an id pretty much makes it impossible to get more specific without using the id again. So ids should be used extremely sparingly and you should stick to elements and classes. By the way: pseudo-elements count 1, exactly as normal elements. So :hover is worth 1.

The only wormhole around specificity is "!important", which takes precedence over every specificity. This shortcut exists for an important reason: inline styles are worth 1000 points! Without "!important" we would never be able to overwrite those.

So keep in mind this concept whenever you're dealing with classes, ids and styles. Keep to classes at most if you don't have a real good reason for not doing so. Remember: there might be people who'll want to write print styles for your stuff. Using ids forces them to rebuild all selector chains instead of just changing selectively what needs to change.