Saiku CSS code styleguide.
- Preprocessor
- Best practices
- Colors
- Numbers and units
- Inline assets
- Pseudo elements
- Quotes
- Comments
- Naming conventions
- Namespaces
- Whitespace
- Code linting
- Resources
-
1.2 Limit the use of its features to only variables and mixins.
Getting too crazy with Stylus can lead to both terrible code maintenance and output.
- 1.3
@extend
is allowed only when used with placeholders.
@extend
ing classes can lead to terrible code output.
-
2.1 Avoid the use of
!important
at all costs. Exceptions to the rule:- It's being used within a helper class;
- You can explain its use.
-
2.2 Do not use ids.
They kill modularity and are not necessary for styling.
- 2.3 Do not manually add vendor prefixes.
Our tooling should be able to handle this.
- 2.4 Do not use vendor-specific font rendering techniques.
They are not consistent, break constrast and typography rules.
- 2.5 Prefer
background
overbackground-color
when possible.
Simply because it's a shorthand.
- 2.6 Do not use
pointer-events
.
It's not reliable and it's not CSS's role.
- 2.7 Avoid hard-coded magic numbers.
These are definitelly a code smell and make super hard to maintain.
// Bad
.selector {
width: 73px; // WTF is 73px? Why?
z-index: 99999; // Brute force here, not good at all
margin-top: 128px; // Again, what the heck is this?
}
// Good (values actually make sense)
.selector {
width: grid-columns(2);
z-index: $depth-screen-foreground;
margin-top: $selector-inner-padding;
}
- 2.8 Avoid undoing styles.
These are code smells and almost always have room for improvement.
// Bad
h2 {
font-size: 2em;
margin-bottom: 0.5em;
padding-bottom: 0.5em;
border-bottom: 1px solid #ccc;
}
.no-border {
// Brute force resets down here
padding-bottom: 0;
border-bottom: none;
}
// Good
h2 {
font-size: 2em;
margin-bottom: 0.5em;
}
.headline {
padding-bottom: 0.5em;
border-bottom: 1px solid #ccc;
}
- 2.9 Prefer
em
overpx
.
This allows for a more flexible element sizing.
- 3.1 Hexadecimal values should always be in lower case.
This approach improves code readability.
// Bad
.link {
color: #EAEAE2;
}
// Good
.link {
color: #eaeae2;
}
- 3.2 Prefer shorthand notation.
// Bad
$color: #cccccc;
// Good
$color: #ccc;
// Bad
$color: #ff6600;
// Good
$color: #f60;
- 3.3 Do not use CSS color names.
They're not consistently implemented on browsers.
// Bad
.error {
background: red;
}
// Good
.error {
background: #ff0066;
}
- 4.1 Avoid specifying units for zero values.
// Bad
.square {
border: 0px;
}
// Good
.square {
border: 0;
}
- 4.2 Do not use floating decimals.
They do make code harder to read.
// Bad
.heading {
margin-left: -.75px;
padding: .25px;
border: 2.px;
}
// Good
.heading {
margin-left: -0.75px;
padding: 0.25px;
border: 2.0px;
}
- 4.3 Use
pt
units to declareletter-spacing
values.
We found it easier to match Photoshop visual specifications.
// Bad
.text {
letter-spacing: -0.75px;
}
// Good
.text {
letter-spacing: -0.75pt;
}
- 4.4 Do not add units for
line-height
values.
Not doing so will break vertical rhythm.
// Bad
p {
line-height: 1.5px;
}
// Good
p {
// Equivalent to 150% of the font size
line-height: 1.5;
}
- 5.1 Inline assets are only allowed if they weight less than or equal to
1KB
and are presented only once in the code.
- 6.1 Use double collons
::
to access pseudo elements.
// Bad
.button:after {
background: #f60;
}
// Good
.button::before {
outline: 1px solid;
}
Even though some are not mandatory, it will enforce consistency.
// Bad
@import helpers/clearfix;
input[type=radio] {
opacity: 0.35;
}
.selector {
background: url(path/to/image.png) no-repeat;
}
// Good
@import 'helpers/clearfix';
input[type='radio'] {
opacity: 0.35;
}
.selector {
background: url('path/to/image.png') no-repeat;
}
- 8.1 Following is an example of a well documented component following our standards.
/* ==========================================================================
Component name
========================================================================== */
// Component theming properties
$component-background-color: #f06;
$component-color: #fff;
// Set component's layout direction, which changes the way arrows are drawn
$component-direction: 'down';
/**
* Some description about my component.
* Always try to be very concise and straightforward.
*
* TODO: Split this component in two other components.
*/
.component {
// ...
}
/* Sub component name
========================================================================== */
/**
* Some description about my sub component.
*
* FIXME: Rendenring issue on IE8.
*/
.component__sub-component {
}
/**
* Modifier: Description of component modifier.
*/
.component--modifier {
// ...
}
/**
* Function: Description of component function.
*/
component-function() {
// ...
}
/**
* Mixin: Description of component mixin.
*/
component-mixin() {
// ...
}
- 9.1 Use
hyphen-case
to name classes, variables, functions, mixins and placeholders.
// Bad
.fooBar {
border: none;
}
LoremIpsumDolor {
text-align: center;
}
// Good
.foo-bar {
outline: 1px solid red;
}
// Good
.lorem-ipsum-dolor {
vertical-align: middle;
}
- 9.2 Elements should have the base module name as a prefix and the name of the element, separated by double underscores
__
.
The advantage of elements is to not rely on the markup to apply a certain style.
.menu-item {
// ...
}
// Bad
.menu-item.icon {
// ...
}
// Good
.menu-item__icon {
// ...
}
// Bad
.menu-item-list {
// ...
}
// Good
.menu-item__list {
// ...
}
- 9.3 Modifiers should have the base module name as a prefix and the name of the modifier, separated by double hyphens
--
.
Modifiers are also complementary, therefore a master/base class should exist to provide the visual foundation.
.logo {
background: url('./logo.png') no-repeat;
}
// Bad
.logoBig {
transform: scale(1.5);
}
// Good
.logo--big {
transform: scale(1.25);
}
// Bad
.logo-with-small-size {
transform: scale(0.25);
}
// Good
.logo--small {
transform: scale(0.5);
}
- 9.4 States can be prefixed with
is
,has
orshould
.
// Bad
.logo.logoHidden {
opacity: 0;
}
// Good
.logo.is-hidden {
opacity: 0;
}
// Bad
.logo.logo-disabled {
border: 1px solid;
}
// Good
.logo.is-disabled {
border: 1px solid fuchsia;
}
// Bad
.button-with-icon {
// ...
}
// Good
.button.has-icon {
// ...
}
Namespaces help us understand what role classes play.
Prefix | Description | Example |
---|---|---|
c |
For user interface components | c-dropdown |
ab |
For A/B testing stuff (usually removed and re-implemented once the test is done) | ab-jira-ticket-42 |
u |
For utils | u-clearfix |
t |
For custom themes | t-black-friday |
_ |
For hacks (that should be removed as soon as possible) | _fix-dropdown-ie8 |
is , has , should |
For component states | is-disabled |
v |
For vendor service hooks (such as Optimizely, Crazy Egg, etc) | v-optimizely |
- 11.1 Add a space after selector definition.
// Bad
.selector{content: 'foo';}
// Good
.selector { content: 'foo'; }
- 11.2 Add a space between a rule and its value.
// Bad
.button {
color:#fff;
background:#f06;
}
// Good
.button {
color: #fff;
background: #f06;
}
- 11.3 Add inner spaces to inline selectors.
// Bad
.selector {content: 'foo';}
// Good
.selector { content: 'foo'; }
- 11.4 If a selector has more than a single rule, break all the rules into new lines.
This will improve code readability.
// Bad
.section { cursor: pointer; text-align: center; }
// Good
.section { cursor: default; }
// Good
.section {
text-align: left;
vertical-align: middle;
}
- 11.5 When targeting multiple selectors break each one in a new line.
// Bad
.footer, .header, .main {
display: block;
}
// Good
.footer,
.header,
.main {
margin: 0 auto;
}
- 11.6 Keep multiple rules in more than one line for better readability.
// Bad
.box {
box-shadow: 0 1px 1px #eee,
inset 0 1px 0 #f00;
}
// Good
.box {
box-shadow: 0 1px 1px #eee,
0 1px 0 #f00 inset;
background: linear-gradient(
#1e5799 0%,
#2989d8 50%,
#207cca 51%,
#7db9e8 100%);
}
- 11.7 Add a white space after each comma on multiple values.
// Bad
.selector {
background: rgba(0,0,0,0.5);
}
// Good
.selector {
background: rgba(255, 255, 255, 0.75);
}
- 12.1 We use stylelint to lint our CSS code. All the rules can be found on the
stylelint-config.js
file.