scss-lint
is a tool to help keep your SCSS files
clean and readable. You can run it manually from the command-line, or integrate
it into your SCM hooks. It uses rules
established by the team at Causes.com.
- Ruby 1.9.3+
- Files you wish to lint must be written in SCSS (not Sass) syntax
gem install scss-lint
Run scss-lint
from the command-line by passing in a directory (or multiple
directories) to recursively scan:
scss-lint app/assets/stylesheets/
You can also specify a list of files explicitly:
scss-lint app/assets/stylesheets/**/*.css.scss
scss-lint
will output any problems with your SCSS, including the offending
filename and line number (if available).
Command Line Flag | Description |
---|---|
-c /--config |
Specify a configuration file to use |
-e /--exclude |
Exclude file from being linted |
-i /--include-linter |
Specify which linters you specifically want to run |
-x /--exclude-linter |
Specify which linters you don't want to run |
-h /--help |
Show command line flag documentation |
--show-linters |
Show all registered linters |
-v /--version |
Show version |
scss-lint
will automatically recognize and load any file with the name
.scss-lint.yml
as a configuration file. It loads the configuration based on
the location of the file being linted, starting from that file's directory and
ascending until a configuration file is found. Any configuration loaded is
automatically merged with the default configuration (see config/default.yml
).
The configuration file is structured like so:
inherit_from: '../../inherited-config.yml'
linters:
BorderZero:
enabled: false
Indentation:
enabled: true
width: 2
All linters have an enabled
option which can be true
or false
, which
controls whether the linter is run. Otherwise, each linter defines its own
configuration options. The defaults are defined in config/default.yml
.
The inherit_from
directive allows a configuration file to inherit settings
from another configuration file. The file specified by inherit_from
is loaded
and then merged with the settings in the current file (settings in the current
file overrule those in the inherited file).
You can also configure scss-lint
by specifying a file via the --config
flag, but note that this will override any configuration files that scss-lint
would normally find on its own (this can be useful for testing a particular
configuration setting, however). Configurations loaded this way will still be
merged with the default configuration specified by config/default.yml
.
scss-lint
is an opinionated tool that helps you enforce a consistent style in
your SCSS. As an opinionated tool, we've had to make calls about what we think
are the "best" style conventions, even when there are often reasonable arguments
for more than one possible style. While all of our choices have a rational
basis, we think that the opinions themselves are less important than the fact
that scss-lint
provides us with an automated and low-cost means of enforcing
consistency.
Any lint can be disabled by using the --exclude_linter
flag.
-
Prefer
border: 0
overborder: none
. -
IDs, classes, types, placeholders, and pseudo-selectors should be all lowercase.
// Incorrect - capitalized class name .Button { ... } // Correct .button { ... }
-
Prefer hexadecimal colors over their human-friendly form.
// Incorrect color: green; // Correct color: #0f0;
Defining colors directly in properties is usually a smell. When you color your body text in a number of places, if you ever want to change the color of the text you'll have to update the explicitly defined color in a number of places, and finding all those places can be difficult if you use the same color for other elements (i.e. a simple find/replace may not always work).
A better approach is to use global variables like
$color-text-body
and refer to this variable everywhere you want to use it. This makes it easy to update the color, as you only need change it in one place. It is also more intention-revealing, as seeing the name$color-text-body
is more descriptive than#333
orblack
. Using color keywords can obfuscate this, as they look like variables. -
Prefer
//
comments over/* ... */
.// Incorrect /* This is a comment that gets rendered */ // Correct // This comment never gets rendered
//
comments should be preferred as they don't get rendered in the final generated CSS, whereas/* ... */
comments do.Furthermore, comments should be concise, and using
/* ... */
encourages multi-line comments can tend to not be concise. -
Write
@extend
statements first in rule sets, followed by property declarations and then other nested rule sets.// Incorrect .fatal-error { color: #f00; @extend %error; p { ... } } // Correct .fatal-error { @extend %error; color: #f00; p { ... } }
-
Functions, mixins, and variables should be declared with all lowercase letters.
// Incorrect - uppercase letters $myVar: 10px; @mixin myMixin() { ... } // Correct $my-var: 10px; @mixin my-mixin() { ... }
-
Prefer hyphens over underscores in function, mixin, and variable names.
// Incorrect - words separated by underscores $my_var: 10px; @mixin my_mixin() { ... } // Correct - words separated by hyphens $my-var: 10px; @mixin my-mixin() { ... }
Hyphens are easier to type than underscores.
The Sass parser automatically treats underscores and hyphens the same, so even if you're using a library that declares a function with an underscore, you can refer to it using the hyphenated form instead.
-
Prefer the shortest possible form for hex colors.
// Incorrect color: #ff22ee; // Correct color: #f2e;
-
Don't combine additional selectors with an ID selector.
// Incorrect - `.button` class is unnecessary #submit-button.button { ... } // Correct #submit-button { ... }
While the CSS specification allows for multiple elements with the same ID to appear in a single document, in practice this is usually a smell. When reasoning about IDs (including selector specificity), it should suffice to style an element with a particular ID based solely on the ID.
Even better would be to never use IDs in the first place.
-
Use two spaces per indentation level. No hard tabs.
// Incorrect - four spaces p { color: #f00; } // Correct p { color: #f00; }
-
Don't write leading zeros for numeric values with a decimal point.
// Incorrect margin: 0.5em; // Correct margin: .5em;
-
Always use placeholder selectors in
@extend
.// Incorrect .fatal { @extend .error; } // Correct .fatal { @extend %error; }
Using a class selector with the
@extend
statement statement usually results in more generated CSS than when using a placeholder selector. Furthermore, Sass specifically introduced placeholder selectors in order to be used with@extend
. -
Prefer the shortest shorthand form possible for properties that support it.
// Incorrect - all 4 sides specified with same value margin: 1px 1px 1px 1px; // Correct - equivalent to specifying 1px for all sides margin: 1px;
-
Split selectors onto separate lines after each comma.
// Incorrect .error p, p.explanation { ... } // Correct - each selector sequence is on its own line .error p, p.explanation { ... }
-
Sort properties in alphabetical order.
It's brain-dead simple (highlight lines and execute
:sort
invim
), and it can benefit gzip compression.Sorting alphabetically also makes properties easier to find. Ordering based on the semantics of the properties can be more problematic depending on which other properties are present.
Note that there are legitimate cases where one needs to explicitly break alphabetical sort order in order to use vendor-specific properties. In this case, this is usually avoided by using mixins from a framework like Compass or Bourbon so vendor-specific properties rarely need to be manually written.
-
Commas in lists should be followed by a space.
// Incorrect @include box-shadow(0 2px 2px rgba(0,0,0,.2)); color: rgba(0,0,0,.1); // Correct @include box-shadow(0 2px 2px rgba(0, 0, 0, .2)); color: rgba(0, 0, 0, .1);
-
Properties should be formatted with no space between the name and the colon, and a single space separating the colon from the property's value.
// Incorrect - space before colon margin : 0; // Incorrect - more than one space after colon margin: 0; // Incorrect - no space after colon margin:0; // Correct margin: 0;
-
Opening braces should be preceded by a single space.
// Incorrect - no space before brace p{ } // Incorrect - more than one space before brace p { } // Correct - exactly one space before brace p { }
-
Property values should always end with a semicolon.
// Incorrect - no semicolon p { color: #fff } // Incorrect - space between value and semicolon p { color: #fff ; } // Correct p { color: $fff; }
-
Omit units on zero values.
// Incorrect - unnecessary units can be omitted margin: 0px; // Correct margin: 0;
- Reports
@debug
statements (which you probably left behind accidentally) - Reports when you define the same property twice in a single rule set
- Reports when you have an empty rule set
We love getting feedback with or without pull requests. If you do add a new feature, please add tests so that we can avoid breaking it in the future.
Speaking of tests, we use rspec
, which can be run like so:
bundle exec rspec
If you're interested in seeing the changes and bug fixes between each version
of scss-lint
, read the SCSS-Lint Changelog.
If you'd like to integrate scss-lint
with Git, check out our Git hook gem,
overcommit.
This project is released under the MIT license.