The Ultimate Sass Style Guide

by Tommy Coppers — on  ,  , 

cover-image

Sass Guidelines

The root of a code style is about authorship and presentation rather than function and performance. A considerable amount of time goes into developing a style. Sometimes an engineer will seek out guides, memorize patterns, and write love songs about their beloved methodology. Others might just happen upon their own way of doing things based off of years (or minutes) of developing and organizational preferences. But if styles are purely aesthetic, why do we get so upset when someone disagrees with how we’ve written our code?

Coding Styles Matter. The reason why we hold to our own style standards with white knuckles is because they are our own. They are expressions of ourselves, a portal into our brains, a glimpse of how we process data, and a way to pursue creativity between curly brackets and semi-colons. Styles are a very personal matter, for everyone.

And there’s the problem. As the project scales, so do our efforts in development. More development will result in more authors; more authors result in more personal opinions; those opinions result in disjointed code… You can see how the problem can start snowballing from there.

Personal coding styles work on personal projects, however when the project evolves from personal to communal, communication must be emphasized. Communication is key. Communication comes into play when we consider how code is presented rather than how it performs. The way we author our code provides key insights for other authors and editors. Good style guides make a team more efficient.

Notes
  • A few of the examples below are OpenX-specific, e.g. .ox-btn and ox-color(). Feel free to adapt these to your own purposes.
  • As a full disclosure, our style guide was adapted from some very smart, industry leaders. Why? Because they usually set the beat that the masses dance to.

The Skinny

You talk a lot, give me the tl; dr

General
  • two (2) space indents
  • only one (1) rule per line
  • only one (1) selector per line
  • one (1) space after colons property: value
  • one (1) space before/after ()’s @function () {}
  • one (1) space before {}’s .foo {}
  • tight ()’s @mixin bar ($name, $another-property, $foo: true) {}
  • precede each ruleset with an empty line (double return)
  • no empty lines before closing }s
  • trail each file with an empty line
  • no !important tags
  • max selector depth: four (4)
  • max nesting depth: six (6)
  • use border: 0 instead of border: none
  • only class selectors!
    • attribute & tag selectors are allowed as qualifying selectors input[type='text']
  • use the shorthand properties when available
  • no vendor prefixes (auto-prefixer does it for us)
Selectors
  • BEM (Block Element Modifier) classes .block__element--modifier .person__arm--right
  • prefix project specific classes with ‘ox-‘ .ox-btn .ox-tabs .ox-modal
  • no camelCasing class names
  • no snake_casing class names
  • no unnecessary parent references
  • declare component selectors in _selectors.variables.scss
    • declare as a constant (UPPERCASE_SNAKING)
Quotes
  • single (1) quote surrounding strings $direction: 'right' font-family: 'Open Sans'
  • interpolate variables within a string "What's up, #{$friend}"
Code Structure
  • single file structure:
    • File Variables
      • Theme Map $ox-something-theme: ()
      • Other
    • Functions
    • Mixins
    • Style Declarations
  • style declaration structure
    • declaration specific variables
    • placeholders (@at-root)
    • extends
    • includes
    • element specific style properties
    • element pseudo classes :before :after :hover :first-child
    • BEM elements &__element
    • nested elements
    • modifier elements &--modifier
    • mixin calls with @content coming after any nested selector
  • property sort order (Details in .scss-lint.yml)
    • Layout (Box Model / Positioning)
    • Typography
    • Theming
    • Animations
    • Everything Else
Numbers
  • no leading/trailing 0’s
  • no units appending 0’s
  • put each level of your calculations in ()’s ((3 + 2) * 5)
  • lead and trail mathematical operators + - / * =
  • no ‘magic’ numbers
Colors
  • declare variables in hexadecimal form
  • use the long form of a hexadecimal #ffffff
  • use variables or functions only in style declarations
  • ONLY USE semantic variables only when referring to a color
  • DO NOT USE palette variables for anything other than the _colors.variables.scss file
  • use ox-color() to adjust a color’s tone
    • do not use lighten() or darken() on this project
Lists
  • < 5 items should be inlined
  • >= 5 items should be on multiple lines
  • unless used as is for CSS purposes, always comma separated;
  • always wrapped in parenthesis;
  • trailing comma if multilines, not if inlined.
  • when adding new items to a list, always use the provided API
