乐趣区

CSS 搞事技巧:checkbox+label+selector

介绍
其实这篇文章写到一大半时它的名字还叫做《重温 Flex 布局》,结果写着写着就走了心,附上一图表示心情吧:

其实我并不是一个喜欢搞事的人,真的,从我游戏:屠夫沉默(DOTA2),盖伦(LOL),亚瑟(农药)的英雄池完全可以看出来。
这三个元素作为这个《CSS 搞事技巧》的第一篇并非仅仅是在接下来的《重温 Flex 布局》中要使用,而是因为这个技巧的确是很基础。
核心概念:所谓技巧,无非就是保存状态(划重点啦)。
示例
示例部分仅放 Gif 图样及源码地址,详情请查看技巧说明部分(技巧是通用的)。
1. switch 开关
样式模仿的是 Vuetify 的 Switches。
Gif 预览:

动画源码、在线动画
2. 关灯效果
上面实现了开关,那么一个简单的联想当然是开关灯啦。
Gif 预览:

动画源码、在线动画
技巧说明
在 JavaScript 中,我们可以利用变量,DOM 来保存状态,而 CSS 当中,我们也可以利用伪类选择器来保存状态,这就是 CSS 搞事的核心了,也是上面示例实现的本质。
回到主题,也就是 Flex 布局来,我们初步回顾一下,Flex 布局的相关概念,首先被声明了 Flex 弹性布局的元素叫做弹性容器,其子元素被称为弹性项目。这个弹性容器中默认存在两个轴,一个叫做主轴(main axis),侧轴(cross axis)。整个 Flex 容器具有六个属性,此次仅介绍两个:justify-content 和 align-items(提一下 align-content 是多行的概念)。
列出这个两个属性的常用值(看 MDN 可知已经增加了更多的值):
.flex {
justify-content: flex-start | flex-end | center | space-between | space-around;
align-items: flex-start | flex-end | center;
}
代码解读
该项目是通过 VuePress 来渲染的,所以会使用到 Vue 的语法,不过此处仅使用 Vue 的 for 循环来解决重复书写 DOM 的问题;该效果参考 来源。
1. label
功能栏与展示栏分列两侧,首先是完成 DOM 结构:
flex__feats 为左侧功能栏,flex__exh 为展示栏。
<div class=”flex”>
<section class=”flex__feats”>
<div class=”feat__list”>
<h4 class=”feat__list_title”>justify</h4>
<div class=”feat__list_labels”>
<label>flex-start</label>
<label>flex-end</label>
<label>center</label>
<label>space-between</label>
<label>space-around</label>
</div>
</div>
<div class=”feat__list”>
<h4 class=”feat__list_title”>align</h4>
<div class=”feat__list_labels”>
<label>flex-start</label>
<label>flex-end</label>
<label>center</label>
</div>
</div>
</section>
<div class=”divider”></div>
<section class=”flex__exh”></section>
</div>
接着使用 Flex 布局来将它们分割,因为这次主要将的不是 Flex,所以就不进行阐述了。
<style lang=”stylus” scoped>
.flex
width 100%
height 100%
display flex
*
box-sizing border-box
&__feats
flex-basis 28%
height 100%
display flex
justify-content space-around
.feat__list
display flex
flex-direction column
justify-content flex-start
align-items center
.feat__list_labels
flex-grow 1
display flex
flex-direction column
justify-content space-around
align-items center

.divider
width 1px
height 100%
margin 0 2px
background-color #000;
</style>
可以注意到功能栏的 DOM 结构是重复的,使用 Vue 来简化一下吧:
<section class=”flex__feats”>
<div class=”feat__list” v-for=”(feat, index) in feats()” :key=”index”>
<h4 class=”feat__list_title”>{{feat.title}}</h4>
<div class=”feat__list_labels”>
<label v-for=”(item, index) in feat.list” :key=”index”>{{item}}</label>
</div>
</div>
</section>

<script>
export default {
data() {
return {
bgColor: “#c0c4c3”, // 月影白
feats: () => {
return [
{title: “jusitify”, list: [“flex-start”, “flex-end”, “center”, “space-between”, “space-around”]},
{title: “align”, list: [“flex-start”, “flex-end”, “center”]}
]
}
};
}
};
</script>
2. checkbox
接着需要一堆 checkbox 来触发状态,因为 DOM 解析是深度优先,CSS 中也没有父选择器这一说,虽然有一定的办法 hack 一下,所以这一堆 checkbox 就需要放在顶部:
<div class=”flex”>
<input type=”checkbox” class=”toggle” v-for=”(checkbox, index) in checkboxs()” :id=”checkbox”>
</div>
接着需要将其隐藏:
.toggle[type=”checkbox”]
width 0
height 0
filter opacity(0)
opacity 0
display none
3. selector
要想生效的话,还需要将 input 的 id 绑定到 label 上:
<label v-for=”(item, index) in feat.list” :key=”index” :for=”`${feat.title}-${item}`”>{{item}}</label>
接着利用 selector(选择器),获取到 label 并改变其颜色证明它是被选召的孩子,举个例子(完整版):
#jusitify-flex-start:checked ~ .flex__feats .jusitify-flex-start
padding 4px 4px
background-color #5a191b // 栗紫
color #fffef9 // 雪白
测试绑定情况:

4. 右侧展示
首先在其中添加三个元素,帮助我们观察效果:
<section class=”flex__exh”>
<div class=”exh__item” v-for=”n in 3″ :key=”n”></div>
</section>
&__exh
flex-grow 1
padding 16px
.exh__item
width 15%
height 15%
box-shadow 0 0 4px rgba(0, 0, 0, .5)
&:nth-child(1)
width 18%
height 20%
&:nth-child(2)
width 14%
height 18%
&:nth-child(3)
width 15%
height 15%
接着继续使用 selector 来完成最后的任务,示例(完整版):
#jusitify-flex-start:checked ~ .flex__exh
display flex
justify-content flex-start

这样就大功告成啦,在线查看。
最后
CSS 的美丽是有多个属性组合而成。切记要和设计师搞好关系,不然你这些属性都会了,做出来的东西还是会很难看的……
预告:《重温 Flex 布局》正在路上。
参考资料

Vuetify
配色方案:中国色
MDN

退出移动版