Skip to content

Commit d146b99

Browse files
authored
Merge pull request #309 from tailwindcss/apply-important
Add support for applying classes as `!important`
2 parents 47a3b93 + 6ba8af3 commit d146b99

File tree

3 files changed

+103
-15
lines changed

3 files changed

+103
-15
lines changed

__tests__/applyAtRule.test.js

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,36 @@ test("it copies a class's declarations into itself", () => {
1414
})
1515
})
1616

17-
test('it removes important from applied classes', () => {
18-
const output = '.a { color: red !important; } .b { color: red; }'
17+
test('it removes important from applied classes by default', () => {
18+
const input = `
19+
.a { color: red !important; }
20+
.b { @apply .a; }
21+
`
1922

20-
return run('.a { color: red !important; } .b { @apply .a; }').then(result => {
21-
expect(result.css).toEqual(output)
23+
const expected = `
24+
.a { color: red !important; }
25+
.b { color: red; }
26+
`
27+
28+
return run(input).then(result => {
29+
expect(result.css).toEqual(expected)
30+
expect(result.warnings().length).toBe(0)
31+
})
32+
})
33+
34+
test('applied rules can be made !important', () => {
35+
const input = `
36+
.a { color: red; }
37+
.b { @apply .a !important; }
38+
`
39+
40+
const expected = `
41+
.a { color: red; }
42+
.b { color: red !important; }
43+
`
44+
45+
return run(input).then(result => {
46+
expect(result.css).toEqual(expected)
2247
expect(result.warnings().length).toBe(0)
2348
})
2449
})

docs/source/docs/functions-and-directives.blade.md

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,69 @@ This is extremely useful when you find a common utility pattern in your HTML tha
5454
}
5555
```
5656

57-
Note that `@@apply` **will not work** for mixing in hover or responsive variants of another utility. Instead, mix in the plain version of that utility into the `:hover` pseudo-selector or a new media query:
57+
Rules can listed on a single line or with multiple calls to `@@apply`:
58+
59+
```less
60+
.btn {
61+
@@apply .font-bold;
62+
@@apply .py-2;
63+
@@apply .px-4;
64+
@@apply .rounded;
65+
}
66+
```
67+
68+
You can mix `@@apply` declarations with normal CSS declarations too of course:
69+
70+
```less
71+
.btn:hover {
72+
@@apply .bg-blue-dark;
73+
transform: translateY(-1px);
74+
}
75+
```
76+
77+
Any rules mixed in with `@@apply` will have `!important` **removed** by default to avoid specificity issues:
78+
79+
```less
80+
// Input
81+
.foo {
82+
@@apply .bar;
83+
}
84+
85+
.bar {
86+
color: blue !important;
87+
}
88+
89+
// Output
90+
.foo {
91+
color: blue;
92+
}
93+
94+
.bar {
95+
color: blue !important;
96+
}
97+
```
98+
99+
If you'd like to `@@apply` an existing class and make it `!important`, simply add `!important` to the end of the declaration:
100+
101+
102+
```less
103+
// Input
104+
.btn {
105+
@@apply .font-bold .py-2 .px-4 .rounded !important;
106+
}
107+
108+
// Output
109+
.btn {
110+
font-weight: 700 !important;
111+
padding-top: .5rem !important;
112+
padding-bottom: .5rem !important;
113+
padding-right: 1rem !important;
114+
padding-left: 1rem !important;
115+
border-radius: .25rem !important;
116+
}
117+
```
118+
119+
Note that `@@apply` **will not work** for mixing in hover, focus, or responsive variants of another utility. Instead, mix in the plain version of that utility into the appropriate pseudo-selector or a new media query:
58120

59121
```less
60122
// Won't work:

src/lib/substituteClassApplyAtRules.js

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@ import _ from 'lodash'
22
import postcss from 'postcss'
33
import escapeClassName from '../util/escapeClassName'
44

5-
function normalizeClassNames(classNames) {
6-
return classNames.map(className => {
7-
return `.${escapeClassName(_.trimStart(className, '.'))}`
8-
})
5+
function normalizeClassName(className) {
6+
return `.${escapeClassName(_.trimStart(className, '.'))}`
97
}
108

119
function findMixin(css, mixin, onError) {
@@ -52,14 +50,17 @@ export default function() {
5250
return _.startsWith(mixin, '--')
5351
})
5452

55-
const decls = _.flatMap(normalizeClassNames(classes), mixin => {
56-
return findMixin(css, mixin, message => {
57-
throw atRule.error(message)
53+
const decls = _(classes)
54+
.reject(mixin => mixin === '!important')
55+
.flatMap(mixin => {
56+
return findMixin(css, normalizeClassName(mixin), message => {
57+
throw atRule.error(message)
58+
})
5859
})
59-
})
60+
.value()
6061

61-
decls.forEach(decl => {
62-
decl.important = false
62+
_.tap(_.last(mixins) === '!important', important => {
63+
decls.forEach(decl => (decl.important = important))
6364
})
6465

6566
atRule.before(decls)

0 commit comments

Comments
 (0)