关于Sass的&父选择器各种使用

5,517 阅读2分钟

一般我们对于&的常见用法无外乎

.selector {
  // 伪类
  &:hover {
    color: pink;
  }
  
  // 伪元素
  &::after {
    content: " ";
  }
  
  // 级联选择器
  &.active {
    background: blue;
  }
  
  // 反向选择
  .container & {
    color: plum;
  }
}

// 编译后css
.selector:hover {
  color: pink;
}
.selector::after {
  content: " ";
}
.selector.active {
  background: blue;
}
.container .selector {
  color: plum;
}

下面讲下其他常见用法

class与元素同时选择器

例如

.selector {
  color: blue;
}
a.selector {
  color: red;
}

使用了Sass后,利用&父选择器和内嵌特性,我们可以减少类名的重复填写。

但是上面的css样式,好像我们没法用Sass简化了,因为我们没办法写成如下,这样会编译错误

.selector {
  color: blue;
  a& {
    color: red;
  }
}

但如果改成如下

.selector {
  color: blue;
  #{a + &} {
    color: red;
  }
}

虽然能够编译成功,但结果却不是我们想要的了

.selector {
  color: blue;
}
.selector a.selector {
  color: red;
}

所以我们需要使用 @at-root,将选择器在顶层输出

.selector {
  color: blue;
  @at-root #{a + &} {
    color: red;
  }
}

// 可以得到想要的结果
.selector {
  color: blue;
}
a.selector {
  color: red;
}

我们将这一小功能可以封装成mixin

@mixin qualify($selector) {
  @at-root #{$selector + &} {
    @content;
  }
}

日后使用就方便多了

.selector {
  color: blue;
  @include qualify(a) {
    color: red;
  }
}

本节内容来自于www.sitepoint.com/sass-3-4-is…

相邻兄弟选择器

首先我们举个简单的例子

.list {
  .list-item {
    display: block;
    // 省略其他样式
  }

  .list-item + .list-item {
    margin-top: 10px;
  }
}

我们想给.list-item的元素之间添加10px的间距。可是写法太重复了,于是我们变更一下

.list {
  .list-item {
    display: block;
    & + & {
      margin-top: 10px;
    }
  }
}

事实这种写法是错误的,因为编译出来的是

.list .list-item + .list .list-item {
  margin-top: 10px;
}

而若想正确添加间距,我们想要的是

.list .list-item + .list-item {
  margin-top: 10px;
}

因此我们换种下面方式

.list {
  .list-item {
    display: block;

    & + .list-item {
      margin-top: 10px;
    }
  }
}

这样就能够达到目的了。但还是重复了。

这里提一下,如果我们不用class类名,如果知道元素标签类型的话,可以直接使用

.list {
  > li {
    display: block;
  }
  > li + li {
    margin-top: 10px;
  }
}

但是现在我们不考虑这种情况,回到刚才的话题,我们要怎么达到只写一遍.list-item呢,方法当然是有的。 我们把&父选择器当成字符串来处理,首先找到最后一个空格,那么这个空格后面就是当前的选择器.list-item

.list {
  .list-item {
    display: block;
    
    $index: lastIndex(#{&}, " ");
    $selector: string.slice(#{&}, $index);
    
    // $selector即为.list-item
    & + #{$selector} {
      margin-top: 10px;
    }
  }
}

那么我们把这几行封装起来,方便多次使用

@mixin adjacentSiblingSelector {
  $index: lastIndex(#{&}, " ");
  $selector: string.slice(#{&}, $index);
  & + #{$selector} {
    @content;
  }
}

使用时如下,这样就清爽多了

.list {
  .list-item {
    display: block;
    @include adjacentSiblingSelector {
      margin-top: 10px;
    }
  }
}

最后细心的你,应该注意到lastIndex函数,其实Sass是没有这个函数的,我们可以自己封装一个

@function lastIndex($str, $match) {
  $len: string.length($str);
  @while $len > 0 {
    @if string.slice($str, $len, $len) == $match {
      @return $len;
    }
    $len: $len - 1;
  }
  @return -1;
}

以上就是&父选择器的一些用法,希望对你有用