Use stylelint and the P'unk Ave stylelint configuration to lint CSS. There's an Atom plugin available for stylelint. If you don't have stylelint validating with a build tool or test you need to rely on your editor for linting.
Use Harry Robert's ITCSS Architecture to author CSS. ITCSS provides a way to manage common issues that crop up caused by source order, cascade and specificity in large scale projects.
ITCSS organizes CSS into eight "groups" that can even be used to organize your LESS folders if you wish. The main goal is that the compiled CSS file is structured (top to bottom) in order of specificity.
- Settings - Variables
- Tools - Mixins, Functions
- Generic - Ground zero styles (normalize.css, resets)
- Base - Unclassed HTML elements
- Objects - UI Abstractions (object-oriented css)
- Components - One off designed components (footer, header, etc.)
- Utilities - Single purpose (immutable) selectors
It's also a helpful pattern to prefix selectors (i.e. .o-, .c-, .u-
) using these group names so that it's easy to identify the role of a selector in markup.
Use the BEM methodology to name class selectors.
<article class="c-card c-card--theme">
<div class="c-card__body">
<h3 class="c-card__title c-card__title--featured">Vulputate Bibendum</h3>
<p class="c-card__lede">Aenean lacinia bibendum nulla sed consectetur.</p>
<div>
</article>
Only use location dependent styles rarely.
Why? This ensures that selectors can be reused anywhere and are context agnostic.
// Good
.context {
border: 1rem solid #ccc;
}
.aside--context {
padding-bottom: 3rem;
}
// Bad
.context {
border: 1rem solid #ccc;
.aside {
padding-bottom: 3rem;
}
}
Name selectors by role in UI instead of semantically.
Why? This decouples rigid, visual semantics from the UI
// Good
.title-primary {
font-family: 'Helvetica';
font-size: 2rem;
color: black;
}
// Bad
.title-black {
font-family: 'Helvetica';
font-size: 2rem;
color: black;
}
Use abstractions to name variables.
Why? This makes the UI flexible to visual change.
// Good
@border-primary: 1rem solid green;
// Bad
@green-border: 1rem solid green;
- Use
px
for borders - Use unitless line height
- Use
em
for media queries - Use
rem
for everything else (font size, spacing, etc.) %
is also appropriate and can be used for column widths, etc.
Why? A relative, root font size is important so that type scales appropriately if a user has their type size settings adjusted in their browser.
Set a root font-size
of 62.5%
on the html
selector, which is roughly equivalent to 10px
(an authoring convenience, 1.6rem
is equal to 16px
) across browsers.
Use variables or maps to manage z-index values. Variables or keys should be named semantically, such as "z-index-modal". Values should ideally be set 1, 2, 3, 4
etc. and shouldn't be set arbitrarily. Declarations like z-index: 9999;
should never be used and always avoid !important
. Store all variables or maps in a partial or single place.
Using the @extend
directive in Sass is a good tool to keep code DRY, but it can also lead to unintentional exponential bloat. To prevent this, the @extend
directive should only be used with placeholder selectors (e.g., %class-name
).
The short version of the reasoning is that the placeholder can be limited to precisely what should be duplicated. Extending an actual class can unintentionally duplicate any rules where that class is present, even if not desired. More here for the extended reasoning.
For example:
%btn-style {
// CSS declarations
}
.o-button {
@extend %btn-style;
}
.o-tab {
@extend %btn-style;
}
Compiles to:
.o-button,
.o-tab {
// CSS declarations
}
// @NOTE: Placeholder class is not compiled.