Skip to content

cpapdotcom/usx-css-sass-style-guide

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 

Repository files navigation

USX CSS / SASS Style Guide

The USX approach to CSS and SASS

Other Style Guides

Table of Contents

  1. Terminology
  2. File Structure
  3. Documentation
  4. Rules
  5. Indentation
  6. Formatting
  7. Nesting
  8. Selectors
  9. Properties
  10. SASS Variables
  11. SASS Components
  12. Reserved Classes

Terminology

  • 1.1 Block: A block is the name given to a selector (or a group of selectors) with an accompanying group of properties.

    .listing {
        font-size: 1.1rem;
        line-height: 1.2;
    }

  • 1.2 Selectors: In a block, selectors are the bits that determine which elements in the DOM tree will be styled by the defined properties. The selectors can match HTML elements, as well as an element's class, ID, or any of its attributes.

    .my-element-class {
        /* ... */
    }
    
    [aria-hidden] {
        /* ... */
    }

  • 1.3 Properties: Finally, properties are what give the selected elements of a block their style. Properties are key-value pairs, and a block can contain one or more property declarations.

    /* some selector */ {
        background: #F1F1F1;
        color: $gray;
    }

⬆ back to top

File Structure

  • 2.1 Use the .scss syntax, never the deprecated .sass syntax.

    Bad

    touch foo.sass

    Good

    touch foo.scss

  • 2.2 All SCSS/CSS should go into the .scss files found within a Modules Resources/assets/sass/* directory. It should never be put into Vue single-file component.

    Why? Even though component SCSS/CSS can be conveniently modularized, and scoped, using Vue single-file components it can be hard to track down within the codebase. It also doesn't get run through the stylelint linting on webpack build or PR Bamboo build. Having it within our SASS files keeps our SCSS centralized and is easier to find and debug.

  • 2.3 Below is a breakdown and description of a Modules Resources/assets/sass/ directory structure:

    • Resources/assets/sass/
      • The primary module import files. These files should contain no actual styling code, just order-specific @imports for building the modules CSS output.
    • Resources/assets/sass/breakpoints
      • This contains general rules for the primary global framework separated by the applications pre-determined breakpoints. This should remain lean. Most styles are broken down into more specific SASS files described below.
    • Resources/assets/sass/components
      • USX Vue Component styles by file. Example: modal.scss contains all the style code for the USX Vue Modal Component.
    • Resources/assets/sass/globals
      • This is the primary directory for global, reusable styles pertaining to specific functionality or types (but not partials or any page specific styles).
    • Resources/assets/sass/modules
    • Resources/assets/sass/pages
      • Specific styles used by a single page represented by a single file. Example: view-order.scss would contain non-reusable styles that pertain solely to the order page.
    • Resources/assets/sass/partials
      • Contains code grouped by global entities or components. Example: sidebar-navigation.scss contains all the style code for the ModuleCow sidebar.
      • The partials directory is also a good place to abstract out reusable code that can be used by multiple pages or the framework in general. Example: Create a reusable .employee-card class (and nested blocks) that may be used on the employee profile page, but also used again within other pages, such as the employee "About Us" admin page. If you ever build a styled class for a page and think it may have benefits as a reusable entity, you should abstract it out into the partials directory.
    • Resources/assets/sass/vendor-extensions
      • This is used to extend, and override, classes and styles that are vendor specific. Meaning that the vendor files themselves are loaded through Yarn and the primary vendor SASS/CSS file resides within the node_modules directory. This directory contains style rules that will extend or override those vendor defaults. The SCSS filename should match the vendor tool name.

⬆ back to top

Documentation

  • 3.1 File Documentation: All new SCSS files should contain a DocBlock style multi-line comment providing a general explanation of the category or grouping the styles in that file represent.

    /**
     * ModuleCow Bulma Extensions and Overrides
     *
     * These are exact class specific overrides to Bulma classes. Use this modular file
     * when overriding or extending a rule or rule set on an already existing Bulma class.
     */
    
    /* initial block */ {
        ...
    }

  • 3.2 Prefer // inline comments to standard single line CSS block comments (SCSS files only).

    /* bad */
    .foo {
        ...
    }
    
    // good
    .foo {
        ...
    }

  • 3.3 Place single line comments on a newline above the subject of the comment. Put an empty line before the comment unless it’s on the first line of a block.

    .foo { // bad
        ...
    }
    
    .foo {
    
        // bad
        .bar {
            ...
        }
    }
    
    // good
    .foo {
        ...
    }
    
    .foo {
        // good
        .bar {
            ...
        }
    }

⬆ back to top

Rules

  • 4.1 Our primary style and structure is dictated by our configured styelint rule set.

    Please see the .stylelintrc file for all enforced CSS/SASS style rules.

    Detailed rule explanations can be found here.

  • 4.2 Use 0 instead of none to specify that a style has no border..

    Bad

    .foo {
        border: none;
    }

    Good

    .foo {
        border: 0;
    }

⬆ back to top

Indentation

  • 5.1 Use soft tabs (space character) set to 4 spaces.

    Bad

    .foo {
    ∙font-size: 1.2rem;
    }
    
    .foo {
    ∙∙font-size: 1.2rem;
    }

    Good

    .foo {
    ∙∙∙∙font-size: 1.2rem;
    }

⬆ back to top