Maps
  • trailing space after the colon :
  • opening ( on the same line as the colon :
  • quoted keys if they are strings
  • each key/value pair on its own new line
  • comma , at the end of each key/value
  • trailing comma , on last item to make it easier to add, remove or reorder items
  • closing parenthesis ) on its own new line
  • no space or new line between closing parenthesis ) and semi-colon ;
Variables
  • hyphenate your mutable variables $color-primary
  • UPPERCASE_SNAKE constants $OX_BTN: '.ox-btn'
  • use two (2) hyphens -- to provide a modifier context $gutter--large: 10000000px
  • use the !default flag on any variable that could be overridden before its declaration
  • use the !global flag only when overriding a global variable from a local scope.
Extends
  • Avoid @extend
    • Exceptions: Within a module
      • Use extend on placeholders exclusively, not on actual selectors.
      • Make sure the placeholder you extend is present as little as possible in the stylesheet.
Mixins
  • semantic, hyphenated naming
  • use functional approach @mixin _whisky-helper
  • when omitting parameters, omit parenthesis @include whisky;
  • unit test global mixins
  • comment everything
Functions
  • semantic, hyphenated naming
  • use functional approach @functional _whisky-helper
  • unit test global functions
  • comment everything
Theming
  • include map of colors and possible variations of styles
  • prepend with $ox- and append with -theme(s): $ox-btn-themes
  • only pair semantic base colors with theme properties
  • handle tone changes within style blocks when possible
Files
  • one master project file ox-components.scss to import partials
  • import order:
    • utilities (variables, mixins, functions, etc.)
    • base (project set up, namely typography, icons, tag level elements)
    • modules/components (reusable codeblocks)
    • project-wide layouts (header, footer, navs, etc)
    • app specific alterations (if applicable)
    • page specific alterations (if applicable)
    • shame file (all the gross CSS your grandmother would scold you for)
  • any file not intended to compile into itself should be prepended with an underscore _
  • @import partials without the prepended underscore & without file extension @import colors.variables
  • append ‘.[utility name]’ to all utility file names layouts.mixins.scss
  • use the ‘.scss’ on all Sass files

High Level Syntax & Formatting

Spacing

  • two (2) space indents
  • only one (1) rule per line
  • only one (1) selector per line
  • one (1) space after colons property: value
  • one (1) space before/after ()’s @function () {}
  • one (1) space before {}’s .foo {}
  • tight ()’s @mixin bar ($name, $another-property, $foo: true) {}
  • precede each rule-set with an empty line (double return)
  • trail each file with an empty line
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// ___ Good ___

.foo,
.bar {
  display: block;
  position: absolute;
  top: 3px;
  background: #ffffff;

  .zoo {
    display: inline-block;
    text-align: center;
  }
}

.bar {
  bottom: 3px;
  background: #000;
}

// ___ Bad ___

.foo, .bar {
  display: block;
  position: absolute; top: 3px;
  background: #ffffff;
  .zoo {display: inline-block; text-align: center;}
}
.bar {
  bottom: 3px;
  background: #000;
}

Specificity

Nesting Depth: Max 6 code blocks deep. Nesting is a lot of fun. Sometimes it can be too fun and the trade-off is readability. Keeping the number of nested blocks at bay will help other authors parse the code quickly.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// ___ Kind of hard to read ___
.foo {
  &__bar {
    &--zoo {
      &:first-child {
        &:not('.foo__bar--secondary){
          &:hover {
            &:before {
              content: '';
              background: #ffffff;
            }
          }
        }
      }
    }
  }
}

Max Selector Depth: 4. CSS is all about CASCADING Style Sheets. It is all too tempting to just add another qualifying selector in our declarations so that we can increase specificity instead of leveraging the benefits that come from cascading our styles. Keeping the specificity low means that we can easily tweak a style later on within a different context. Better put, it means less headaches and less !important trump cards.

BTW: BEM is really good for this

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// Good
.ox-table {
  &__cell {
    &__icon {
      font-size: 12px;
    }
  }
}
// => .ox-table__cell__icon {font-size: 12px;} - 1 level


