Sass 的最大好处之一就是具有创建可重用代码块的能力。我经常用 %placeholders 或者 @mixins 创建可重用代码模块。占位符(%placeholders)和混合宏(@mixins)之间有很大不同。简而言之:当你需要传递变量时使用混合宏(@mixins),若不需要,则使用占位符(%placeholder)。
我目前在做一个网站,该网站在多个页面下使用相同的网格组件:产品,服务及行业都选择相同的结构布局。我不需要任何变量控制样式,所以我首先想到的是使用占位符。使用 Sass3.3 的占位符,你可以通过用 & 引用父级选择器创建 OOCSS/BEM 选择器。在上一个版本,你可以创建嵌套选择器,现在你可以创建新的选择器:
// ----
// Sass (v3.3.6)
// Compass (v1.0.0.alpha.18)
// ----
/* You can do this with 3.2 & down: */
.parent {
text-align: center;
.child {
text-align: left;
}
}
/* You can do *this* with 3.3: */
.entry {
font-size: 1em;
&-title {
font-size: 2em;
}
}
/* You can do this with 3.2 & down: */
.parent {
text-align: center;
}
.parent .child {
text-align: left;
}
/* You can do *this* with 3.3: */
.entry {
font-size: 1em;
}
.entry-title {
font-size: 2em;
}
我想知道是否可以在一个 &- 嵌套顶部用的 %placeholder,在容器选择器中扩展顶部占位符,让Sass生成所有我需要的新的 &-selectors。事实证明不会生成选择器名。(如果我选套父/子选择器则它会运行顺畅)看下面我想表达的意思:
// ----
// Sass (v3.3.6)
// Compass (v1.0.0.alpha.18)
// ----
/* You can generate nested selectors this: */
%parent {
text-align: center;
.single {
text-align: left;
}
h1 {
font-size: 2em;
}
}
.post-archive {
@extend %parent;
}
/* You cannot generate new selectors like this: */
%article {
font-size: 1em;
&-title {
font-size: 2em;
}
}
.post {
@extend %article;
}
/* You can generate nested selectors this: */
.post-archive {
text-align: center;
}
.post-archive .single {
text-align: left;
}
.post-archive h1 {
font-size: 2em;
}
/* You cannot generate new selectors like this: */
.post {
font-size: 1em;
}
现在我能使用 @mixin 获取我想要的。那是有效的,但是它会重复代码:每次我运行 @mixin,在我的样式表中新的地方我都将得到相同的样式。我不想重复。如果用组合选择器,只调用 @mixin 一次,那么我能避免重复:
// ----
// Sass (v3.3.6)
// Compass (v1.0.0.alpha.18)
// ----
/* Here's my mixin, but it will repeat itself too much for my taste: */
@mixin grid() {
width: 100%;
&-item{
width: 33%;
padding: 1em;
}
}
.products {
@include grid();
}
.services {
@include grid();
}
/* Ah, here's a better way to use the mixin.
Only problem is I have to use put all my parent classes in the same place. */
.products,
.services {
@include grid();
}
/* Here's my mixin, but it will repeat itself too much for my taste: */
.products {
width: 100%;
}
.products-item {
width: 33%;
padding: 1em;
}
.services {
width: 100%;
}
.services-item {
width: 33%;
padding: 1em;
}
/* Ah, here's a better way to use the mixin.
Only problem is I have to use put all my parent classes in the same place. */
.products,
.services {
width: 100%;
}
.products-item,
.services-item {
width: 33%;
padding: 1em;
}
这几乎是我知道的最枯燥无味的解决方式了。如果你不需要保持父选择器为独立部分,你可以同时一起申明他们并且在他们上面同时运行@mixin。但是,如果你喜欢先进的Sass且不介意付出额外的劳动,则请继续阅读下面的内容。
如果你需要保持你的父级/容器选择器为独立部分,却仍然想避免相同的样式,你可以在项目中先设置空列表变量,在适合的地方为每个单独的部分中增加父级类,然后在空列表尾部调用 @mixin。下面例子可以说明我的意思:
// ----
// Sass (v3.3.6)
// Compass (v1.0.0.alpha.18)
// ----
$red: #ff4242;
// Declare this variable early
$parent-classes: '';
// This mixin holds the style code you want to repeat
@mixin grid() {
width: 100%;
&-item {
width: 33%;
padding: 1em;
&-title {
color: $red;
text-transform: uppercase;
}
}
}
// In _products.scss:
$parent-classes: join('.products-grid', $parent-classes);
// In _services.scss:
$parent-classes: join('.services-grid', $parent-classes);
// In _industries.scss:
$parent-classes: join('.industries-grid', $parent-classes);
// Do this near the end:
@if $parent-classes != '' {
$i: 1;
$return: '';
@each $class in $parent-classes {
@if $i > 1 {
$return: $return + ", ";
}
$return: $return + $class;
$i: $i + 1;
}
#{$return} {
@include grid();
}
}
/* Read the detailed explanation behind this gist here:
http://jamessteinbach.com/css/sass/creating-repeatable-style-pattern-sass-placeholders-vs-mixins/
*/
.industries-grid, .services-grid, .products-grid {
width: 100%;
}
.industries-grid-item, .services-grid-item, .products-grid-item {
width: 33%;
padding: 1em;
}
.industries-grid-item-title, .services-grid-item-title, .products-grid-item-title {
color: #ff4242;
text-transform: uppercase;
}
/* Read the detailed explanation behind this gist here:
http://jamessteinbach.com/css/sass/creating-repeatable-style-pattern-sass-placeholders-vs-mixins/
*/
最后的 @if 循环:
现在没有 @mixin 代码是重复的,所有的父类可以存在他们自己的部分中,所有的 OOCSS/BEM 子项类能够正确生成。
当然,这个不只是适用于网格系统,它适用于任何嵌套样式,这些样式你需要在元素重复用不同类名称。请在评论中让我知道你如何使用这种模式。或者,如果你找到一个更好的方式,也分享一下,谢谢!
感谢 Hugo,他提交了一个 更为简洁的版本,该版本用一种更直接的方式处理父组合选择器,从而不需要使用最后的 @if 循环:
// ----
// Sass (v3.3.8)
// Compass (v1.0.0.alpha.19)
// ----
$red: #ff4242;
// Declare this variable early
$parent-classes: ();
// This mixin holds the style code you want to repeat
@mixin grid() {
width: 100%;
&-item {
width: 33%;
padding: 1em;
&-title {
color: $red;
text-transform: uppercase;
}
}
}
// In _products.scss:
$parent-classes: append($parent-classes, #{'.products-grid'}, comma);
// In _services.scss:
$parent-classes: append($parent-classes, #{'.services-grid'}, comma);
// In _industries.scss:
$parent-classes: append($parent-classes, #{'.industries-grid'}, comma);
// Do this near the end:
#{$parent-classes} {
@include grid();
}
/* Read the detailed explanation behind this gist here:
http://jamessteinbach.com/css/sass/creating-repeatable-style-pattern-sass-placeholders-vs-mixins/
*/
.products-grid, .services-grid, .industries-grid {
width: 100%;
}
.products-grid-item, .services-grid-item, .industries-grid-item {
width: 33%;
padding: 1em;
}
.products-grid-item-title, .services-grid-item-title, .industries-grid-item-title {
color: #ff4242;
text-transform: uppercase;
}
/* Read the detailed explanation behind this gist here:
http://jamessteinbach.com/css/sass/creating-repeatable-style-pattern-sass-placeholders-vs-mixins/
*/
