子元素选择器
用法:parent > child { }
子元素选择器通过 > 符连接两个元素,两个元素是严格的父子关系。
例子:
<div class="parent">
<p class="child">我是子元素.child</p>
<p class="child">我是子元素.child</p>
<div class="box">
<p class="child">我是孙子元素.child</p>
</div>
</div>
.parent > .child {
color: #f23;
}
后代元素选择器
用法:parent child { }
后代元素选择器通过一个空格符连接两个元素,child 元素可以是 parent 元素的子元素,也可以是孙子元素,曾孙子元素,曾曾曾。。。
例子:
<div class="parent">
<p class="child">我是子元素.child</p>
<p class="child">我是子元素.child</p>
<div class="box">
<p class="child">我是孙子元素.child</p>
</div>
</div>
.parent .child {
color: #f23;
}
通用兄弟选择器
用法:prev ~ nextAll { }
通过 ~ 符连接两个同级元素,nextAll 元素是 prev 后的所有同级兄弟元素。
这个选择器大家用的肯定很少,但是它其实相当强大,在不可思议的纯CSS导航栏下划线跟随效果这篇文章中,实现核心其实就是使用通用兄弟选择器 ~。
它其实还可以在更多的地方来简化我们的效果实现方式,比如我们要实现一个如下的tab页切换的效果:
通常我们可能直接想到的就是完全使用JavaScript,获取 tab 标签按钮,获取滑动块,通过索引判断,写动画,还得判断方向......想想就麻烦,但是如果配合 ~ 选择器,我们的JavaScript代码就会大量减少。
我就结合效果来逐一分析代码了,全部上上来,大家自己看吧:
<div id="box">
<div class="tab-list">
<div class="tab-item tab-item-active">标签一</div>
<div class="tab-item">标签二</div>
<div class="tab-item">标签三</div>
<div class="tab-item">标签四</div>
</div>
<div class="swiper-list">
<div class="swiper-item swiper-item-active bg-red">第一页内容</div>
<div class="swiper-item bg-yellow">第二页内容</div>
<div class="swiper-item bg-blue">第三页内容</div>
<div class="swiper-item bg-green">第四页内容</div>
</div>
</div>
#box {
width: 600px;
height: 400px;
border: 1px solid #ccc;
}
/* tab标签栏样式 */
.tab-list {
display: flex;
justify-content: space-between;
border-bottom: 1px solid #ccc;
}
.tab-item {
flex: 1;
text-align: center;
line-height: 50px;
cursor: pointer;
}
.tab-item:hover {
background-color: #3f3;
}
.tab-item-active {
background-color: #3f3;
}
/* 滑动块的样式 */
.swiper-list {
box-sizing: border-box;
position: relative;
width: 600px;
height: 349px;
overflow: hidden;
}
/* 下面三个样式规则是实现这个效果的核心 */
.swiper-item {
position: absolute;
left: -100%;
width: inherit;
height: inherit;
transition: all .3s;
}
.swiper-item-active {
left: 0;
}
.swiper-item-active ~ .swiper-item {
left: 100%;
}
/* 滑动内容的背景色 */
.bg-red {
background-color: red;
}
.bg-yellow {
background-color: yellow;
}
.bg-blue {
background-color: blue;
}
.bg-green {
background-color: green;
}
const tabItem = document.querySelectorAll('.tab-item');
const swiperItem = document.querySelectorAll('.swiper-item');
tabItem.forEach((item, index) => {
item.onclick = function () {
const tabActive = document.querySelector('.tab-item-active');
tabActive.classList.remove('tab-item-active')
item.classList.add('tab-item-active');
const swiperActive = document.querySelector('.swiper-item-active');
swiperActive.classList.remove('swiper-item-active')
swiperItem[index].classList.add('swiper-item-active')
}
})
你可能跟我一样,能不用JS的地方就坚决不用JS,所以针对上面的情况,能不能一行JS都不写呢?也不是没有办法。
相邻兄弟选择器
用法:prev + next { }
通过 + 符连接两个同级元素,next 元素是紧挨着 prev 的同级兄弟元素。
伪类选择器 :checked
用法:input:checked { }
表示被选中的 radio、 checkbox、 select 元素。
结合这两个选择器,我们对上面的代码进行修改:
<div id="box">
<!-- 这里通过使用label元素来选中radio -->
<div class="tab-list">
<label class="tab-item-label" for="item-radio-1">标签一</label>
<label class="tab-item-label" for="item-radio-2">标签二</label>
<label class="tab-item-label" for="item-radio-3">标签三</label>
<label class="tab-item-label" for="item-radio-4">标签四</label>
</div>
<div class="swiper-list">
<input type="radio" name="item-radio" class="item-radio" id="item-radio-1" checked>
<div class="swiper-item swiper-item-active bg-red">第一页内容</div>
<input type="radio" name="item-radio" class="item-radio" id="item-radio-2">
<div class="swiper-item bg-yellow">第二页内容</div>
<input type="radio" name="item-radio" class="item-radio" id="item-radio-3">
<div class="swiper-item bg-blue">第三页内容</div>
<input type="radio" name="item-radio" class="item-radio" id="item-radio-4">
<div class="swiper-item bg-green">第四页内容</div>
</div>
</div>
#box {
width: 600px;
height: 400px;
border: 1px solid #ccc;
}
/* tab标签按钮样式 */
.tab-list {
display: flex;
justify-content: space-between;
border-bottom: 1px solid #ccc;
}
.tab-item-label {
position: relative;
flex: 1;
text-align: center;
line-height: 50px;
cursor: pointer;
}
.tab-item-label:hover {
background-color: #3f3;
}
/* 滑动块样式 */
.swiper-list {
box-sizing: border-box;
position: relative;
width: 600px;
height: 349px;
overflow: hidden;
}
.swiper-item {
position: absolute;
left: -100%;
width: inherit;
height: inherit;
transition: all .3s;
}
/* 隐藏input元素 */
.item-radio {
display: none;
}
/* 点击label元素,对应被选中的input后的那个.swiper-item */
.item-radio:checked + .swiper-item {
left: 0;
}
/* 选中的input后的那个.swiper-item后的所有同级.swiper-item */
.item-radio:checked + .swiper-item ~ .swiper-item {
left: 100%;
}
/* 滑动内容背景色 */
.bg-red {
background-color: red;
}
.bg-yellow {
background-color: yellow;
}
.bg-blue {
background-color: blue;
}
.bg-green {
background-color: green;
}
效果如下:
不过这里有个缺陷,就是 tab标签 按钮没有实现选中效果,我暂时还没有想到好的办法,大家可以集思广益,如果有好的实现方式,请一定在评论告诉大家,谢谢!
总结
写了两篇 CSS选择器 的文章,但没有把所有选择器写出来,我也并没有把规范抄一次的打算。这里只写了几个容易混淆的选择器和我暂时发现用的很少,但能力很强的选择器,以后可能还会继续新增,特别是对于伪类选择器和伪元素的使用。
对于新手可以举一反三,对于大牛,就当做抛砖引玉好了,希望能看到大家更多实用的CSS选择器技巧。