Guidelines for good SCSS / CSS
Use low-specificity selectors
The more specific the selector is, the less reusable the accompanying CSS is and/or the longer a selector you need to override it. (Or you add !important in places you shouldn't.)
The following should be used sparingly in CSS
idselectors.Complex element/type selectors with attributes such as
button[type=button]andinput[type=text].Descendant combinators such as
#main ol li ulor.process p a.Chaining class names.
buttonandbutton.lg)
High specificity selectors are more likely to create side effects, that have to be undone with more CSS rules or longer selectors.
Avoid nesting SCSS selectors prematurely
SCSS compiles nested selectors into descendant combinators. For example:
#content {
ol {
p {}
}
}
Compiles to:
#content ol p {}
There's a high likelihood, however that your selectors don't need to be that long; ol p would provide the same styling. If the worry is being overly broad, you can get the same results using a class name. This is related to the previous point. Specific selectors are often caused by SCSS nesting.
Nesting selectors can be useful, however, when creating variants. For example:
.button {
&-link {
}
}
Compiles to button-link.
Restrict class names to a single pattern or component type.
For example, don't use .process for lists and as a div or section type. Rules you introduce for div.process probably aren't related to those for ol.process. Instead use .list-process and .section-process.
Favor descriptive class names that describe what the class does or the kind of content it affects
Class names such as .primary, or .section are confusing and more likely to be misused by a colleague than .intro-text or .sidebar.
Use a product-specific prefix to avoid class name collisions
This keeps selector specificity low, while also restricting the side-effects of any one selector.
Don't use @extend
SCSS @extend repeats every instance of the extended selector for the extendee selector. (This will be flagged by our Sass-lint configuration.)
h4 {
color: #c09;
font-size: 1.2rem;
font-weight: 100;
}
label {
@extend h4;
cursor: pointer;
}
.footer h4 {
display: inline;
}
Compiles to:
h4, label {
color: #c09;
font-size: 1.2rem;
font-weight: 100; }
label {
cursor: pointer; }
.footer h4, .footer label {
display: inline; }
Every instance of h4 will also be applied to label. This is usually not the behavior we want, particularly across an entire code base.
CHECK. YOUR. OUTPUT.
Periodically check your generated CSS files (JavaScript too!) to ensure that you didn't introduce bloat with your selectors or asset imports.
True story: we reduced the size of our home page CSS by ~400K by removing SVG fonts. Our Webpack configuration included base64-encoded versions of SVG fonts which dramatically inflated our file size. This fact was discovered only after viewing the generated CSS files.
Help and feedback
Get help from the Platform Support Team in Slack.
Submit a feature idea to the Platform.