// Bad
table.ox-table {
  tbody {
    tr {
      td {
        &.ox-table__cell {
          span {
            i.ox-table__cell__icon {
              font-size: 12px;
            }
          }
        }
      }
    }
  }
}
// => table.ox-table tbody tr td.ox-table__cell span i.ox-table__cell__icon {font-size: 12px;} - 9 levels

no !important tags. Important tags are not a last resort. They have a very specific intentions and thus only 1 permissible exception: a high-level modifier class, that has styles INTENDED to override all other styles. Best to just not to use them.

Declaration Order

Order Declarations within a rule block as follows:

  • declaration specific variables
  • placeholders (@at-root)
  • extends
  • includes
  • element specific style properties
  • element pseudo classes :before :after :hover :first-child
  • BEM elements &__element
  • nested elements
  • modifier elements &--modifier

Generalities

  • use border: 0 instead of border: none
  • use the shorthand properties when available
  • no vendor prefixes (auto-prefixer does it for us)

Selector Conventions

  • BEM (Block Element Modifier) selector styles .block__element--modifier
  • prefix project specific blocks with ‘ox-‘ .ox-btn .ox-tabs .ox-modal
  • no camelCasing
  • no snake_casing
  • no unnecessary parent references
  • only class selectors!
    • attribute & tag selectors are as qualifying selectors input[type='text']
Why BEM?

Simply put: Simplicity!

BEM is declarative and, though lengthy at times, gives rich insight into what an element is, what it does, and how it can change. It is an attempt at Object Oriented declarations within CSS. One look at a class name and one should be able to tell where how/when an element is used, and where to find it in the codebase.

Benefits from BEM include:

  • Selector specificity reduction
  • Semantic writing
  • Performance boosting!

Strings

Let’s talk quotation marks

Single quotes for the win! This is generality, of course; We’ll allow a combination of single and double quotes in special circumstances; Somethings you might think are strings but really aren’t. Well that’s confusing… Let’s dive in bit further.

Strings in values

CSS (and thus Sass) is a minority language, where quoting is optional for strings. That is, unless the string has whitespace included, then it might complain or fail silently. For standardization with other languages, and really to just avoid conflicts, we should definitely quote actual strings in our CSS values. Here are reasons why:

  • color names are treated as colors when unquoted, which can lead to serious issues;
  • most syntax highlighters will choke on unquoted strings;
  • it helps general readability;
  • there is no valid reason not to quote strings.

So what constitutes a value? Strings as values would be anything that isn’t a preset CSS property value. You’ll mostly find them in these scenarios:

  • Variables
  • Font family names
  • URLs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// ___ Good ___
 $SELECTOR: '.foo__bar--zoo';
 $direction: 'right';

 body {
  font-family: 'Open Sans', 'helvetica';
 }

// ___ Bad ___
 $SELECTOR: .foo__bar--zoo;
 $direction: "right";

 body {
  font-family: Open Sans, 'helvetica';
 }

CSS Identifiers

Sometimes CSS is confusing and something that looks like a string is actually an identifier (or variable of sorts). Basically, if it is a preset value for a property, it is an identifier and the quotes are gonna break the internet. For example, if you were to write position: static, “static” is actually just a codeword for the browser’s rendering engine to render the position in a static way. Adversely, if you were to type position: 'static', the browser is going to choke. Examples of CSS Identifiers:

  • position: relative
  • font-family: sans-serif
  • float: right

Strings with Quotes

Comments are a classic case where combining double and single quotes are allowed. Be smart about it, though and only do it when it’s easier to read. Like the following:

1
2
3
4
5
// Okay
@debug 'the parameter\'s value isn\'t found in this project\'s list.';

// ___ Better ___
@debug "the parameter's value isn't found in this project's list.";

Interpolation in Strings

As far as interpolation goes for strings, if you are going to inject a value into a quote of some sort, we don’t want to break up and concatenate strings. Instead do something like this:

1
2
3
4
5
// ___ Good ___
@warn 'Please choose a variable from the following list: #{$list-of-variables}.  Have a great day!';

// ___ Bad ___
@warn 'Please choose a variable from the following list: ' + $list-of-variables + '. Have a great day!';

If you want to read more:


Numbers

Numbers in Sass represent a data type that is arithmetical and used for making calculations and defining measurements in lengths, frequencies, and durations. Numbers can be unit-less or contain any of the standard CSS units: px, em, rem, s, ms, etc.

