Skip to content

Commit a6a2e3e

Browse files
committed
Advise against @extend, enable SCSS-lint ExtendDirective
@extend is unintuitive and dangerous, so we are recommending against its use. As part of this commit, I enabled the SCSS-lint linter that will warn against its use. I also revised content that mentioned @extend, to maintain philosophical consistency.
1 parent bf1e947 commit a6a2e3e

File tree

2 files changed

+12
-66
lines changed

2 files changed

+12
-66
lines changed

.scss-lint.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ linters:
1010
DeclarationOrder:
1111
enabled: false
1212

13+
ExtendDirective:
14+
enabled: true
15+
1316
LeadingZero:
1417
enabled: false
1518

README.md

Lines changed: 9 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@
1717
1. [Sass](#sass)
1818
- [Syntax](#syntax)
1919
- [Ordering](#ordering-of-property-declarations)
20-
- [Mixins](#mixins)
21-
- [Placeholders](#placeholders)
20+
- [Extend directive](#extend-directive)
2221
- [Nested selectors](#nested-selectors)
2322

2423
## Terminology
@@ -174,55 +173,41 @@ We recommend creating JavaScript-specific classes to bind to, prefixed with `.js
174173
### Syntax
175174

176175
* Use the `.scss` syntax, never the original `.sass` syntax
177-
* Order your `@extend`, regular CSS and `@include` declarations logically (see below)
176+
* Order your regular CSS and `@include` declarations logically (see below)
178177

179178
### Ordering of property declarations
180179

181-
1. `@extend` declarations
180+
1. Property declarations
182181

183-
Just as in other OOP languages, it's helpful to know right away that this “class” inherits from another.
182+
List all standard property declarations, anything that isn't an `@include` or a nested selector.
184183

185184
```scss
186185
.btn-green {
187-
@extend %btn;
188-
// ...
189-
}
190-
```
191-
192-
2. Property declarations
193-
194-
Now list all standard property declarations, anything that isn't an `@extend`, `@include`, or a nested selector.
195-
196-
```scss
197-
.btn-green {
198-
@extend %btn;
199186
background: green;
200187
font-weight: bold;
201188
// ...
202189
}
203190
```
204191

205-
3. `@include` declarations
192+
2. `@include` declarations
206193

207-
Grouping `@include`s at the end makes it easier to read the entire selector, and it also visually separates them from `@extend`s.
194+
Grouping `@include`s at the end makes it easier to read the entire selector.
208195

209196
```scss
210197
.btn-green {
211-
@extend %btn;
212198
background: green;
213199
font-weight: bold;
214200
@include transition(background 0.5s ease);
215201
// ...
216202
}
217203
```
218204

219-
4. Nested selectors
205+
3. Nested selectors
220206

221207
Nested selectors, _if necessary_, go last, and nothing goes after them. Add whitespace between your rule declarations and nested selectors, as well as between adjacent nested selectors. Apply the same guidelines as above to your nested selectors.
222208

223209
```scss
224210
.btn {
225-
@extend %btn;
226211
background: green;
227212
font-weight: bold;
228213
@include transition(background 0.5s ease);
@@ -233,51 +218,9 @@ We recommend creating JavaScript-specific classes to bind to, prefixed with `.js
233218
}
234219
```
235220

236-
### Mixins
237-
238-
Mixins, defined via `@mixin` and called with `@include`, should be used sparingly and only when function arguments are necessary. A mixin without function arguments (i.e. `@mixin hide { display: none; }`) is better accomplished using a placeholder selector (see below) in order to prevent code duplication.
239-
240-
### Placeholders
241-
242-
Placeholders in Sass, defined via `%selector` and used with `@extend`, are a way of defining rule declarations that aren't automatically output in your compiled stylesheet. Instead, other selectors “inherit” from the placeholder, and the relevant selectors are copied to the point in the stylesheet where the placeholder is defined. This is best illustrated with the example below.
243-
244-
Placeholders are powerful but easy to abuse, especially when combined with nested selectors. **As a rule of thumb, avoid creating placeholders with nested rule declarations, or calling `@extend` inside nested selectors.** Placeholders are great for simple inheritance, but can easily result in the accidental creation of additional selectors without paying close attention to how and where they are used.
245-
246-
**Sass**
247-
248-
```sass
249-
// Unless we call `@extend %icon` these properties won't be compiled!
250-
%icon {
251-
font-family: "Airglyphs";
252-
}
253-
254-
.icon-error {
255-
@extend %icon;
256-
color: red;
257-
}
258-
259-
.icon-success {
260-
@extend %icon;
261-
color: green;
262-
}
263-
```
264-
265-
**CSS**
221+
### Extend directive
266222

267-
```css
268-
.icon-error,
269-
.icon-success {
270-
font-family: "Airglyphs";
271-
}
272-
273-
.icon-error {
274-
color: red;
275-
}
276-
277-
.icon-success {
278-
color: green;
279-
}
280-
```
223+
`@extend` should be avoided because it has unintuitive and potentially dangerous behavior, especially when used with nested selectors. Even extending top-level placeholder selectors can cause problems if the order of selectors ends up changing later (e.g. if they are in other files and the order the files are loaded shifts). Gzipping should handle most of the savings you would have gained by using `@extend`, and you can DRY up your stylesheets nicely with mixins.
281224

282225
### Nested selectors
283226

0 commit comments

Comments
 (0)