Rule Formatting

Class and Variable Naming

  1. Create variables when the value is repeated more than once, or the value is likely to be updated more than once.
  2. You can create local variables if necessary to prevent repeatition in code.
  3. Local variables should be placed at the top of the file they are being used in, one per line.
  4. The !global flag should only be used when overriding a global variable from a local scope.
  5. Variables across the whole SCSS codebase should be placed in their own file - this needs team discussion
  6. Set variables for breakpoints or create mixins that you can update easily - team discussion for actual implementation
  7. Avoid using 'lighten' or 'darken' - or any other SCSS color manipulation when creating variables.
  8. Use all lowercase letters when naming a class or variable:
    // Wrong //
    .exampleClass {
        ...
    }
    
    // Wrong //
    .Example-Class {
        ...
    }
    
    // Right //
    .example-class {
        ...
    }
    
    $component-heading-text: #ccc; 
                                    
  9. Defined constants should be underscore-spaced(snakerized) and all-caps'd:
    // Wrong //
    $css-positions: (top, right, bottom, left, center);
    
    // Right //
    $CSS_POSITIONS: (top, right, bottom, left, center);
                                    
  10. Use dashes over camelCasing in class names. Underscores are used as part of the BEM methodology.
    // Wrong // 
    .thisIsBad_dontDoThis-BadStuff { 
        ... 
    }                                
                                    
    // Right // 
    // This is a good -if verbose- example:
    .example-class__heading--postive {
        ...
    } 
                                    
  11. Variable names should not be how something looks, but rather what the something is responsible for:
    // This is ok:
    $color-ocean: #00a3bb;
    
    // This is better:
    $primary-color: #00a3bb;
    
    // This is even BETTER better:
    $component-banner-background: $primary-color;
                                    
  12. Use imported or already existing branding or theme colors as bases for your variables, abstracted out and ensure you add 'default' at the end of any variables you create/use that you might need to easily override in a later partial:
    // Variable from the 'descriptive-colors.scss' theme partial:
    $color-ocean: #3baecc;
    
    // Using the descriptive color in the theme palate:
    $color-text-primary: $color-ocean !default;
    
    // Using the theme palate color in a component variable:
    $component-text-heading: $color-text-primary !default;                                
                                    
  13. Namespace your variables if they are going to be used across the project or in conjunction with another library, so there are no conflicts:
    // Wrong //
    $spacing (...);
    
    // Right //
    $willow-spacing (...);
                                    
  14. Don't name variables based on context:
    // Wrong //
    $background-color: $info-color;
    
    // Right //
    $global-alert-info-background-color: $info-color;
                                    

