Mixins allow document authors to define patterns of property value pairs, which can then be reused in other rulesets. The mixin name is a class selector that identifies the mixin being declared. The @mixin
keyword must be followed by the mixin name and a declaration block.
The following lines define a mixin clearfix
, and give it three property-value pairs:
@mixin .clearfix { overflow: hidden; _overflow: visible; zoom: 1; }
Document authors may use mixins to group vendor prefixes and simplify their code during the time it takes for vendors to stabilize their implementations.
The following example groups various vendor prefixes for border-radius:
@mixin .rounded7px {
-moz-border-radius: 7px;
-webkit-border-radius: 7px;
border-radius: 7px;
}
Authors may specify media-dependent @mixins. They are specified via comma separated media types after the URI.
The following lines illustrate how @mixins can be made media-dependent:
@variables .clearfix @media print { overflow: visible; }
In the absence of any media types, the mixin rule is unconditional. Specifying 'all' for the medium has the same effect. The mixins only take effect if the target medium matches the media list. A target medium matches a media list in the same cases that it would for @import.
Value: | [<selector>] [, <selector>]* |
Initial: | none |
Applies to: | all |
Inherited: | no |
Percentages: | N/A |
Media: | all |
Computed value: | as specified |
Include allows the property value pairs in an @mixin to be copied into the current declaration block. An include consists of the include keyword, followed by a colon (:), followed by a value. Around each of these there may be white space. The value may be a simple selector or a comma separated list of simple selectors.
Values have the following meanings:
The following ruleset includes the .clearfix
mixin in the .mainContent
declaration block:
.mainContent { include: .clearfix; }
Selectors may import multiple mixins via a comma separated list of mixin names. The rulesets are imported in the order they are referenced.
The following ruleset includes both '.clearfix' and '.rounded7px':
.mainContent { include: .clearfix, .rounded7px; }
If an included mixin has not been defined, user agents should ignore property value pairs according to the normal rules for invalid constructs and, if the UA provides an API to the document author, it should issue a warning.
In the following example, .mainContent
includes .undefinedMixin
. The user agent should ignore the include because the mixin has not previously been defined:
.mainContent { include: .undefinedMixin; }
If one of the mixins is undefined, the defined mixins are included normally and only the undefined mixin is ignored.
The following example includes both the defined mixin .clearfix
and the undefined mixin .undefinedMixin
. The user agent should include .clearfix
normally and ignore .undefinedMixin
.
.mainContent { include: .clearfix, .undefinedMixin; }
User agents must copy the mixin declaration block into the current ruleset each time the value matches the selector of an @mixin
rule. The specificity and cascading order should be interpreted as if the included declaration block was invoked within the current ruleset. Differences between declared values and imported values should be resolved via the cascade order.
The following example illustrates a difference between declared and imported values because clearfix sets overflow to hidden and the current selector sets it to scroll. The user agent should interpret the selector to overflow scroll because that declaration came after the imported ruleset: @@@rework wording@@@
.mainContent { include: .clearfix; overflow: scroll; }
When the include property is declared more than once, conflicts are resolved according to the normal rules for the cascade. The latter include takes precedence.
In the following example the second include, bar
, overwrites the first. Therefore, only .bar property value pairs are included:
include: .foo; include: .bar;
Once a class name has been associated with a mixin, that class may be used as a part of a complex selector.
The following example defines an empty mixin clearfix
and then applies rules to the :after pseudo class of clearfix:
@mixin .clearfix { } .clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } .mainContent { include: .clearfix; }
When mainContent
includes clearfix
, it also includes the rules applied to pseudo classes like :after
. In effect, .mainContent:after
has all the same properties as .clearfix:after
.
Mixins may have sub-nodes. When a mixin name is part of a complex selector, composed of multiple simple selectors, the styles applied to the subnodes will also be applied to the subnodes of the object that included the mixin.
In the following example, we've abstracted the code necessary to insure sufficient text-contrast on dark background colors. The paragraphs inside .sale
and .help
will also have white text:
body { color: #333; background-color: #fff; } @mixin .contrastAdjust { } .contrastAdjust p { color: #fff; } .sale { background-color: red; include: .contrastAdjust; } .help { background-color: blue; include: .contrastAdjust; }
Imagine that we wanted to use the mixin .rounded7px
on a more complex object. This one has two subnodes; a title and a paragraph. If we wanted all three to have rounded corners, we might need to apply the mixin to its subnodes. @@@not a great example because it links container and content@@@
Consider the following snippet of HTML:
<div class="article">
<h3>Movie: The Last Unicorn (1982)</h3>
<p>I have seen very few films that have actually brought me close to tears, and most of those movies are ones I didn't like. The Last Unicorn is an especially ... (IMDB)</p>
</div>
In the following example, the mixin .rounded7px
applies a border radius to both itself and a subnodes p
and h3
:
@mixin .rounded7px,
.rounded7px p, .rounded7px h3 {
-moz-border-radius: 7px;
-webkit-border-radius: 7px;
border-radius: 7px;
}
When .rounded7px
is included in entry
, post
, and article
, the h3
and p
subnodes inherits the rules defined for .rounded7px .inner
:
.entry { background-color: blue; include: .rounded7px; } .post { background-color: green; include: .rounded7px; } .article { background-color: red; include: .rounded7px; }
User agents should interpret the following code the same way they would the example the preceeded it:
.entry { background-color: blue; } .entry p, .entry h3 { -moz-border-radius: 7px; -webkit-border-radius: 7px; border-radius: 7px; } .post { background-color: green; } .post p, .post h3 { -moz-border-radius: 7px; -webkit-border-radius: 7px; border-radius: 7px; } .article { background-color: red; } .article p, .article h3 { -moz-border-radius: 7px; -webkit-border-radius: 7px; border-radius: 7px; }
An obvious advantage of using include is the reduction in code sent over the wire while at the same time allowing grouping of related code. The same could be accomplished using either a preprocessor or comma separated selectors, but those would not simultaneously achieve those two objectives.
Includes may only refer to a single class name which has been declared using the @mixin
rule, and may not reference a complex selector string. User agents should ignore includes that refer to a complex selector.
The following example is incorrect and should be ignored by the UA. It includes a complex selector html body .foo
:
include: html body .foo;
The ruleset associated with a mixin is treated as though it were declared in the location where the include property was specified.
Mixins do not impact the specificity of the ruleset in which they are invoked.