Formatting

  • 6.1 Below are our general formatting guidelines. For a complete overview of enforced CSSS/SCSS formatting see our .stylelintrc configuration file.

    • When using multiple properties in a rule block, give each property its own line.

      /* bad */
      .foo {
          background: $white; color: $black;
      }
      
      /* good */
      .foo {
          background: $white;
          color: $black;
      }
    • Put a space before the opening brace { in rule blocks

      /* bad */
      .foo{
          background: $white;
      }
      
      /* good */
      .foo {
          background: $white;
      }
    • In properties, put a space after, but not before, the : character.

      /* bad */
      .foo {
          background:$white;
      }
      
      /* good */
      .foo {
          background: $white;
      }
    • Put closing braces } of rule blocks on a new line

      /* bad */
      .foo {
          background: $white;}
      
      /* good */
      .foo {
          background: $white;
      }
    • Put blank lines between rule blocks

      /* bad */
      .foo {
          background: $white;
      }
      .bar {
          color: $black;
      }
      
      .foo {
          background: $white;
          .bar {
              color: $black;
          }
      }
      
      /* good */
      .foo {
          background: $white;
      }
      
      .bar {
          color: $black;
      }
      
      .foo {
          background: $white;
      
          .bar {
              color: $black;
          }
      }

⬆ back to top

Nesting

  • 7.1 Nesting blocks is required, even if no properties exist on the selector itself.

    Why? Updating and extending selectors is much easier when the nesting structure is already in place.

    Bad

    .foo {
        font-size: 1.2rem;
    }
    
    .foo .bar .faz {
        color: $grey;
    }

    Good

    .foo {
        font-size: 1.2rem;
    
        .bar {
            .faz {
                color: $grey;
            }
        }
    }

  • 7.2 Attempt to keep primary selector nesting to no more than 4 levels deep, not including pseudo-elements or pseudo-classes. We won't include enforced linting for this rule but it is best practice.

    Why? When selectors become this long, you're likely writing CSS that is:

    • Strongly coupled to the HTML (fragile) —OR—
    • Overly specific (powerful) —OR—
    • Not reusable

    Bad

    .page-container {
        .profile {
            .employee {
                .employee-history {
                    .icon {
                        /* STOP! */
                    }
                }
            }
        }
    }

    Good

    /* create reusable employee card styling */
    .employee-card {
        .history {
            .icon {
                ...
            }
        }
    }

⬆ back to top

Selectors

  • 8.1 Always use slug naming (dashed compounds) for class and ID selector names.

    Bad

    .fooBar {
        ...
    }
    
    .foo_bar {
        ...
    }

    Good

    .foo-bar {
        ...
    }

  • 8.2 Prefer classes over IDs. IDs should rarely be used.

    Why? While it is possible to select elements by ID in CSS, it should generally be considered an anti-pattern. ID selectors introduce an unnecessarily high level of specificity to your rule declarations, and they are not reusable. For more on this subject, read CSS Wizardry's article on dealing with specificity.

    Bad

    #foo {
        ...
    }

    Good

    .foo {
        ...
    }

  • 8.3 JavaScript Hook Classes: Avoid binding to the same class in both your CSS and JavaScript. Due to the fact that we utilize the Vue framework throughout our application, a specific JavaScript hook class should rarely, if ever, be required (currently none exist at the time of this writing).

    However, if it is required that you use JavaScript to "reach" into the DOM to manipulate a specific element you should use a unique, JavaScript specific, class prefixed with .js-.

    Why? Conflating the two often leads to, at a minimum, time wasted during refactoring when a developer must cross-reference each class they are changing, and at its worst, developers being afraid to make changes for fear of breaking functionality.

    Create a JavaScript-specific class to bind to, prefixed with .js-:

    <button class="btn btn-primary js-request-prescription">Request Prescription</button>

⬆ back to top

Properties

  • 9.1 Properties should be ordered alphabetically. We have a Gulp command to implement this automatically. It should be run before submitting a PR request.

    Why? It adds consistency and makes it easier to locate properties within a block.

    Bad

    .foo {
        z-index: $base-z-index + 5;
        font-family: Arial, sans-serif;
        background: $white;
        width: 100vw;
        font-size: 1.1rem;
        display: block;
        font-weight: bold;
    }

    Good

    .foo {
        background: $white;
        display: block;
        font-family: Arial, sans-serif;
        font-size: 1.1rem;
        font-weight: bold;
        width: 100vw;
        z-index: $base-z-index + 5;
    }

⬆ back to top

SASS Variables

  • 10.1 Always use slug naming (dashed compounds) for SASS variables.

    Bad

    $fooBar: #FFF;
    
    $foo_bar: #FFF;

    Good

    $foo-bar: #FFF

  • 10.2 z-index properties should always extend from one of the base z-index SASS variables.

    Bad

    .foo {
        z-index: 999;
    }

    Good

    .foo {
        z-index: $base-z-index + 5;
    }

  • 10.3 SASS colors should always be variables. Most framework colors should already be defined and you should attempt to use the preset colors defined within the SASS variables to keep the UI consistent. If you must utilize a new color that isn't already defined then you should add it to the variables.scss file with a semantic name.

    Why? This allows for consistent, and reusable, color palettes for the UI. It also allows us to change color options site wide with a single variable.

    Bad

    .foo {
        color: #F1F1F1;
        background: #333;
    }

    Good

    .foo {
        color: $off-white;
        background: $gray;
    }

⬆ back to top

SASS Components

  • 11.1 Mixins: Mixins should be used to DRY up your code, add clarity, or abstract complexity--in much the same way as well-named functions.

  • 11.2 Extend Directive: @extend should be avoided because it has unintuitive and potentially dangerous behavior, especially when used with nested selectors. Even extending top-level placeholder selectors can cause problems if the order of selectors ends up changing later (e.g. if they are in other files and the order the files are loaded shifts). Gzipping should handle most of the savings you would have gained by using @extend, and you can DRY up your stylesheets nicely with mixins.

⬆ back to top

Reserved Classes

  • 12.1 The following are reserved classes used by the USX framework, vendor libraries, or components.

    • .dropzone
    • .animated

⬆ back to top

About

US Expeditors CSS and Sass Style Guide

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published