Skip to content

Instantly share code, notes, and snippets.

@gjrevans
Last active November 21, 2017 19:44
Show Gist options
  • Save gjrevans/ab6a8e340bee062d5fc9b0588b53db85 to your computer and use it in GitHub Desktop.
Save gjrevans/ab6a8e340bee062d5fc9b0588b53db85 to your computer and use it in GitHub Desktop.
An overview of the CSS rules that I push for in my development practices

CSS RULES FOR GOOD DEVELOPERS

Writing consistent and readable CSS that will scale well is a challenging process. Especially when the style sheets are getting larger, more complex, and harder to maintain. I have created this set of rules to simplify decision making and maintainability when developing new projects. The following rules assume we are using CSS preprocesser like SASS (.scss) to simplify our lives.

GENERAL RULES

As a general rule of thumb, code should be as modular as possible. Don't be afraid to break CSS into seperate files where it makes sense. The following rules are here to help not hinder. Great teams are built on colaboration and progress. That to say, we're always open to rule modification where it makes sense.

  1. For indentation, use spaces instead of tabs. For our projects, we will use 2 spaces.

  2. Include an empty line between each statement.

  3. Use one selector per line:

.selector-1,
.selector-2 {
  font-size: 1rem;
}
  1. Do not include a space between parentheses. Use of parentheses should look like so:
.selector {
  @include mixin1($size: 4, $color: red);
}
  1. Use single quotes to enclose strings and URLs:
.selector { 
  font-family: 'Roboto', serif;
}
  1. End all rules with a semicolon without spaces before:
.selector {
  margin: 1rem;
}
  1. Use CAPITAL leters when defining colors:
.selector {
  color: #FF0000;
}
  1. Never write vendor prefixes. Use autoprefixer instead .

  2. Use maximum three levels of deep in nested rules.

.selector-1 {
.selector-2 {
  .selector-3 {
  // STOP. RIGHT. MEOW!
  }  
}
}

FILE & IMPORT RULES

  1. Use a the main.scss file to import all blocks, partials, and configs.

  2. Import vendor and global dependencies first, then authored dependencies, then layouts, patterns, and finally the parts and blocks. This is important to avoid mixed imports and overwrite of rules, because the vendor and global rules can’t be managed by us.

SELECTOR RULES:

  1. Avoid the use of ID selectors. IDs are too specific and used mostly for JavaScript actions. If you are going to use ID's include them at the top of your css file.

  2. Avoid !important. If you need to use this rule, it means that something is wrong with your CSS rules in general, and that your CSS is not structured well. CSS with many !important rules can be easily abused and ends up with messy and hard to maintain CSS code.

  3. Do not use child selector i.e. selector > child. This rule shares the same reasoning as the ID one. Child selectors are too specific and are tightly coupled with your HTML structure.

  4. Put class names at the lowest possible level.

<main class='mainly'>
  <p>Lorem ipsum</p> <!-- I'd like to style this paragraph-->
</main>
main.mainly p { 
  // DON'T DO THIS..
}
.paragraph-style {
  // INSTEAD, DO THIS...
}
  1. Don’t use camelCase, instead use snake-case; its easier to read.
.myCoolSelector {}
.my-cool-selector {}
  1. Use a js- prefix if your selector is only used by JavaScript: <button class="js-open-window">Open Window</button>

ORDER RULES

It is important to keep consistency in the code. In additon to layout and structure, it is important to also keep the order of rules. In this way other developers can read the code with much more understanding, and will spend less time finding their way around.

  1. Use @extend first. This let you know at first that this class inherits rules from elsewhere.

  2. Use @include next. Having your mixins and functions included at top is nice to have, and also allows you to know what you will be overwriting (if needed).

  3. Next include your regular CSS class or element rules.

  4. Place nested pseudo classes and pseudo elements before any other element.

  5. Finally, write other nested selectors like in the following example.

.homepage {
  @extend page;
  @include border-radius(5px);
  margin-left: 5px;
  &:after {
    content: ‘’;
  }
  a {
  }
  ul {
  }
}

NAMING RULES

We will use a modified version of the BEM naming convention. BEM stands for Block, Element, Modifier. It was developed by the YANDEX team, and the idea behind BEM was to help developers understand the relationship between HTML and CSS in the project.

Inspired by the BEM convention, our naming conventions rules are as follows:

  1. Use prefix for each type of element. Prefix your blocks, like so:
.l-content {
  // layouts (l-)
}
.m-tab {
  // modules (m-)
}
.is-selected {
  // states (is-)
}
  1. Use two underscores for child elements for every block, like so:
.m-tab__icon {
  // This is a module with a child element style
}
  1. Use two dashes for modifiers for every block, like so:
.m-tab--bordered {
  // This is a modile with a modified style
}

VARIABLE RULES

Use variables. Start with the more general and global variables like colors, and create a separate file for them _config.scss.

  1. If you notice you are repeating some value over the style sheet multiple times, go and create a new variable for that value.

  2. Please DRY. You will be grateful when you want to change that value, and when you will need to change it in only one place.

  3. Use a hyphen to name your variables, like so:

$red: #FF0000;
$red-highlight: darken($red, 5%);

MEDIA QUERY RULES

With Sass you can write your media queries as element queries. Most of the developers write media queries in a separate file or at the bottom of our rules, but that is not recommended.

  1. Nest media queries inside your given selectors for more efficient future maintenance. These nested media queries rules allow you to know very clearly what rules are you overwriting, as you can see in the Sass snippet where named media queries are used.
.m-block {
  &:after {
    @include breakpoint(tablet){
      content: '';
      width: 100%;
    }
  }
}
  1. To create named media queries, create your mixins like so:
@mixin breakpoint($point) {
  @if $point == tablet {
    @media (min-width: 768px) and (max-width: 1024px) {
      @content;
    }
  } @else if $point == phone {
    @media (max-width: 767px) {
      @content;
    }
  } @else if $point == desktop {
    @media (min-width: 1025px) {
      @content;
    }
  }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment