CSS/SASS
File structure
- Use one import file that can be used in to a webpack mix.
- Files that are imported into that single file should have a _underscore before the filename to indicate this is a imported file.
- Structure the files in these folders: ‘Core’ ‘Layouts’ ‘Elements’ ‘Components’.
Core
Use this folder only for styling that will be used globally. Here’s an example:
@import 'core/animation';
@import 'core/base';
@import 'core/typography';
@import 'core/variables';
Example css from the base file
* {
box-sizing: border-box;
}
html {
scroll-behavior: smooth;
}
body {
position: relative;
font-family: $font-family-base;
font-size: $base-font-size;
color: $base-font-color;
background: $body-bg;
text-rendering: optimizeLegibility;
overflow-x: hidden;
}
Layouts
These files are meant for styling for specific layout. The auth screens (Login, register) for example usually have a different layout.
// Layouts
@import 'layouts/app';
@import 'layouts/auth';
Elements
Elements are predefined components in the framework, so for example in Bootstrap the components could be buttons or cards. Here you can place overrides for those components if needed. The name of the file should correspond with the components name from the framework.
// Elements
@import 'elements/buttons';
@import 'elements/cards';
@import 'elements/dropdowns';
// Elements
@import 'elements/primary-button';
@import 'elements/home-card';
@import 'elements/table-dropdown';
Components
This folder is used to store the styling for components that are not predefined by the framework, these are custom made or could be imported outside of the css framework. Examples of those components are footers, headers, multiselect, etc.
// Components
@import 'components/footer';
@import 'components/sidebar';
@import 'components/multiselect';
@import 'components/v-datepicker';
Terminology
Rule declaration
A “rule declaration” is the name given to a selector (or a group of selectors) with an accompanying group of properties. Here’s an example:
.listing {
font-size: 18px;
line-height: 1.2;
}
Selectors
In a rule declaration, “selectors” are the bits that determine which elements in the DOM tree will be styled by the defined properties. Selectors can match HTML elements, as well as an element’s class, ID, or any of its attributes. Here are some examples of selectors:
.my-element-class {
/* ... */
}
[aria-hidden] {
/* ... */
}
Properties
Finally, properties are what give the selected elements of a rule declaration their style. Properties are key-value pairs, and a rule declaration can contain one or more property declarations. Property declarations look like this:
/* some selector */ {
background: #f1f1f1;
color: #333;
}
CSS
Formatting
- Use soft tabs with 2 spaces.
- Use dashes over camelCasing in class names
- Do not use ID selectors
- When using multiple selectors in a rule declaration, give each selector its own line.
- Put a space before the opening brace { in rule declarations.
- Place closing braces of declaration blocks on a new line.
- In properties, put a space after, but not before, the : character.
- Each declaration should appear on its own line for more accurate error reporting.
- End all declarations with a semi-colon. The last declaration’s is optional, but your code is more error prone without it.
- Comma-separated property values should include a space after each comma (e.g.,
box-shadow). - Don’t prefix property values or color parameters with a leading zero (e.g.,
.5instead of0.5and-.5pxinstead of-0.5px). - Lowercase all hex values, e.g.,
#fff. Lowercase letters are much easier to discern when scanning a document as they tend to have more unique shapes. - Use shorthand hex values where available, e.g.,
#fffinstead of#ffffff. - Use 0 instead of none to specify that a style has no border.
- Avoid specifying units for zero values, e.g.,
margin: 0;instead ofmargin: 0px;.
Not so good
.avatar{
border-radius:50%;
border:2px solid white; }
.no, .nope, .not_good {
// ...
}
#lol-no {
// ...
}
Better
.avatar {
border-radius: 50%;
border: 2px solid #fff;
}
.one,
.selector,
.per-line {
// ...
}
Comments
- Prefer line comments (
//in Sass-land) to block comments. - Prefer comments on their own line. Avoid end-of-line comments.
- Write detailed comments for code that isn't self-documenting:
- Uses of z-index
- Compatibility or browser-specific hacks
ID selectors
While it is possible to select elements by ID in CSS, it should generally be considered an anti-pattern. ID selectors introduce an unnecessarily high level of specificity to your rule declarations, and they are not reusable.
JavaScript hooks
Avoid binding to the same class in both your CSS and JavaScript. Conflating the two often leads to, at a minimum, time wasted during refactoring when a developer must cross-reference each class they are changing, and at its worst, developers being afraid to make changes for fear of breaking functionality.
We recommend creating JavaScript-specific classes to bind to, prefixed with .js-:
<button class="btn btn-primary js-request-to-book">Request to Book</button>
SASS
Syntax
- Use the .scss syntax, never the original .sass syntax
- Order your regular CSS and @include declarations logically (see below)
Ordering of property declarations
List @extend(s) First
Knowing right off the bat that this class inherits another whole set of rules from elsewhere is good. Another benefit is that overriding styles for that inherited set of rules becomes much easier.
.weather {
@extend %module;
...
}
List @include(s) Next
Next up is your @includes for mixins and other functions. Again, this is nice to have near the top for reference, but also allows for overrides.
.weather {
@extend %module;
@include transition(all .3s ease-out);
...
}
List “Regular” Styles Next
Adding out regular styles after the @extends and @includes allows us to properly override those properties, if needed.
.weather {
@extend %module;
@include transition(all .3s ease-out);
background: $brand-primary;
...
}
Nested Pseudo Classes and Pseudo Elements Next
Pseudo elements and pseudo classes directly related to the element itself so, for that reason, we nest them first before other selectors. Having pseudo elements come before classes seems to be a bit easier to read, but whether one comes before the other is totally a preference. Either way, it might be best to keep elements with other elements and classes with other classes.
.weather {
@extend %module;
@include transition(all .3s ease-out);
background: $brand-primary;
&:hover {
background: darken($brand-primary, 10%);
}
&::before {
content: "";
display: block;
}
...
}
Nested Selectors Last
Nothing goes after the nested stuff. And the same order as above within the nested selector would apply.
.weather {
@extend %module;
@include transition(all .3s ease-out);
background: $brand-primary;
&:hover {
background: darken($brand-primary, 10%);
}
&::before {
content: "";
display: block;
}
> h3 {
@include transform(rotate(90deg));
border-bottom: 1px solid #fff;
}
...
}
Maximum Nesting
Three Levels Deep. Chances are, if you’re deeper than that, you’re writing a crappy selector. Crappy in that it’s too reliant on HTML structure (fragile), overly specific (too powerful), and not very reusable (not useful). It’s also on the edge of being difficult to understand.
.weather {
.cities {
li {
// no more!
}
}
}
Nest your media queries
The ability to nest media queries in Sass means 1) you don’t have to re-write the selector somewhere else which can be error prone 2) the rules that you are overriding are very clear and obvious, which is usually not the case when they are at the bottom of your CSS or in a different file.
.sidebar {
float: right;
width: 33.33%;
@media screen and (min-width: 992px) {
width: 25%;
}
}
Variables
Use variables for elements that are used multiple times to define the brand and might be subject to change, good examples of those elements are colors, font-family, font-sizes etc…
$brand-primary: #f9f9f9;
$brand-secondary: #f91829;
$font-family-base: 'Gilroy', helvetica, arial, sans-serif;
Naming
Prefer dash-cased variable names (e.g. $my-variable) over camelCased or snake_cased variable names. It is acceptable to prefix variable names that are intended to be used only within the same file with an underscore (e.g. $_my-variable).
Colors
Variablize all colors except perhaps white and black. Chances are a color isn’t one-off, and even if you think it is, once it’s in a variable you might see uses for it elsewhere. Variations on that color can often be handled by the Sass color functions like lighten() and darken() – which make updating colors easier (change in one place, whole color scheme updates).