The following subsections contain our project’s rules.

Zeros

Do not write leading or trailing zeros

1
2
3
4
5
6
7
8
9
10
11
// ___ Good ___
.foo {
    padding: .5em;
    margin-left: 5rem;
}

// ___ Bad ___
.foo {
    padding: 0.5em;
    margin-left: 5.0rem;
}

Units

0’s should not have units.

Bonus: A unit isn’t actually a string. This is extremely important to remember and a huge pain point for those who are new to Sass. That means if you want to add a unit to a number, you can’t just add the unit by concatenating it, you have to multiply it by 1 unit. The reverse is true when you want to strip a unit.

1
2
3
4
5
6
7
8
9
10
11
12
13
$value: 77;

$length: ($value * 1em); // => 77em  - Number
$length: ($value + em); // => '77em' - String

$new-value: 10px;

$length: ($new-value / 1px) // => 10 - Number


$newest-value: 100%;

$length: ($newest-value / 4) // => 25% - Number

Calculations

Wrap all calculations within parentheses. It increases readability and is a safeguard for when you get your order of operations wrong. There really isn’t a reason not to.

NO MAGIC NUMBERS

Magic numbers are the “I don’t really know why this works… but it works… and so here it is…” kind of numbers. They are dirty, they defy logic, and they make coworkers’ lives miserable. Please, do not ever put in a magic number.

But of course, there are those times where you HAVE TO put one in; Maybe a browser bug; Designs might have some weird requirements. IN THOSE CASES ONLY, please just put down an extensive comment, not out of shame, but in order to help other developers know that it was simply unavoidable.

Further Reading


Colors

We are primarily a #hexadecimal color project. This is mainly because it is easiest to communicate between the UX team and the UI teams. The other reason is because we have Sass to fill in the gaps and adjust other values such as alpha channels, HSL properties, etc. If you are given a any other format, please ask for the hexadecimal equivalent.

Variables

ALL colors should be referenced by $variables or functions. I cannot stress this enough.

The UX team has worked hard on establishing our color palette and their semantic values. By diverging from the provided variables, we are not only compromising our style guide, but could very quite possibly be visually cluttering the final render of our product.

You’ll find the predefined color variables in in our _colors.variables.scss file. Within that file you’ll find something that looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// ___ Color palette ___
$palette-black:      #000000;
$palette-navee:      #002d4d;
$palette-regal-blue: #0068b3;
$palette-green:      #92ac41;
$palette-badass:     #bada55;
$palette-orange:     #ff8e00;
$palette-red:        #dd2c09;
$palette-white:      #ffffff;


// ___ Semantic Naming (Use these) ___
$color-primary:       $palette-green;        // Primary denotes the color associated with the main functionality of the site.  Used to draw the user's eyes to top priority items
$color-secondary:     $palette-regal-blue;   // Secondary denotes the color associated with the extra functionality of the site.  Used to draw the user's eyes to function based items
$color-accent-1:      $palette-badass;       // Accent colors are to add flair to the site.  Not necessarily associated with functionality, but needed in special cases
$color-neutral:       $palette-black;        // Neutral colors are for added contrast to the site.  Usually found in backgrounds and text-colors.
$color-cool-neutral:  $palette-navee;        // Cool Neutrals are used to add contrast to the site.  It is another option to the neutral colors.
$color-white:         $palette-white;


//  ___ Statuses ___
$status-color--info:      $palette-regal-blue;  // Info is to provide more context or further information
$status-color--error:     $palette-red;         // Error represents the color associated to error messaging
$status-color--success:   $palette-badass;      // Success represents the color associated to a success message
$status-color--warning:   $palette-orange;      // Signal should be used to alert a user to use caution
$status-color--required:  $palette-red;         // Signal that an element is required

Please do not use any colors outside of these or their respective variants (described later).

Hold up. Why so many variables?

Good eye. The palette variables are establishing the base colors for our brand in general. Theses variable names are meaningful descriptors of the color itself.

The semantic variables set up the theme of the page by pointing to a palette color and attaching a high-level descriptor of the color’s intention.

Let me reiterate. Palette variables describe color. Semantic variables describe context.

By separating the two, we can avoid problems when/if the theme changes. You wouldn’t want something like $green: orange.

How to use OpenX colors

