Dropbox’s (S)CSS authoring style guide

Related tags

CSS css-style-guide
Overview

Dropbox (S)CSS Style Guide

“Every line of code should appear to be written by a single person, no matter the number of contributors.” —@mdo

General

Don’ts

  • Avoid using HTML tags in CSS selectors
    • E.g. Prefer .o-modal {} over div.o-modal {}
    • Always prefer using a class over HTML tags (with some exceptions like CSS resets)
  • Don't use ids in selectors
    • #header is overly specific compared to, for example .header and is much harder to override
    • Read more about the headaches associated with IDs in CSS here.
  • Don’t nest more than 3 levels deep
    • Nesting selectors increases specificity, meaning that overriding any CSS set therein needs to be targeted with an even more specific selector. This quickly becomes a significant maintenance issue.
  • Avoid using nesting for anything other than pseudo selectors and state selectors.
    • E.g. nesting :hover, :focus, ::before, etc. is OK, but nesting selectors inside selectors should be avoided.
  • Don't !important
    • Ever.
    • If you must, leave a comment, and prioritise resolving specificity issues before resorting to !important.
    • !important greatly increases the power of a CSS declaration, making it extremely tough to override in the future. It’s only possible to override with another !important declaration later in the cascade.
  • Don’t use margin-top.
    • Vertical margins collapse. Always prefer padding-top ormargin-bottom on preceding elements
  • Avoid shorthand properties (unless you really need them)
    • It can be tempting to use, for instance, background: #fff instead of background-color: #fff, but doing so overrides other values encapsulated by the shorthand property. (In this case, background-image and its associative properties are set to “none.”
    • This applies to all properties with a shorthand: border, margin, padding, font, etc.

