◆

Less 嵌套与父选择器 & 用法示例

2023-02-02 01:370

Less 嵌套里的 & 代表「当前这一层展开后的完整父选择器字符串」。理解成字符串替换是关键——它不是「父元素」的意思,而是把父选择器原封不动地插到 & 出现的位置上。搞清这一点,下面几种看起来很绕的写法就都能推出来了。

最实用的场景是配合 BEM 之类的命名规范拼类名:&-ok 直接生成 .button-ok,类名集中在一处维护,改前缀只需改一个地方,同时也避免了多写一层嵌套导致选择器权重升高。除此之外 & 还能表达相邻、后代、同元素多类名这几种关系,写在一起时区别很微妙,容易写错。

下面三段分别是:拼接类名、& 的各种组合形式、以及多层嵌套下 & 会展开成什么。

拼接类名

& 紧跟后缀,直接生成 .button-ok 这样的类名,注意输出里没有任何空格或层级关系——生成的是独立的类选择器,不是后代选择器。

.button {
  &-ok {
    background-image: url('ok.png');
  }

  &-cancel {
    background-image: url('cancel.png');
  }

  &-custom {
    background-image: url('custom.png');
  }
}

// 输出:
.button-ok {
  background-image: url('ok.png');
}

.button-cancel {
  background-image: url('cancel.png');
}

.button-custom {
  background-image: url('custom.png');
}

& 的几种组合形式

这段是四种容易混淆的写法的对比,差别全在 & 之间有没有符号、有没有空格:

  • & + & → .link + .link,相邻兄弟,命中紧跟在另一个 .link 后面的那个(常用来给列表项之间加间距,比 :not(:first-child) 更直观)
  • & & → .link .link,后代,命中嵌套在 .link 内部的 .link
  • && → .link.link,同一个元素上重复出现的类,选中的还是同一批元素,但选择器权重翻倍——这是提升优先级又不用 !important 的常见手段
  • &, &ish → .link, .linkish,逗号分组,&ish 是字符串拼接的结果
.link {
  & + & {
    color: red;
  }

  & & {
    color: green;
  }

  && {
    color: blue;
  }

  &,
  &ish {
    color: cyan;
  }
}

将输出: .link + .link {
  color: red;
}

.link .link {
  color: green;
}

.link.link {
  color: blue;
}

.link,
.linkish {
  color: cyan;
}

多层嵌套时 & 展开成什么

这段是最容易踩坑的地方。嵌套两层后,& 代表的不是 .parent,而是完整的 .grand .parent。所以 & > & 展开成 .grand .parent > .grand .parent——一个四级的选择器,实际页面里几乎不可能有这种 DOM 结构,写出来等于无效样式。

这说明 & 的字符串替换是拿「到当前层为止的整条父选择器」去替的。嵌套越深,& 的内容越长,& & 这类组合就越容易失控。实践中我尽量把嵌套控制在两层内,需要表达相邻或后代关系时直接写死类名,比依赖 & 展开更可控。

.grand {
  .parent {
    & > & {
      color: red;
    }

    & & {
      color: green;
    }

    && {
      color: blue;
    }

    &,
    &ish {
      color: cyan;
    }
  }
}

// 结果是:
.grand .parent > .grand .parent {
  color: red;
}

.grand .parent .grand .parent {
  color: green;
}

.grand .parent.grand .parent {
  color: blue;
}

.grand .parent,
.grand .parentish {
  color: cyan;
}
💬留言板0

还没有留言,来发表第一条吧~

PAGE LOAD / LIVELess 嵌套与父选择器 & 用法示例加载中