Merge pull request #309 from tailwindcss/apply-important

Add support for applying classes as `!important`
This commit is contained in:
Adam Wathan 2017-12-13 13:04:06 -05:00 • committed by GitHub
commit d146b996aa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 103 additions and 15 deletions

View file

@ -14,11 +14,36 @@ test("it copies a class's declarations into itself", () => {
})
})
test('it removes important from applied classes', () => {
const output = '.a { color: red !important; } .b { color: red; }'
test('it removes important from applied classes by default', () => {
const input = `
.a { color: red !important; }
.b { @apply .a; }
`
return run('.a { color: red !important; } .b { @apply .a; }').then(result => {
expect(result.css).toEqual(output)
const expected = `
.a { color: red !important; }
.b { color: red; }
`
return run(input).then(result => {
expect(result.css).toEqual(expected)
expect(result.warnings().length).toBe(0)
})
})
test('applied rules can be made !important', () => {
const input = `
.a { color: red; }
.b { @apply .a !important; }
`
const expected = `
.a { color: red; }
.b { color: red !important; }
`
return run(input).then(result => {
expect(result.css).toEqual(expected)
expect(result.warnings().length).toBe(0)
})
})

View file

@ -54,7 +54,69 @@ This is extremely useful when you find a common utility pattern in your HTML tha
}
```
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:
Rules can listed on a single line or with multiple calls to `@@apply`:
```less
.btn {
@@apply .font-bold;
@@apply .py-2;
@@apply .px-4;
@@apply .rounded;
}
```
You can mix `@@apply` declarations with normal CSS declarations too of course:
```less
.btn:hover {
@@apply .bg-blue-dark;
transform: translateY(-1px);
}
```
Any rules mixed in with `@@apply` will have `!important` **removed** by default to avoid specificity issues:
```less
// Input
.foo {
@@apply .bar;
}
.bar {
color: blue !important;
}
// Output
.foo {
color: blue;
}
.bar {
color: blue !important;
}
```
If you'd like to `@@apply` an existing class and make it `!important`, simply add `!important` to the end of the declaration:
```less
// Input
.btn {
@@apply .font-bold .py-2 .px-4 .rounded !important;
}
// Output
.btn {
font-weight: 700 !important;
padding-top: .5rem !important;
padding-bottom: .5rem !important;
padding-right: 1rem !important;
padding-left: 1rem !important;
border-radius: .25rem !important;
}
```
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:
```less
// Won't work:

View file

@ -2,10 +2,8 @@ import _ from 'lodash'
import postcss from 'postcss'
import escapeClassName from '../util/escapeClassName'
function normalizeClassNames(classNames) {
return classNames.map(className => {
return `.${escapeClassName(_.trimStart(className, '.'))}`
})
function normalizeClassName(className) {
return `.${escapeClassName(_.trimStart(className, '.'))}`
}
function findMixin(css, mixin, onError) {
@ -52,14 +50,17 @@ export default function() {
return _.startsWith(mixin, '--')
})
const decls = _.flatMap(normalizeClassNames(classes), mixin => {
return findMixin(css, mixin, message => {
throw atRule.error(message)
const decls = _(classes)
.reject(mixin => mixin === '!important')
.flatMap(mixin => {
return findMixin(css, normalizeClassName(mixin), message => {
throw atRule.error(message)
})
})
})
.value()
decls.forEach(decl => {
decl.important = false
_.tap(_.last(mixins) === '!important', important => {
decls.forEach(decl => (decl.important = important))
})
atRule.before(decls)