Spacing

  1. Tabs should equal 4 spaces.
  2. Everything following an opening brace ( { ) should be on a new line.
  3. Use a space between the class name and the opening brace ( { ):
    // Wrong //
    .example-class{
        property: value;
    }
    
    // Right //
    .example-class {
        property: value;
    }
                                    
  4. Vendor prefixes should be right aligned:
    // Wrong //
    .example-class {
        -webkit-border-radius: 3px;
        -moz-border-radius: 3px;
        border-radius: 3px;
    }
    
    // Right //                            
    .example-class {
        -webkit-border-radius: 3px;
            -moz-border-radius: 3px;
                border-radius: 3px;
    }
                                    
  5. Combinators should have a space before and after:
    // Wrong //
    .example-class>.example-class {
        height: calc(50%-1rem);
    }
    
    // Right //
    .example-class > .example-class {
        height: calc(50% - 1rem);
    }
                                    
  6. There should be a space following the colon of the property within a rule:
    //Wrong //                           
    .example-class {
        width:calc(100vw / 2);
    } 
    
    //Right //
    .example-class {
        width: calc(100v2 / 2);
    }
                                    
  7. Ensure all calculations are wrapped in parentheses:
    .example-class {
        width: calc(100vw / 2);
    }
                                    
  8. Closing selector braces ( } ) should be in line with the selector name and on their own line immediately preceeding the last rule (or other in-class content):
    // Wrong //
    .example-class {
        property: value;}
    
    // Right //
    .example-class {
        property: value;
    } // <-- This brace should be in line with the namespace
                                    

SCSS Arguments

  1. Arguments within parenthese can with a space following the comma, except for the last one.
  2. If the number of arguments grows too long, consider stacking them like rulesets in a class:
    // Wrong //
    $case1(
        $big, 
        $little, 
        $front, 
        $back
    );
    
    // Wrong //
    $case2($many, $more, $variables, $so, $many, $that, $this, $should, $begin, $to, $stack);
    
    // Right //
    $case1($big, $little, $front, $back);
    
    // Right //
    $case2(
        $many, 
        $more, 
        $variables, 
        $so, 
        $many, 
        $that, 
        $this, 
        $should, 
        $begin, 
        $to, 
        $stack
    );             
                                    
  3. You can use your discretion as far as putting a comma after the last item in the arguments list.

Measurement Units

  1. Use percentages when layout components stay relational to each other (like a component that always takes up 75% of the screen and a second one that always takes up 25%).
  2. Use pixel(px) units for when measurement should not change based on user-set font size or browser zooming.
  3. Use rem units for font sizes.
  4. Use up to 10 decimal places in em units to ensure accuracy - if you choose to do so, it will eliminate some of the browser-specific calculation fluctuations based on resizing and percent widths etc.
  5. Use units when measuring dimensions (margins, borders, padding etc).

Property Declaration Order

  1. Organize the inside of a selector as follows:
    // 1 - extends
    // 2 - includes
    // 3 - declarations
    // 4 - :pseudo selectors and elements
    // 5 - media queries
    // 6 - nested elements
    // 7 - nested classes
    // 8 - imports of sub-elements
    
    .example-class {
        @extend .other-class; // 1
        @include mixin; // 2
    
        property: value; // 3
        property: value;
        property: value;
    
        // 4
        :hover {
            property: value;
        }
    
        :after {
            property: value;
        }
    
        // 5
        @media screen and (min-width: $medium-breakpoint) {
            property: value;
            property: value;
        }
    
        // 6
        a {
            ... 
        }
    
        // 7
        .nested-class {
            ...
        }
    
        // 8
        @import "child-element-1";
        @import "child-element-2";
    
    }
                                    
    • Note: Nested selectors/elements/classes should be constructed the same way as the example selector.
  2. Property declaration should be alphabetical
    // Wrong //
    .example-class {
        display: block;
        padding: 10px;
        margin: 10px;
        background-color: #fff;
        border-radius: 5px;
    }
    
    // Right //
    .example-class {
        background-color: #fff;
        border-radius: 5px;
        display: block;
        margin: 10px;
        padding: 10px;
    }
                                    
  3. Some property declarations can be written in shorthand, however using shorthand on some CSS properties can get confusing. Avoid shorthand for these properties:
    • background
    • font
    • list-style
    // Wrong //
    .example-class {
        background: #000 url("images/bg.jpg") no-repeat 50% 100px;
        font: italic 12px/1.5 sans-serif;
        list-style: url("images/shape.jpg") outside;
    }
    
    // Right //
    .example-class {
        background-color: #000;
        background-image: url(images/bg.jpg);
        background-position: 50%;
        background-repeat: no-repeat;
        background-size: 100px;
        font-family: sans-serif;
        font-size: 12px;
        font-style: italic;
        line-height: 1.5;
        list-style-image: url("images/shape.jpg");
        list-style-position: outside;
    }   
                                    
  4. Shorthand is okay on the following properties but avoid using 3 values for margin, padding and border-radius
    • margin
    • padding
    • border
    • border-radius
    // Wrong //
    .example-class {
        margin: 1em 1.5em 2em;
    }
    
    // Right //
    .example-class {
        margin: 1em;
        //or
        margin: 1em 1.5em;
        //or
        margin: 1em 1.5em 2em 1.5em;
    }
                                    
  5. Only include properties being used in rule declarations. For example, if there are no styles necessary for "border-top", then do not declare it in the rule.
  6. Remove empty rulesets:
    // Wrong //
    .example-class {
        //I'm empty and should be removed
    }
                                    
  7. Selectors and declarations should be written on separate lines:
    // Wrong //
    .example, .example-class {
        property: value;
    }
    
    // Right //
    .example,
    .example-class {
        property: value;
    }
                                    
  8. Rulesets should have an empty line between them:
    // Wrong //
    .example-class {
        property: value;
    }
    .example-class {
        property: value;
    }
    
    // Right //
    .example-class {
        property: value;
    }
    
    .example-class {
        property: value;
    }
                                    
  9. Use double quotes for values:
    // Wrong //
    .example-class {
        background-image: url('/images/logo.jpg');
    }
    
    // Right //
    .example-class {
        background-image: url("/images/logo.jpg");
        font-family: "Open Sans";
    }
                                    
  10. All property-value pairs should be on separate lines, indented once and have an ending semi-colon:
    // Wrong //
    .example-class {
        property: value; property: value;
    }                            
    
    // Right //
    .example-class {
        property: value;
        property: value;
    }
                                    
  11. Any comma-separated property values should have a space after each comma.
    // Wrong //
    .example-class {
        property: value,value;
    }                            
    
    // Right //
    .example-class {
        property: value, value;
    }
                                    
  12. Do not include spaces after commas for values wrapped in parentheses
    // Wrong //
    .example-class {
        property: value(value-1, value-2);
    }                            
    
    // Right //
    .example-class {
        property: value(value-1,value-2);
    }
                                    

Colors

  1. Hexadecimal codes should be typed in lowercase.
  2. Use shorthand hex notation where available:
    .example-class {
        //regular 6 char hex notation
        color: #ffffff; 
    }
    
    // Right //
    .example-class {
        //shortened 3 char hex notation
        color: #fff; 
    }
                                    
  3. Do not use keyword colors
    // Wrong //
    .example-class {
        color: MistyRose;   
    }
                                    

Comments

  1. Well-commented code is important, take time to properly describe what the code does, limitations, construction etc.
  2. If using SCSS, try to use single line comments ( // ) over block comments ( /* ... */ ).
    • Note: CSS does not permit single line comments.
  3. Put comments on their own line above the class or declaration in question, and avoid end-of-line comments.
  4. Write detailed comments for code that isn't self-documenting:
    • Documenting uses of z-index;
    • Documenting compatibility or browser-specific hacks;
  5. Write comments that are easy for other developers to understand:
    // Wrong //
    // z-index so it is on top
    .example-class {
        z-index: 100;
    }
    
    // Right //
    // z-index required because of bug with IE9 (www.link-to-the-bug-documentation.com)
    .example-class {
        z-index: 100;
    }
                                    
  6. Highlight purpose or context of item being explained in comment:
    // Wrong //
    // Class Name
    .example-class {
        ...
    }
    
    // Right //
    // Wrapping element for .example-class__heading
    .example-class {
        ...
    }
                                    
  7. Length of code or comment lines should be 80 characters or less:
    // Dang this is a really long comment, it really had to detail in depth
    // everything regarding what happened in this particular segment of css,
    // it should be easy to read both vertically and horizontally 
    // without having to scroll in order to read it all
                                    

Fonts

  1. Use number values for font weights, not words.
    // Wrong //
    .example-class {
        font-weight: bold;
    }
    
    // Right //
    .example-class {
        font-weight: 500;
    }
                                    
  2. Use rem units for font sizes with a px fallback.
  3. Set the HTML element font-size to a default size: 62.5%. This will set 1em = 10px which will make mental conversion of em and rem sizes easier. Example: 1.4em = 14px.
    html {
        font-size: 62.5%;
    }
                                    

Media Queries

  1. Styles should be applied mobile first, so media queries will usually apply to larger-than-mobile device sizes.
  2. Specify in the media query what media type it is for (screen, tv, handheld etc) so it will not be applied to all stylesheets:
    .example-class {
        background-color: lighten($primary-component-background, 10%);
    
        @media screen (min-width: 680px) {
            background-color: $primary-component-background;
        } 
    }
                                    
  3. Use variables to set your media queries throughout so they are easy to manage and update:
    // Wrong //
    @media (min-width: 680px) {
        ...
    } 
    
    // Right //
    @media screen (min-width: 680px) {
        ...
    }                               
    
    // SCSS Example - Nested inside class selectors
    // Nest media queries within the selector but after the mobile styling
    // Use variable for screen size value
    
    $medium-breakpoint: 680px;
    
    .example-class {
        property: value;
        property: value;
    
        @media screen (min-width: $medium-breakpoint) {
            property: value;
        } 
    }
                                    

Values

  1. Values less than 1 should have a leading zero.
  2. Utilize variables to create a system of values instead of using arbitrary numbers spread throughout your code:
    // Wrong //
    .a-component {
        margin: 0.37rem;
    }
    
    .b-component {
        margin: 0.35rem;
    }
    
    .c-component {
        margin: 0.2rem;
    }
    
    // Right //
    // These space values are golden-ratio based
    // Systems do not have to be ratio based
    
    $space-xxs: 0.3776rem;
    $space-xs: 0.6110rem;
    $space-s: 0.9888rem;
    $space: 1.6rem;
    $space-l: 2.5888rem;
    $space-xl: 4.1886rem;
    $space-xxl: 6.7772rem;
    
    .a-component {
        padding: $space;
    }
    
    .b-component {
        padding: $space;
    }
    
    .c-component {
        padding: $space-s;
    }
                                    
  3. Line-height value should be unitless:
    .example-class {
        line-height: 1;
    }
                                    
  4. Use a value of "0" instead of "none" to specify an element has no border or padding or margin etc:
    .example-class {
        border: 0;
    }
                                    
  5. Avoid specifying units for zero values:
    // Wrong //
    .example-class {
        border: 0px;
    }
    
    // Right //
    .example-class {
        border: 0;
    }
                                    

Specificity and Selectors

Specificity

It is important to use selectors with low specificity. This allows styles to be easily overridable in the future. It is also important to avoid shared selectors as much as possible to prevent unintended updates in the future.

HTML Selectors

  1. Do not use tag selectors unless necessary:
    // Wrong //
    p.example-class {
        font-weight: 700;
    }
    
    // Right //
    .example-class {
        font-weight: 700;
    }
                                    

Attribute Selectors

  1. Use HTML and attribute selectors only when necessary.
  2. Attribute values in selectors should be surrounded by double quotes:
    // Attribute selector:
    [type="input"] {
        ...
    }
    
    // Element selector
    h1 {
        ...
    }
                                    

Classes

  1. Use only classes and data-attributes to style a component.

IDs

  1. Do not use IDs as selectors.

Nesting

  1. Try to avoid using nested selectors.
    • If you have no choice, apply styles to an element by using nested rulesets no more than three selectors deep.
    • BEM principles will help restrict and enforce this convention for most use cases.

SCSS Mixins

  1. Try to use mixins whenever possible for any groups of properties that are repeated and located together.
  2. Use mixins when things require parameters.
  3. Use mixins to change size.
  4. Try to keep mixins as concise as possible, we do not currently have a line limit in place.
  5. Do not worry about creating/using a vendor prefix mixin unless you do not have access to Autoprefixer or and pre-constructed mixins.
  6. All .SCSS component-named partials should keep the base styles in a base mixin that is contained at the top of the document:
    // This is scss in an individual component root file - for ex. 'banner.scss'
    @mixin base() {
        text-align: center;
    }
        
    .banner {
        @include base;
    }
                                    
  7. If the mixin does not use any variables, you may call it without using parenthesis:
    @mixin base() {
        text-align: center;
    }
        
    .banner {
        @include base;
    }
                                    
  8. When dealing with an unknown number of arguments in a mixin, always use an arglist rather than a list:
    //This enables you to pass any number of arguments to a mixin/function                                 
    @mixin base(bases...) {
        text-align: center;
    }       
                                    

SCSS Maps

  1. Maps should be treated like any other property: value, pair.
  2. The opening brace ( ( ) should be on the same line as the map name.
  3. Each property-value pair should be on its own line.
  4. Each pair should be immediately followed by a comma.
  5. Each property should have a space after each colon.
  6. Use double-quotes if using strings in values.
  7. The closing brace ) ) should be on its own line and in line with the map name.
  8. Do not put an empty line between last value and the closing ( ) ) brace.

