Wednesday, April 03, 2013

All In The Family: Grouping CSS Selectors

Grouping CSS Selectors

Grouped selectors are one of the most efficient ways of reducing your CSS to tight, clean, easily maintained code, while bringing the benefit of imposing a stronger, more consistent design.

The principle is simple: where properties and values are shared in a stylesheet, join the declarations and selectors into a single group. As one example, it's common to see repeated uses of the same font-family in a stylesheet:

h1 { font-family: Avenir, Arial, Helvetica, sans-serif; line-height: 1.4; }
p { font-family: Avenir, Arial, Helvetica, sans-serif; line-height: 1.6; }

It's far more efficient to join the selectors together as a group with shared properties and values, leaving the unique declarations separate:

h1, p { font-family: Avenir, Arial, Helvetica, sans-serif; } 
h1 { line-height: 1.4; } 
p { line-height: 1.6; }

You can group almost anything in a stylesheet: simple elements, classes, ids, pseudo-element selectors and more. Often the selectors in a grouped style will be determined before site construction begins, based a mockup, styletiles, meetings with clients or a style guide. You'll often find lengthy grouped selections in CSS resets.

Don't Forget Inheritance

It's the CSS equivalent of "not seeing the wood for the trees": seeing commonalities as you write your CSS, grouping them together and not realizing that you have so many elements chained together with shared rules that the styles should be inherited by every element.

If you start seeing grouped selectors like this in your CSS:

h1, h2, h3, h4, h5, h6, p, td, th { font-weight: 100; }

It's a fair bet that almost everything in your site has the lightest font-weight possible. In that case, simply eliminate the grouped selector and substitute this:

body { font-weight: 100; }

...addressing any exceptions in a grouped selector, if need be.

Complex Grouped Selectors Call For Pre-Preprocessors

Grouping can get particularly long and complex with particular forms of selectors, most especially pseudo states such as :hover & :visited. For example, attempting to share a :hover effect between several different classes and states in a grouped selector:

ul li a.social:hover, nav a:hover, h1 a:hover { opacity: 1; }

Not only is this difficult to read, but it's frustrating: there's no way to make a selector that simply says "control the :hover states of all these elements".

If your CSS is getting this wild and thorny, it may be time to consider a CSS pre-processor: a framework tool that allows a series of shortcuts that CSS does not currently support, but which exports generated styles in a way that modern browsers can understand. For example, writing the declaration is a lot easier in SASS:

ul li a.social, nav a, h1 a { /* shared CSS */ 
&:hover { /* shared CSS for a hover state */ } 
}

Further reading: The 30 CSS Selectors you Must Memorize