你可能不清楚的 CSS 选择器用法(二)

397 阅读5分钟
原文链接: github.com

子元素选择器

用法: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;
}

image

后代元素选择器

用法: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;
}

image

通用兄弟选择器

用法:prev ~ nextAll { }

通过 ~ 符连接两个同级元素,nextAll 元素是 prev 后的所有同级兄弟元素。

这个选择器大家用的肯定很少,但是它其实相当强大,在不可思议的纯CSS导航栏下划线跟随效果这篇文章中,实现核心其实就是使用通用兄弟选择器 ~

它其实还可以在更多的地方来简化我们的效果实现方式,比如我们要实现一个如下的tab页切换的效果:

tab1

通常我们可能直接想到的就是完全使用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 { }

表示被选中的 radiocheckboxselect 元素。

结合这两个选择器,我们对上面的代码进行修改:

  <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;
}

效果如下:

tab2

不过这里有个缺陷,就是 tab标签 按钮没有实现选中效果,我暂时还没有想到好的办法,大家可以集思广益,如果有好的实现方式,请一定在评论告诉大家,谢谢!

总结

写了两篇 CSS选择器 的文章,但没有把所有选择器写出来,我也并没有把规范抄一次的打算。这里只写了几个容易混淆的选择器和我暂时发现用的很少,但能力很强的选择器,以后可能还会继续新增,特别是对于伪类选择器和伪元素的使用。

对于新手可以举一反三,对于大牛,就当做抛砖引玉好了,希望能看到大家更多实用的CSS选择器技巧。