SCSS Conditionals

  1. Do not use conditionals unless you have some medium to complex logic in your code.
  2. Use conditionals in accordance with any libraries or frameworks you are including.
  3. You do not need to use parentheses unless necessary:
    //Wrong
    @if ($full-bleed == true) {
        //...    
    }
    
    // Right
    @if $full-bleed {
        //...
    }
                                    
  4. Test falsey conditionals by using 'not':
    //Wrong
    @if base($full-bleed, $item) == null {
        //...    
    }
    
    // Right
    @if not base($full-bleed, item) {
        //...
    }
                                    
  5. Conditional variables should always be on the left side of the statement, for consistency:
    //Wrong
    @if 42 == $base-value {
        //...    
    }
    @else {
        //...
    }
    
    // Right
    @if $base-value == 42 {
        //...
    }
                                    
  6. If you use an if/else combination, the else statement should begin on the same line as the closing brace( } ):
    //Wrong
    @if $full-bleed {
        //...    
    }
    @else {
        //...
    }
    
    // Right
    @if $full-bleed {
        //...
    } @else {
        //...
    }
                                    
  7. If you need to return a different result based on an if/then, make sure the statement has a @return statement outside conditional block:
    //Wrong
    @function base($condition) {
        @if $condition {
            @return true;
        } @else {
            @return false;
        }
    }
    
    // Right
    @function base($condition) {
        @if $condition {
            @return true;
        }
    
        @return false;
    }