Rock CSS Guide
When starting out in a new codebase, or writing a new section of CSS, there can be a lot of hesitation and uncertainty — "Is this the best way to do this?" "Am I doing this right?"
Our goals in writing this guide are:
At a high-level, your goals in writing CSS for Rock should be:
Note: at time of writing, our current codebase does not always follow these guidelines. We're aware of this and are making plans to refactor it.
A mix of BEM (a naming convention meaning block, element, modifier) and Bootstrap's conventions. More on this in section 5.
.blockname-elementname-modifiername
// Example
.footernav
.footernav-col
.footernav-col-big
We seperate our javascript hooks from styling hooks to prevent accidental breakages, and allow more confidence in style refactoring.
.js-hookname
// Example
.js-loginbtn
Never style a .js- class — and don't use style classes for selectors in Javascript, either.
//
// Heading 1 (2 blank lines above, 2 below)
// --------------------------------------------------
// Heading 2 (2 above, 1 below)
// -------------------------
// Heading 3 (2 above, 1 below)
.person
.person-head
.person-head-eye
.person-eye
.person-tall
.person-eye-blue
Don't modify the properties of a class based on it's location. Instead, add an optional class that adds the desired changes.
.footer .menu { color: white }
.menu-light { color: white }
In this example, .menu has a different color simply becuase it is located in a different position within the HTML markup. Essentially, the styles for this specific module now live in two different areas — creating potential headaches later on. A more future oriented solution is to add another class to the HTML to achieve the same effect.
There are many reason why it's a bad idea — mainly, it's practically impossible to override without using !important
. The benefits just don't outweigh the disadvantages.
If you have to style third party code that does use ID tags, try using an attribute selector instead [id=“vendor-thing”] { … }
Use the least amount of specificity necessary. The more specific your styles are, the increasingly harder it will become to extend and modify them later.
Dont use ul.footernav
if you can use .footernav
instead.
LESS (and other preprocessors) make it easy nest your styles. It can be very convenient, but it's overuse can lead to styles that are more specific than necessary. It's easy to lose track of how long (and specific) a selector has become when you're 5 levels deep.
// No
.footernav {
[...]
.footernav-col {
[...]
.footernav-header { [...] }
}
}
// Yes
.footernav {
[...]
}
.footernav-col {
[...]
}
.footernav-header { [...] }
@xs = (min-width: @screen-xs-min) = 480px
@sm = (min-width: @screen-sm-min) = 768px
@md = (min-width: @screen-md-min) = 992px
@lg = (min-width: @screen-lg-min) = 1200px
// Example
@media @xs {
.footernav {
padding: 2em;
}
}
Aim to build your styles and their respective media queries mobile first: styles for mobile are the base styles, and media queries are used to provide styles for the larger screen sizes. This isn't always feasible, but it will help you and other developers in the future.
// Yes
.block { padding: 1em; }
@media @sm {
.block { padding: 2em; }
}
@media @lg {
.block { padding: 4em; }
}
// No
.block { padding: 4em; }
@media (max-width: 1199px) {
.block { padding: 2em; }
}
@media (max-width: 992px) {
.block { padding: 1em; }
}
Helper classes are single responsibility classes or variables that can be combined with reusable modules, or added into a glue layer, to acheive the styles you're looking for.
See #6
Our margin and padding helpers follow a basic pattern:
[margin/padding]-[side: t,b,r,l,v,h,all]-[size: sm,md,lg,xl]
Side values
// Examples of actual classes
.padding-b-md
.margin-l-xl
<!-- Usage Example -->
<div class="margin-v-lg">[...]</div>
We use some spacing variables that are based of off bootstraps own variable: @grid-gutter-width
. We multiply or divide this variable to create complementary pixel values.
// Our Helpers
@spacing-sm-px // Default: 7.5px
@spacing-md-px // Default: 15px
@spacing-lg-px // Default: 30px
@spacing-xl-px // Default: 60px
Using spacing variables can help you create designs that have consistent spacing and vertical rhythm.
One of the goals when writing CSS for Rock is to create reusable modules. If you can control the markup of the HTML, this is easy to implement. If you have to use markup that is already set, and possibly unchangeable, it becomes more of a problem.
There are two ways to work around this:
With a glue layer, you add mixins (can be regular CSS classes), to specific class. When compiled by LESS, all of the styles from these classes will be added, or mixed-in.
// Example
.some-rock-block-header {
.footernav-heading;
}
.some-rock-block-wrapper {
.container;
}
.some-rock-block-button {
.btn;
.btn-default;
.pull-right;
}
Note: this method creates a bit of duplication in your stylesheets. This is something we would normally avoid, but there are not too many alternatives here.
Most of the work is inspired, similar, or copy and pasted directly from articles by really talented individuals.