likes
comments
collection
share

你的less父级选择器 & 玩出花了吗?

作者站长头像
站长
· 阅读数 29

不知道各位同学有没有觉得现在css在前端圈子里越来越不受“待见”了。原因可能有下:

  • 难以模块化,不可维护,没啥可以深入研究的
  • 面试基本也不会问啊
  • 部分公司还有 css 工程师,前端不需要关心
  • 。。。

但是作为从看张鑫旭大佬的文章才一步步开启我的前端之路的开发er,我可不能“忘了本”。犹记得才刚刚转行那会面试的时候会问我“你觉得自己css和js哪个更擅长?”,我都会不犹豫的说“css”。

平常用 BEM 规则写样式的同学可能经常会遇到下面这样的(类似)场景,标签列表中会有正常状态和选中状态。故事的开始就是起于这样一段html代码:

<!-- 第1种组织形式,个人比较倾向这种 -->
<!-- tag里面的子节点变多的时候不需要给每一个子节点都添加 --active 的修饰符 -->
<div class="tag tag--active">
    <img src="" class="tag__img" />
    <span class="tag__text">222</span>
</div>

<!-- 第2种组织形式 -->
<!-- 可能更符合 bem的 思想(减少样式嵌套)-->
<div class="tag">
    <img src="" class="tag__img--active" />
    <span class="tag__text--active">222</span>
</div>

针对第一种html的结构,如何通过父级选择器 & 更优雅的写出样式。现在我们就从 & 的基础用法一步步说起。

为了方便我们使用命令行测试,请全局安装less

npm install less -g // 当前版本:3.11.3

下面的例子都是基于常见的通过 BEM 写样式的业务场景。

相信看完这篇文章的同学再用 BEM 规则写样式的时候代码一定会洋气的一批。

基本用法

& 运算符表示一个嵌套规则的父选择器

上面是 less 官方对于 & 的定义(请一定要深刻体会),下面我们通过例子来逐步感受。

.header {
    &__text {
        color: #000;
        &--active {
            color: #fff;
        }
    }
    &:before {
        content: '';
        display: block;
    }
    &.test3 {
        font-size: 12px;    
    }
}

通过 lessc 编译后:

.header__text {
  color: #000;
}
.header__text--active {
  color: #fff;
}
.header:before {
  content: '';
  display: block;
}
.header.test3 {
  font-size: 12px;
}

可以看到,& 引用了距离他最近的完整的父级。为什么强调是完整的父级呢,.header__text--active 而不是 .text--active 就是最好的证明。可能很多同学对于 & 的用法也就到这里就结束了(包括我自己以及身边很多工作好多年的同事,没错,我用下面的例子给他们做了测试,哈哈哈哈),如果你对“工程卓越”有追求的话请继续往下看。

高阶用法

对于开篇提到的那个html结构,如何优雅的写active状态的样式覆盖,也有相当一段长的时间困扰着我,甚至写了一段时间这样的代码:

.tag {
    &__img {
        width: 100px;
        height: 100px;
    }
    &__text {
        font-size: 14px;
        color: #fff;
    }
    &--active {
        .tag__img {
            background: #000;
        }
        .tag__text {
            color: #000;
        }
    }
}

简直是丑到家了。实际上各位同学如果真的能理解父级选择器,仔细思考一下同时抛弃你的惯性思维,就能写出下面的代码:

.tag {
    &__img {
        width: 100px;
        height: 100px;
    }
    &__text {
        font-size: 14px;
        color: #fff;
    }
    &--active &__img {
        background: #000;
    }
    &--active &__text {
        color: #000;
    }
}

通过lessc命令看看最终转成啥样:

.tag__img {
  width: 100px;
  height: 100px;
}
.tag__text {
  font-size: 14px;
  color: #fff;
}
.tag.tag--active .tag__img {
  background: #000;
}
.tag.tag--active .tag__text {
  color: #000;
}

请大家好好消化,其实 & 就是代替父级的存在。 在上面场景的基础上,我们再思考下另一个类似的情况:

<div class="tag active">
    <img src="" class="tag__img" />
    <span class="tag__text">222</span>
</div>

和上面不同的是,我们使用active来代替tag--active。这在实际开发的场景中是很常见的。active作为一个全局定义好的通用选中状态,应用到业务场景中。那么现在如何再去覆盖tag__text的样式呢?

.tag {
    &__img {
        width: 100px;
        height: 100px;
    }
    &__text {
        font-size: 14px;
        color: #fff;
    }
    .active & {
        &__text {
            #000;
        }
    }
}

通过lessc命令看看最终转成啥样:

.tag__img {
  width: 100px;
  height: 100px;
}
.tag__text {
  font-size: 14px;
  color: #fff;
}
.active .tag__text {
  color: #000;
}

成功的将active状态下的tag__text的文字颜色改成了黑色。这里我们注意到 & 放到了类名后面,请大家再次体会一下。其实 & 的位置放在哪里都是可以当作父级来使用的,使用的次数也没有限制,可以使用两个甚至更多。

结束

文章到这里就结束了,希望看完的同学能增加对于 & 的认识,更重要的是能重拾起来对于样式的“工程卓越”的追求。最后,以此文纪念自己刚开始学习前端的日子。