用 Sass 的占位符和混合宏创建可复用的样式

发布于 2021-07-11 21:21:41 字数 7229 浏览 1184 评论 0

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 循环:

  1. 确保 $parent-classes 不是空的
  2. 把所有想转化为以逗号分隔的字符串
  3. 字符串包含的类中调用 @mixin

现在没有 @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/
*/

英文出处:http://jamessteinbach.com/css/sass/creating-repeatable-style-pattern-sass-placeholders-vs-mixins

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

虐人心

有一天你能到我的心里去,你会看到那里全是你给的伤悲。

0 文章
0 评论
24514 人气
更多

推荐作者

qq_Yqvrrd

文章 0 评论 0

2503248646

文章 0 评论 0

浮生未歇

文章 0 评论 0

养猫人

文章 0 评论 0

第七度阳光i

文章 0 评论 0

新雨望断虹

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文