use the semantic variables Please do not include the palette colors anywhere in the application other than when you are declaring the semantic color variables. By doing this, we can better understand why certain colors are being used.

use high level color variables These variables are mapped to the semantic variables. They are colors like $panel-bg, $font-color, $title-color, and $border-color. This helps to ensure parody across the application.

use the ox-color() function The ox-color function is our OpenX mapping between photoshop and the web world. This is important because the UX team will supply a tone-variation of a base color to apply to an element.

ox-color()

Tone change? What about Sass’s lighten() and darken() modifiers? In short, those functions will convert the color into its HSL (Hue Saturation Lightness) equivalent, adjust the lightness property and then return back the new color. The problem is, each color has it’s own relative lightness, which means your expected results might be dramatically different than what photoshop told you it was going to be. For example, if you were to have a color with a lightness value of 80, but you are told to lighten it 40%, you have adjusted the lightness past it’s maximum 100%, turning it into pure white. Technically, there is a Sass function to scale the color’s lightness proportionally, but unless you were originally intending on manipulating an HSL color, your hue is going to be off. That’s why instead of lightness, we change tone.

tone represents the grayscale influence in a color. tone is how PhotoShop actually adjusts how dark or light a color can get. It does this by tinting, which mixes in a percentage of white into a color, or shading which mixes in a percentage of black into a color.

ox-color then is how engineers and designers at OpenX bridge the communication gap between PhotoShop mockups and the final web rendering. It takes in two parameters – $color and $tone-adjustment. $color will take in the semantic color value as a base color. $tone-adjustment will represent the percentage of white or black to mix into the base color.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// Design says that .foo is primary color +40
// Design says that .bar is secondary color -60

// ___ Good ___
.foo {
  background: ox-color($color-primary, 40); // tints $color-primary by mixing 40% white into it
}

.bar {
  background: ox-color($color-secondary, -60); // shades $color-secondary by mixing 60% black into it
}

// ___ Bad ___
.foo {
  background: lighten($color-primary, 40); // Adjusts the HSL and will return a color different from the mockups
}

.bar {
  background: darken($palette-regal-blue, 60); // Do not use palette colors.  Adjusts the HSL and will return a color different from the mockups
}

APIs

  • Sass has a lot of wonderful color APIs found here: Sass Color Functions
  • The OpenX Framework also has additional color functions found in this file: _colors.functions.scss

Lists

Lists are Sass’s version of arrays. They store a flat collection of data types. They should be formatted according to the following:

  • < 5 items should be inlined
  • >= 5 items should be on multiple lines
  • unless used as is for CSS purposes, always comma separated
  • always wrapped in parenthesis
  • trailing comma if multilines, not if inlined
  • when adding new items to a list, always use the provided API
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// ___ Good ___
$my-list: ('scotch', 'bourbon', 'rye whiskey', 'gin');

// ___ Good ___
$my-list: (
  'apples',
  'bananas',
  $oranges,
  'kiwi',
  77,
  $lil-cuties,
);

// ___ Bad ___
$my-list: ('apples', 'bananas', $oranges, 'kiwi', 77, $lil-cuties,);

// ___ Bad ___
$my-list: 'apples', 'bananas',
  $oranges,
  'kiwi',
  77,
  $lil-cuties
;

Further Reading


Maps

These little gems are a powerhouse for Sass. They are the equivalent to associative arrays, JavaScript objects or hashes. A Sass Map is a collection of key, value pairs.

  • trailing space after the colon :
  • opening ( on the same line as the colon :
  • quoted keys if they are strings
  • each key/value pair on its own new line
  • comma , at the end of each key/value
  • trailing comma , on last item to make it easier to add, remove or reorder items
  • closing parenthesis ) on its own new line
  • no space or new line between closing parenthesis ) and semi-colon ;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// ___ Good ___
$human: (
  'name': 'Harry Potter',
  'gender': 'boy',
  wardrobe: (
    'scarf': ('red', 'gold'),
    'robe': 'black',
  ),
  'hero': false,
);

// ___ Bad ___
$human: (
  name: 'Harry Potter',
  gender: 'boy',
  wardrobe: ('scarf': ('red', 'gold'),'robe': 'black',),
  hero: false,
);

Further Reading


Variables