Spacing

  • Four spaces for indenting code
  • Put spaces after : in property declarations
    • E.g. color: red; instead of color:red;
  • Put spaces before { in rule declarations
    • E.g. .o-modal { instead of .o-modal{
  • Write your CSS one line per property
  • Add a line break after } closing rule declarations
  • When grouping selectors, keep individual selectors on a single line
  • Place closing braces } on a new line
  • Add a new line at the end of .scss files
  • Trim excess whitespace

Formatting

  • All selectors are lower case, hyphen separated aka “spinal case” eg. .my-class-name
  • Always prefer Sass’s double-slash // commenting, even for block comments
  • Avoid specifying units for zero values, e.g. margin: 0; instead of margin: 0px;
  • Always add a semicolon to the end of a property/value declaration
  • Use leading zeros for decimal values opacity: 0.4; instead of opacity: .4;
  • Put spaces before and after child selector div > span instead of div>span

Sass Specifics

Internal order of a .scss file

  1. Imports
  2. Variables
  3. Base Styles
  4. Experiment Styles

Example:

//------------------------------
// Modal
//------------------------------

@import "../constants";
@import "../helpers";

$DBmodal-namespace: "c-modal" !default;
$DBmodal-padding: 32px;

$DBmodal-background: #fff !default;
$DBmodal-background-alt: color(gray, x-light) !default;

.o-modal { ... }

// Many lines later...

// EXPERIMENT: experiment-rule-name
.o-modal--experiment { ... }
// END EXPERIMENT: experiment-rule-name

Variables

  • Define all variables at the top of the file after the imports
  • Namespace local variables with the filename (SASS has no doc level scope)
    • eg business_contact.scss$business_contact_font_size: 14px;
  • Local variables should be $snake_lowercase
  • Global constants should be $SNAKE_ALL_CAPS

Color

  • Use the defined color constants via the color function
  • Lowercase all hex values #fffff
  • Limit alpha values to a maximum of two decimal places. Always use a leading zero.

Example:

// Bad
.c-link {
  color: #007ee5;
  border-color: #FFF;
  background-color: rgba(#FFF, .0625);
}

// Good
.c-link {
  color: color(blue);
  border-color: #ffffff;
  background-color: rgba(#ffffff, 0.1);
}

Experiments

Wrap experiment styles with comments:

// EXPERIMENT: experiment-rule-name
.stuff { ... }
// END EXPERIMENT: experiment-rule-name

Rule Ordering

Properties and nested declarations should appear in the following order, with line breaks between groups:

  1. Any @ rules
  2. Layout and box-model properties
  • margin, padding, box-sizing, overflow, position, display, width/height, etc.
  1. Typographic properties
  • E.g. font-, line-height, letter-spacing, text-, etc.
  1. Stylistic properties
  • color, background-*, animation, border, etc.
  1. UI properties
  • appearance, cursor, user-select, pointer-events, etc.
  1. Pseudo-elements
  • ::after, ::before, ::selection, etc.
  1. Pseudo-selectors
  • :hover, :focus, :active, etc.
  1. Modifier classes
  2. Nested elements

Here’s a comprehensive example:

.c-btn {
    @extend %link--plain;

    display: inline-block;
    padding: 6px 12px;

    text-align: center;
    font-weight: 600;

    background-color: color(blue);
    border-radius: 3px;
    color: white;

    &::before {
        content: '';
    }

    &:focus, &:hover {
        box-shadow: 0 0 0 1px color(blue, .3);
    }

    &--big {
        padding: 12px 24px;
    }

    > .c-icon {
        margin-right: 6px;
    }
}

Nesting

  • As a general rule of thumb, avoid nesting selectors more than 3 levels deep
  • Prefer using nesting as a convenience to extend the parent selector over targeting nested elements. For example:
    .block {
        padding: 24px;
    
        &--mini {
            padding: 12px;
        }
    }

Nesting can be really easily avoided by smart class naming (with the help of BEM) and avoiding bare tag selectors.


BEM

Block: Unique, meaningful names for a logical unit of style. Avoid excessive shorthand.

  • Good: .alert-box or .recents-intro or .button
  • Bad: .feature or .content or .btn

Element: styles that only apply to children of a block. Elements can also be blocks themselves. Class name is a concatenation of the block name, two underscores and the element name. Examples:

  • .alert-box__close
  • .expanding-section__section

Modifier: override or extend the base styles of a block or element with modifier styles. Class name is a concatenation of the block (or element) name, two hyphens and the modifier name. Examples:

  • .alert-box--success
  • .expanding-section--expanded

BEM Best practices

Don't @extend block modifiers with the block base.

  • Good: <div class="my-block my-block--modifier">
  • Bad: <div class="my-block--modifier">

Don't create elements inside elements. If you find yourself needing this, consider converting your element into a block.

  • Bad: .alert-box__close__button

Choose your modifiers wisely. These two rules have very different meaning:

.block--modifier .block__element { color: red; }
.block__element--modifier { color: red; }

Selector Naming

  • Try to use BEM-based naming for your class selectors
    • When using modifier classes, always require the base/unmodified class is present
  • Use Sass’s nesting to manage BEM selectors like so:
    .block {
        &--modifier { // compiles to .block--modifier
            text-align: center;
        }
    
        &__element { // compiles to .block__element
            color: red;
    
            &--modifier { // compiles to .block__element--modifier
                color: blue;
            }
        }
    }

Namespaced Classes

There are a few reserved namespaces for classes to provide common and globally-available abstractions.

  • .o- for CSS objects. Objects are usually common design patterns (like the Flag object). Modifying these classes could have severe knock-on effects.
  • .c- for CSS components. Components are designed pieces of UI—think buttons, inputs, modals, and banners.
  • .u- for helpers and utilities. Utility classes are usually single-purpose and have high priority. Things like floating elements, trimming margins, etc.
  • .is-, .has- for stateful classes, a la SMACSS. Use these classes for temporary, optional, or short-lived states and styles.
  • ._ for hacks. Classes with a hack namespace should be used when you need to force a style with !important or increasing specificity, should be temporary, and should not be bound onto.
  • .t- for theme classes. Pages with unique styles or overrides for any objects or components should make use of theme classes.

Separation of Concerns (One Thing Well™)

You should always try to spot common code—padding, font sizes, layout patterns—and abstract them to reusable, namespaced classes that can be chained to elements and have a single responsibility. Doing so helps prevent overrides and duplicated rules, and encourages a separation of concerns.

// Bad code
// HTML:
// <div class="modal compact">...</div>
.modal {
    padding: 32px;
    background-color: color(gray, x-light);

    &.compact {
        padding: 24px;
    }
}

// Good code
// HTML:
// <div class="c-modal u-l-island">...</div>
// <div class="c-modal u-l-isle">...</div>

// components/_modal.scss
.c-modal {
    background-color: color(gray, x-light);
}

// helpers/_layout.scss
.u-l-island {
    padding: 32px;
}

.u-l-isle {
    padding: 24px;
}

Media Queries

Media queries should be within the CSS selector as per SMACSS

.selector {
      float: left;

      @media only screen and (max-width: 767px) {
        float: none;
      }
}

Create variables for frequently used breakpoints

$SCREEN_SM_MAX: "max-width: 767px";

.selector {
      float: left;

      @media only screen and ($SCREEN_SM_MAX) {
        float: none;
      }
}
You might also like...

Spectre.css - A Lightweight, Responsive and Modern CSS Framework

Spectre.css Spectre.css is a lightweight, responsive and modern CSS framework. Lightweight (~10KB gzipped) starting point for your projects Flexbox-ba

Jan 8, 2023

Low-level CSS Toolkit – the original Functional/Utility/Atomic CSS library

Basscss Low-level CSS toolkit – the original Functional CSS library https://basscss.com Lightning-Fast Modular CSS with No Side Effects Basscss is a l

Dec 31, 2022

Framework-agnostic CSS-in-JS with support for server-side rendering, browser prefixing, and minimum CSS generation

Aphrodite Framework-agnostic CSS-in-JS with support for server-side rendering, browser prefixing, and minimum CSS generation. Support for colocating y

Jan 1, 2023

CSS Boilerplate / Starter Kit: Collection of best-practice CSS selectors

Natural Selection Natural Selection is a CSS framework without any styling at all. It is just a collection of selectors that can be used to define glo

Dec 8, 2022

Source code for Chrome/Edge/Firefox/Opera extension Magic CSS (Live editor for CSS, Less & Sass)

Live editor for CSS, Less & Sass (Magic CSS) Extension Live editor for CSS, Less & Sass (Magic CSS) for Google Chrome, Microsoft Edge, Mozilla Firefox

Dec 13, 2022

Easily create css variables without the need for a css file!

Tailwind CSS Variables This plugin allows you to configure CSS variables in the tailwind.config.js Similar to the tailwindcss configurations you are u

Dec 22, 2022

Cooltipz.css - A highly customisable, minimal, pure CSS tooltip library

Cooltipz.css - A highly customisable, minimal, pure CSS tooltip library

Cooltipz.css - Cool tooltips Cool customisable tooltips made from pure CSS Lightweight • Accessible • Customisable • Simple Cooltipz.css is a pure CSS

Dec 24, 2022

micro-library for CSS Flexbox and CSS Grid

SpeedGrid micro-library for CSS Flexbox and CSS Grid Overview SpeedGrid dynamically generates inline CSS by specifying the class name. Easy maintenanc

Mar 26, 2022

Data-tip.css - Wow, such tooltip, with pure css!

Notice: hint.css has been much better since I complained about it months ago, so try out its new features instead of this one! data-tip.css Wow, such

May 26, 2021
Comments
  • Clarify

    Clarify "rule" vs "property"

    The goal of this change is to clarify the terms "rule" and "property" so that "rule" refers to the selector followed by a declaration block and "property" refers to the properties inside the declaration block as specified in CSS Syntax:

    • CSS 2 §4.1.7 Rule sets, declaration blocks, and selectors: https://www.w3.org/TR/CSS2/syndata.html#rule-sets
    • CSS Syntax Module Level 3 (CR) §2 Description of CSS’s Syntax: https://www.w3.org/TR/css-syntax-3/#syntax-description
    opened by davidl 2
  • Inconsistent example

    Inconsistent example

    In the Internal order of a .scss file code example you declared local variables using the dash-case notation; and below in the text you mention that "Local variables should be $snake_lowercase".

    Is there any rationale for the usage of the dash-case here?

    opened by makabde 0
Owner
Dropbox
Dropbox
Automatically generate a style guide from your stylesheets.

StyleDocco StyleDocco generates documentation and style guide documents from your stylesheets. Stylesheet comments will be parsed through Markdown and

Jacob Rask 1.1k Sep 24, 2022
Easily create and maintain style guides using CSS comments

mdcss lets you easily create and maintain style guides with CSS comments using Markdown. /*--- title: Buttons section: Base CSS --- Button styles c

Jonathan Neal 679 Oct 4, 2022
Visual primitives for the component age. Use the best bits of ES6 and CSS to style your apps without stress 💅

Visual primitives for the component age. Use the best bits of ES6 and CSS to style your apps without stress ?? Looking for v5? The master branch is un

styled-components 38k Dec 31, 2022
NES-style CSS Framework | ファミコン風CSSフレームワーク

日本語 / 简体中文 / Español / Português / Русский / Français NES.css is a NES-style(8bit-like) CSS Framework. Installation Styles NES.css is available via ei

null 19.2k Jan 5, 2023
Reseter.css - A Futuristic CSS Reset / CSS Normalizer

Reseter.css A CSS Reset/Normalizer Reseter.css is an awesome CSS reset for a website. It is a great tool for any web designer. Reseter.css resets all

Krish Dev DB 1.1k Jan 2, 2023
A markdown based documentation system for style guides.

Hologram Hologram is a Ruby gem that parses comments in your CSS and helps you turn them into a beautiful style guide. There are two steps to building

Trulia, LLC. 2.2k Nov 12, 2022
[ON HOLD] Living Style Guides Engine and Maintenance Environment for Front-end Components. Core repository.

[ON HOLD] SourceJS - Living Style Guide Platform The project been stale for a while and currently is in the [ON HOLD] state until we find new maintain

SourceJS 552 Nov 8, 2022
styled component for react & style-loader/usable

react-styled ES7 decorator for dynamic stylesheet usage w/ webpack install $ npm install bloody-react-styled --save-dev require import styled from "bl

Matthias Le Brun 37 Sep 26, 2022
🐒 Normalize browsers' default style

My open source work is supported by the community Special thanks to: Differences from normalize.css Smaller Includes only normalizations for the lates

Sindre Sorhus 4.8k Jan 3, 2023