This is a temporary document for Sprint.ly CSS standards which will hopefully be replaced soon by a living styleguide.
We use the following for Sprintly CSS development:
- SASS (CSS precompiler)
- Compass (CSS helpers)
- Susy (Grid framework)
- Breakpoint (Simple media queries)
Selectors should abide by The Inception Rule and should try not to go more than 4 levels deep in order to promote modularity, simplicity, and performance. Simple class names are encouraged, and nesting should only be done if absolutely necessary to avoid being unnecessarily specific. For the same reason, we should generally avoid binding classes to specific elements. For example, .my-module-title
is preferred over h3.my-module-title
). Care should be taken to avoid over-classing (classitis) our application as well.
Selector structure should be relatively independent of of the actual HTML markup.
When writing CSS, we generally try to follow the guidelines of SMACSS (the whole book is available online). Your definitions should generally fall in to one of the following categories:
-
Base
Styling of specific HTML tags, e.g.
body
, which should be used very sparingly.For Sprintly, this styling lives under
html/static/scss/base/_html.scss
, and any styling or configuration that is globally (or almost globally) used should go under thebase/
directory. -
Layout
Tools for page layout, like grid systems, columns, etc., as well as page types (e.g. "logged out" vs. "logged in" pages) or even specific pages. This is usually styling that modules (see below) will fall into to determine how they are positioned/flowing on a page. Class names in this category must be prefixed with
.layout-*
.For Sprintly, all layout styles should go under
html/static/scss/layouts/
. -
Module
This is where most of the meat is. Module styles should represent styling for a block of content and should be relatively self-contained and avoid too much dependency on other CSS.
id
selectors should almost always be avoided here asid
s are meant to represent a single element on a page, which is at odds with the concept of modularity.For example, in cases where we might have a lot of similar property definitions, it might be tempting to combine selectors like so:
.my-module, .some-unrelated-module { border: 1px solid #333; color: #ccc; font-family: Helvetica; padding: 5px; }
But we want to avoid this kind of interdependency in our CSS, so an additional class should be used for cases like this:
.pretty-box { border: 1px solid #333; color: #ccc; font-family: Helvetica; padding: 5px; } .my-module { ... } .some-unrelated-module { ... }
<div class="pretty-box my-module">...</div> <div class="pretty-box some-unrelated-module">...</div>
For Sprintly, module styles should be contained into their own file under
html/static/scss/modules/
. -
State
Styling for transient element states (usually modules or parts of a module) that can be applied or removed falls here. Class names in this category must be prefixed with
.is-
or.has-
(or similar), e.g..is-active
,.is-animating
, etc.For Sprintly, all element states should live right inline with their modules, e.g.:
.login-modal { background-color: #fff; border: 1px solid #ccc; &.is-active { border-color: #f60; } }
Selector names must be lower case and hyphenated, like so:
.layout-signup-page .registration-form { ... }
ids
should generally be avoided for the reasons mentioned above in the Module category, but are acceptable for Layout styling, as well as for use by Javascript if necessary.
All new pages should be built with a "responsive first" approach. This means that all default styles should display nicely on a mobile device, and media queries should be used to modify
styles for larger screens/window sizes. Mobile and desktop are the priority, with tablet variations being strongly encouraged. There are only 2 breakpoints, which you can find under html/static/scss/base/_base.scss
,
and they are: $small-breakpoint
and $medium-breakpoint
. Screen sizes lower than $small-breakpoint
are considered "mobile", between $small-breakpoint
and $medium-breakpoint
are "tablet",
and anything larger is "desktop".
When styling for responsive, you should keep your screen size variations distinct, but grouped closely so they are easy to find and maintain. Example:
.layout-article {
.content-column {
@include span(12);
}
.sidebar-column {
@include span(12);
}
// Tablet styles
@include breakpoint($small-breakpoint) {
.content-column {
@include span(6);
}
.sidebar-column {
@include span(6);
}
}
// Desktop styles
@include breakpoint($small-breakpoint) {
.content-column {
@include span(8);
}
.sidebar-column {
@include span(4);
}
}
}
Similar to selectors, all SASS variables must be lower case and hyphenated like so:
$dark-grey: #222;
Sprintly has a SASS file completely dedicated to all the colors in use on the site: html/static/scss/base/_colors.scss
. It consists, first, of a set of color names (e.g. $darker-lime
) followed by
a small set of contextual assignments (e.g. $story-highlight-color: $lime
). You should use these color variables rather than hex values unless you're using a one-off color, and you should create a
contextual assignment in this file if it's for something that has relatively widespread use on the site.
Modules with at least a moderate level of complexity should include markup examples in the comments.
Eventually, we would like to use KSS to maintain a living styleguide, so referencing it for your commenting/documentation formatting is encouraged.
When using class names in Javascript, a js-
prefix must be used. Class names with a js-
prefix must never be present in a CSS document and if the element in question must be styled, it must
have an additional, non-js-prefixed CSS class applied to it. The purpose of this is to keep our Javascript code as decoupled from our CSS as we can so that, for example, if you wanted to
add/remove/modify class names, it doesn't break any Javascript functionality.
Example:
<p>Click <a href="#" class="open-info-link js-open-info">this thing</a> to get more info.</p>
.open-info-link {
color: red;
}
$('a.js-open-info').click(function(e) {
var view = new InfoView();
view.render();
});
As our application exists now, a clearfix
class exists and is being using in countless HTML templates. Eventually these should not exist, as it's unnecessary clutter in the markup. Instead, the .clearfix()
LESS mixin should be used, which should be applied to an element containing floated elements that need to be cleared.
If you're using !important
, you are very likely doing something bad. This usually implies that you are trying to override an overly-specific selector (see The Inception Rule) and something should probably be refactored.