As a rule of thumb, use variables for anything that is repeated 2+ times or that you plan on being changed.

  • hyphenate your mutable variables $color-primary
  • UPPERCASE_SNAKE constants $OX_BTN: ‘.ox-btn’
  • use two (2) hyphens -- to provide a modifier context $gutter--large: 10000000px
  • use the !default flag on any variables that could be overridden before it’s declaration
  • use the !global flag only when overriding a global variable from a local scope.

Extends

Just don’t

We as developers love the idea of inheritance. That’s why @extend came about. It was a way to group selectors with the same code blocks together in the compiling stage. The ultimate goals were readability and consolidation of code. Unfortunately, over the years it has proved to do more harm than good. This is especially true for developers without an intimate knowledge of the codebase. Really, the argument for consolidation is becoming a moot point as well with Gzip compression. Here are some potential problems with extend:

  • selectors get appended to the wrong section of the code
  • selectors get appended to name-spaced sections of the code
  • CSS output gets bloated when the directive is misused
  • extends fail in outer blocks such as media queries.

… except…

For the above reasons, and to further simplify our process, it is the OpenX policy not to use @extend for global uses. That being said, the only time to use an @extend is within a module/component. If this is the case, move forward with caution and stick to the following:

  • Use extend from within a module, not across different modules.
  • Use extend on placeholders exclusively, not on actual selectors.
  • Make sure the placeholder you extend is present as little as possible in the stylesheet.

Mixins

Mixins keep us DRY, semantic and efficient. They keep us from cluttering our HTML with arbitrary class names, they group logical style blocks together, and they improve readability. Here are some guidelines on how to use them:

Don’t over-engineer

It’s really tempting to write crazy mixins that with a single include could write an entire application’s styles. Though it proves how smart an engineer is, it also becomes an amazingly hard document to follow along. When creating Mixins, use the functional approach. Consider splitting up your mixins into smaller chunks.

When to use

  • if you are going to reuse it, put it in a mixin
  • if it promotes standardization, put it in a mixin
  • if you can name a block of code by it’s function, put it in a mixin @mixin clearfix

Naming

Again, the idea here is semantics. Try to be as descriptive of the mixin’s intent in the name as possible. When using the functional approach, use supporting mixins with an underscore _, the base mixin’s name, and the purpose of the mixin.

1
2
3
@mixin columns () {}
@mixin _columns-parent-styles () {}
@mixin _columns-breakpoint-styles () {}

Test it

If you are writing a mixin intended for cross-app use, you want to add unit tests to your mixin to provide helpful/insightful error messages when something goes wrong.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@mixin columns ($column-nums: 3, $side-gutter: $gutter, $top-gutter: $gutter) {
  $errors: _columns-unit-tests($column-nums, $side-gutter, $top-gutter);

  @if not $errors {
    // do something
  }
}

@function _columns-unit-tests($column-nums, $side-gutter, $top-gutter) {
  $column-nums-types: (number, map);

  @if not index($column-nums-types, type-of($column-nums)) {
    @warn '$column-nums needs to be: #{$column-nums-types}.  It is currently: #{type-of($column-nums)}';
    @return true;
  }

  @return false;
}

Conditional Statements

  • No parentheses unless they are necessary
  • Always an empty new line before @if
  • Always a line break after the opening brace {
  • @else statements on the same line as previous closing brace }
  • Always an empty new line after the last closing brace } unless the next line is a closing brace }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Good
@if $whiskey {
  // ...
} @else {
  // ...
}

// Bad
@if ($support-legacy == true) {
  // ...
}
@else {
  // ...
}

When testing for a falsy value, always use the not keyword rather than testing against false or null.

1
2
3
4
5
6
7
8
9
// ___ Good ___
@if not index($list, $item) {
  // ...
}

// ___ Bad ___
@if index($list, $item) == null {
  // ...
}

Always put the item to check on the left of the comparison operator and the value to check against on the right.

1
2
3
4
5
6
7
8
9
// ___ Good ___
@if $value == 77 {
  // ...
}

// ___ Bad ___
@if 77 == $value {
  // ...
}

Always have a default @return statement on the outside of a conditional block when writing functions.

1
2
3
4
5
6
7
8
// ___ Good ___
@function hotdog ($arg) {
@if $arg {
  @return true;
}

@return false;
}