-
Notifications
You must be signed in to change notification settings - Fork 0
02.Stylesheets
—Rebecca Murphey
- Don't try to prematurely optimise your code; keep it readable and understandable.
- Keep specificity low.
- All code in any code-base should look like a single person typed it, even when many people are contributing to it.
- Strictly enforce the agreed-upon style.
- If in doubt when deciding upon a style use existing, common patterns.
Try and write stylesheets in specificity order. This ensures that you take full advantage of inheritance and CSS’ first C: the cascade.
A well ordered stylesheet will be ordered something like this:
- Reset – ground zero
- Elements – unclassed h1, unclassed ul etc.
- Objects and abstractions — generic, underlying design patterns
- Components – full components constructed from objects and their extensions
- Style trumps – error states etc.
This means that—as you go down the document—each section builds upon and inherits sensibly from the previous one(s). There should be less undoing of styles, less specificity problems and all-round better architected stylesheets.
For further reading I cannot recommend Jonathan Snook’s SMACSS highly enough.
- Never mix spaces and tabs for indentation.
- Choose between soft indents (spaces) or real tabs. Stick to your choice without fail. (Preference: spaces)
- If using spaces, choose the number of characters used per indentation level. (Preference: 4 spaces)
- Include a single space before the opening brace of a ruleset.
- Include a single space after the colon of a declaration.
- Include a space after each comma in comma-separated property or function values.
- Separate each ruleset by a blank line.
Tip: configure your editor to "show invisibles" or to automatically remove end-of-line whitespace.
Tip: use an EditorConfig file (or equivalent) to help maintain the basic whitespace conventions that have been agreed for your code-base.
Use a docBlock-esque commenting style, limited to 80 characters in length:
/**
* This is a docBlock style comment
*
* This is a longer description of the comment, describing the code in more
* detail. We limit these lines to a maximum of 80 characters in length.
*
* We can have markup in the comments, and are encouraged to do so:
*
<div class=foo>
<p>Lorem</p>
</div>
*
* We do not prefix lines of code with an asterisk as to do so would inhibit
* copy and paste.
*/
You should document and comment our code as much as you possibly can, what may seem or feel transparent and self explanatory to you may not be to another dev. Write a chunk of code then write about it.
Only one style should exist across the entire source of your code-base. Always be consistent in your use of whitespace. Use whitespace to improve readability. The chosen code format must ensure that code is: easy to read; easy to clearly comment; minimises the chance of accidentally introducing errors; and results in useful diffs and blames.
- Use hyphen-delimited class names (except for BEM notation)
- Keep declarations on their own line.
- Sort declarations alphabetically. Alphabetising CSS properties increases the odds of larger repeatable patterns being present to aid in GZIP compression.
- Indent rulesets to mirror the DOM.
- Always include the final semicolon in a ruleset.
- Use one discrete selector per line in multi-selector rulesets.
- Include one declaration per line in a declaration block.
- Use one level of indentation for each declaration.
- Use lowercase and shorthand hex values, e.g.,
#aaa
. - Use single or double quotes consistently. Preference is for double quotes, e.g.,
content: ""
. - Quote attribute values in selectors, e.g.,
input[type="checkbox"]
. - Where allowed, avoid specifying units for zero-values, e.g.,
margin: 0
. - Include a semi-colon at the end of the last declaration in a declaration block.
- Place the closing brace of a ruleset in the same column as the first character of the ruleset.
The CSS preprocessor of choice is SASS. Use it wisely.
- Variables: it's been a while since we first asked for variables in CSS. They'll come native some day but meanwhile, we have to rely on CSS preprocessors.
- Nesting: it is the ability to nest rules within each others to create expanded CSS selectors. Can be very interesting to avoid code repetition. Remember the inception rule though.
- Functions: I don't think functions deserve an explanation. Give it parameters, it returns a result you can store in a variable or use as a value.
- Mixins: same as functions except it outputs code instead of returning a result. Very useful to output chuncks of code depending on some parameters (mixin arguments).
- Colour functions: every preprocessor nowadays comes with a bunch of functions to ease colour management (lighten, darken, transparentize, mix, complementary…). Very cool to avoid repeated back-and-forths between the IDE and Photoshop and having 50 shades of grey when you only need one (see what I did there?). Also easier to read than hexadecimal in my opinion.
- File concatenation: we often want to split our large stylesheets into several smaller ones but doing so increases the number of HTTP requests, thus the time the page need to load. Sass makes this possible: multiple files in development environment, one single file compressed in production.
- And it's also very cool for a bunch of other things like responsive web design, modular architecture, calculations, namespaces, and so much more...
- List
@extend
s first, - followed by regular CSS declarations,
- then any
@include
s, - followed by nested selectors
This visually separates the @extend
s and @include
s as well as groups the @include
s for easier reading.
A good rule of thumb is to indent class selectors, and nest bare elements within them.
This is over-doing it:
.header {
.site-nav {
li {
a {}
}
}
}
This is nice and contained:
.header {
}
.site-nav {
>li {
>a {
}
}
}
Variables are one of the many benefits to using a CSS preprocessor. Like other programming languages, take care when naming your variables so they are clear for others or even your future-self.
Describe variables from generic to specific. This is easier on your mind as well as on the code-hinter.
$grey:
$grey-light:
$grey-lighter:
$grey-dark:
$grey-darker:
When building a new component write markup before CSS. This means you can visually see which CSS properties are naturally inherited and thus avoid reapplying redundant styles.
By writing markup first you can focus on data, content and semantics and then apply only the relevant classes and CSS afterwards.
So, instead of building dozens of unique components, try and spot repeated design patterns across them all and abstract them out into reusable classes; build these skeletons as base ‘objects’ and then peg classes onto these to extend their styling for more unique circumstances.
If you have to build a new component split it into structure and skin; build the structure of the component using very generic classes so that we can reuse that construct and then use more specific classes to skin it up and add design treatments.
All components you build should be left totally free of widths; they should always remain fluid and their widths should be governed by a parent/grid system.
Heights should never be be applied to elements. Heights should only be applied to things which had dimensions before they entered the site (i.e. images and sprites). Never ever set heights on p
s, ul
s, div
s, anything. You can often achieve the desired effect with line-height
which is far more flexible.
Grid systems should be thought of as shelves. They contain content but are not content in themselves. You put up your shelves then fill them with your stuff. By setting up our grids separately to our components you can move components around a lot more easily than if they had dimensions applied to them; this makes our front-ends a lot more adaptable and quick to work with.
You should never apply any styles to a grid item, they are for layout purposes only. Apply styling to content inside a grid item. Never, under any circumstances, apply box-model properties to a grid item.
Never use ID selectors in CSS.
They can be used in your markup for JS and fragment identifiers but use only classes for styling.
Classes come with the benefit of being reusable (even if we don’t want to, we can) and they have a nice, low specificity. Specificity is one of the quickest ways to run into difficulties in projects and keeping it low at all times is imperative. An ID is 255 times more specific than a class, so never ever use them in CSS ever.