Sass Guidelines



These are some general guidelines to writing effective Sass. The same information applies in general to Less, and to some extent CSS, however CSS won’t have the ability to nest selectors like Sass or Less.

Use lowercase letters and hyphens for variables and class names

As developers might become used to the variable format of their preferred language, they might forget that other languages prefer different variable formats. A Javascript developer might decide to use camelCase, a .Net or C# developer might want to use PascalCase, and a ruby developer might want to use snake_case. CSS prefers to use hyphen-case (lisp-case, spinal-case, or kebab-case) for all variables, class names, and element ID selectors.

Do:

.my-class {
    width: $container-width;
}

Don’t:

.my_class {
    width: $container_width;
}

Class and ID selectors don’t need tag names

It’s reasonable to think that you need to include a tag name for a class selector, such as table.responsive-table, but these additional tag name selectors are unnecessary. There should only be one type of element with the class of .responsive-table.

Do:

.responsive-table {
    display: table;
}

Don’t:

table.responsive-table {
    display: table;
}

Increase specificity without using !important

The !important flag can start a CSS war where one developer adds the !important flag to override a previously defined selector and the next developer needs to override that so they add another !important, but sometimes that second !important can’t override the first because the selector isn’t as specific as the previous selector. You then run into not only the !important war, but also the specificity war. Soon they’re laying traps above doorways and behind picture frames and giggling incessantly at eachother.

Spy vs Spy

Assume the following code is previously defined in some file:

.responsive-table {
    display: block;
    thead {
      display: block;
    }
    tr {
      display: block;
    }
    th, td {
      display: inline-block;
    }
    tbody {
      display: block;
      tr {
        border: 1px solid black;
        td {
          border: 1px solid black;
        }
      }
    }
}

Do:

/* The following code is mobile-second design */
@media only screen and (max-width: 760px) {
  // all of this is resetting IE9 back to normal table mode
  .responsive-table {
    display: table;
    thead {
      display: table-header-group;
    }
    tr {
      display: table-row;
    }
    th, td {
      display: table-cell;

    }
    tbody {
      display: table-row-group;
      tr {
        border: none;
        td {
          border: none;
        }
      }
    }
  }
}

Don’t

@media only screen and (max-width: 760px) {
  // all of this is resetting IE9 back to normal table mode
  .responsive-table {
    display: table !important;
    thead {
      display: table-header-group !important;
    }
    tr {
      display: table-row !important;
    }
    th, td {
      display: table-cell !important;
    }
    tbody {
      display: table-row-group !important;
      tr {
        border: none !important;
        td {
          border: none !important;
        }
      }
    }
  }
}

Don’t use ID selectors

ID selectors, besides the !important flag, are one of the most specific selectors you can use. The general rule is to never use ID selectors for CSS. Instead, create a new class for that element and apply styles to the class. Think of IDs as tools to use for selecting elements in Javascript and for analytics, never for CSS.

Assume we have the following HTML:

<header id="site-header" class="site-header">
  <nav>Hello</nav>
</head>

Which selector type will override the site-header width?

Do:

.site-header {
  margin: 0 auto;
  width: 100%;
}

@media only screen and (min-width: 761px) {
    .site-header {
      width: 80%;
    }
}

Don’t:

#site-header {
  margin: 0 auto;
  width: 100%;
}

@media only screen and (min-width: 761px) {
    .site-header {
      width: 80%;
    }
}

Optimize CSS values

CSS values, for the sake of readability and reduction of the number of characters, should be optimized. This means that if there’s a value that expresses the same intent, but with a lower number of characters, then we should prefer to use that value.

Do:

.my-selector {
    margin: 0; //when using 0, don't write 0px
    padding: 0 5px; //group sizes, (t r b l) => (t/b r/l)
    font-size: .9em; //don't include leading zeros

    .child {
        border: 0; //prefer to use 0 instead of none
        margin: 0 5px 5px; //compress complex values by grouping sizes (t r b l) => (t r/l b)
        padding: 1em; //no trailing zeros
    }
}

Don’t:

.my-selector {
    margin: 0px;
    padding: 0px 5px 0px 5px;
    font-size: 0.9em;

    .child {
        border: none;
        margin: 0px 5px 5px 5px;
        padding: 1.0em;
    }
}

Quotes – Which one to choose

Sass isn’t really particular about quotes, but you can get dinged by a linter if you use double-quotes (“”).
The reason is that the creator of Sass prefers single quotes (apostrophes) to double quotes because you don’t have to press the Shift key.

Do:

input[type='text'] {
    background-image: url('http://placekitten.com/200/300');
    &::after { //use double-colons for pseudo selectors
        content: '';
    }
}

Don’t:

input[type=text] {
    background-image: url(http://placekitten.com/200/300);
    &:after {
        content: "";
    }
}

Down with vendor prefixes!!!

There are tools which can fill in vendor prefixes that you can use during the build and compilation process. There’s no need to include vendor prefixes in the Sass code. If you’re given the opportunity to develop for up-to-date browsers that adhere to standards, then you may not need to include vendor prefixes at all, but that is a choice of which browsers you will have to support. The one rule should be to leave vendor prefixes out of your Sass.

If you need to include vendor prefixes for a selector that isn’t automatically handled by a third-party tool, then use a mixin.

Do:

@mixin placeholder {
  &::-webkit-input-placeholder {@content}
  &:-moz-placeholder           {@content}
  &::-moz-placeholder          {@content}
  &:-ms-input-placeholder      {@content}  
}

.cardInfo-security-code, .cardInfo-credit-card-number {
    @include placeholder {
        @include transparent_placeholder; //this is a file name
    }
}

Don’t:

.cardInfo-security-code, .cardInfo-credit-card-number {
    &::-webkit-input-placeholder {
        @include transparent_placeholder;
    }
    &:-moz-placeholder {
        @include transparent_placeholder;
    }
    &::-moz-placeholder {
        @include transparent_placeholder;
    }
    &:-ms-input-placeholder{
        @include transparent_placeholder;
    }
}

End files with newline

This seems like a ridiculous requirement, but it helps with minification. The newline character allows the compiler to merge files together without a statement from another file ending up on the same line as a closing brace.

Do:

.my-class {
    //...
}
//imagine a blank line here

Don’t:

.my-class {
    //...
}

Leave a Reply

Your email address will not be published. Required fields are marked *