Skip to content

继承(@extend)

Stylus的@extend指令受SASS实现的启发,基本一致,除了些轻微差异。此功能大大简化了继承其他语义规则集的语义规则集的维护。

混合的继承

尽管你可以使用混写实现类似效果,但会导致重复的CSS. 典型的模式式定义如下的几个类名,然后归结到一个元素中,例如"warning message".

该技术实现是没什么问题,但是维护就比较麻烦了

.message,
.warning {
  padding: 10px;
  border: 1px solid #eee;
}

.warning {
  color: #E2E21E;
}
.message,
.warning {
  padding: 10px;
  border: 1px solid #eee;
}

.warning {
  color: #E2E21E;
}

使用 @extend

To produce this same output with @extend, simply pass it the desired selector (note that @extend and @extends are equal, one is just an alias of another). Stylus will then append the .warning selector to the existing .message ruleset.

然后.warning选择器就会继承已经存在的.message规则

.message {
  padding: 10px;
  border: 1px solid #eee;
}

.warning {
  @extend .message;
  color: #E2E21E;
}
.message {
  padding: 10px;
  border: 1px solid #eee;
}

.warning {
  @extend .message;
  color: #E2E21E;
}

这儿是个更复杂的例子,演示了@extend如何级联使用:

red = #E33E1E
yellow = #E2E21E

.message
  padding: 10px
  font: 14px Helvetica
  border: 1px solid #eee

.warning
  @extends .message
  border-color: yellow
  background: yellow + 70%

.error
  @extends .message
  border-color: red
  background: red + 70%

.fatal
  @extends .error
  font-weight: bold
  color: red
red = #E33E1E
yellow = #E2E21E

.message
  padding: 10px
  font: 14px Helvetica
  border: 1px solid #eee

.warning
  @extends .message
  border-color: yellow
  background: yellow + 70%

.error
  @extends .message
  border-color: red
  background: red + 70%

.fatal
  @extends .error
  font-weight: bold
  color: red

这产生如下CSS:

.message,
.warning,
.error,
.fatal {
  padding: 10px;
  font: 14px Helvetica;
  border: 1px solid #eee;
}
.warning {
  border-color: #e2e21e;
  background: #f6f6bc;
}
.error,
.fatal {
  border-color: #e33e1e;
  background: #f7c5bc;
}
.fatal {
  font-weight: bold;
  color: #e33e1e;
}
.message,
.warning,
.error,
.fatal {
  padding: 10px;
  font: 14px Helvetica;
  border: 1px solid #eee;
}
.warning {
  border-color: #e2e21e;
  background: #f6f6bc;
}
.error,
.fatal {
  border-color: #e33e1e;
  background: #f7c5bc;
}
.fatal {
  font-weight: bold;
  color: #e33e1e;
}

目前Stylus与SASS不同之处在于SASS不允许 @extend 嵌套选择器。

form
  button
    padding: 10px

a.button
  @extend form button
Syntax error: Can't extend form button: can't extend nested selectors
        on line 6 of standard input
  Use --trace for backtrace.
form
  button
    padding: 10px

a.button
  @extend form button
Syntax error: Can't extend form button: can't extend nested selectors
        on line 6 of standard input
  Use --trace for backtrace.

Stylus中,只要选择器匹配,就可以生效:

form
  input[type=text]
    padding: 5px
    border: 1px solid #eee
    color: #ddd

textarea
  @extends form input[type=text]
  padding: 10px
form
  input[type=text]
    padding: 5px
    border: 1px solid #eee
    color: #ddd

textarea
  @extends form input[type=text]
  padding: 10px

生成:

form input[type=text],
textarea {
  padding: 5px;
  border: 1px solid #eee;
  color: #ddd;
}
textarea {
  padding: 10px;
}
form input[type=text],
textarea {
  padding: 5px;
  border: 1px solid #eee;
  color: #ddd;
}
textarea {
  padding: 10px;
}

Extending multiple selectors

Stylus allows you to extend multiple selectors at once, just write them with the comma:

.a
  color: red

.b
  width: 100px

.c
  @extend .a, .b
  height: 200px
.a
  color: red

.b
  width: 100px

.c
  @extend .a, .b
  height: 200px

Yielding:

.a,
.c {
  color: #f00;
}
.b,
.c {
  width: 100px;
}
.c {
  height: 200px;
}
.a,
.c {
  color: #f00;
}
.b,
.c {
  width: 100px;
}
.c {
  height: 200px;
}

Extending placeholder selectors

Stylus has a feature similar to the one in Sass — placeholder selectors.

Those selectors should start with a $ symbol (for example, $foo), and are not yielded in the resulting CSS. But you can still extend them:

$foo
  color: #FFF

$foo2
  color: red

.bar
  background: #000
  @extends $foo

.baz
  @extends $foo
$foo
  color: #FFF

$foo2
  color: red

.bar
  background: #000
  @extends $foo

.baz
  @extends $foo

Yielding:

.bar,
.baz {
  color: #fff;
}
.bar {
  background: #000;
}
.bar,
.baz {
  color: #fff;
}
.bar {
  background: #000;
}

Note that if the selector is not extended, it won't be in the resulting CSS, so it's a powerful way to create a library of extendable code. While you can insert code through mixins, they would insert the same code every time you use them, while extending placeholders would give you compact output.

Optional extending

Sometimes it might be usefull to be able to extend something that might or might not exist depending on the context. You can suffix any selector with !optional to achieve this:

$specialDesign
  color: #FFF

.btn
  @extend .design !optional, $specialDesign !optional
$specialDesign
  color: #FFF

.btn
  @extend .design !optional, $specialDesign !optional

Yielding:

.btn {
  color: #fff;
}
.btn {
  color: #fff;
}