nth-child 是 CSS 里,一个不太注目、但在某些场景下很实用的选择器,本文记录码者搬砖过程中使用 nth-child 的一些案例。
选择器是什么
类似:
- #container => 选择页面上 id 为 container 的元素
- .wrapper => 选择别面上 class 为 wrapper 的元素
- p => 选择页面上所有 p 元素
- …
nth-child 同以上这些一样,只不过没那么常见。
如何使用
案例一
- nth-child 是一个伪类选择器,选择的结果是某种元素的第 n 个子元素。
- 类似 hover,要在它前面加个冒号
- 具体写法是
.item:nth-child(2)
,表示选择 class 为 item 且是父元素中第二个子元素的目标
<style>
.item{
background: #000;
margin: 10px;
height: 50px;
}
.item:nth-child(2){
background: #f00;
}
</style>
<body>
<div class="wrapper">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
</body>
注 子元素从第一个开始而不是第零个
案例二
- nth-child 的括号里还支持一个表达式
- 比如
.item:nth-child(2n+1)
代表:class 为 item、且在父元素的排在第 2n+1 个的元素(n 取值为:0,1,2,3,…)也就是第奇数个元素
<style>
.item{
background: #000;
margin: 10px;
height: 50px;
}
.item:nth-child(2n+1){
background: #f00;
}
</style>
<body>
<div class="wrapper">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
</body>
- 当然,
:nth-child(2n)
选择第偶数个元素 :nth-child(3n-1)
等,都是允许的- n 取负值,会有“向前”的效果,比如
:nth-child(-n+3)
选择前三个元素,:nth-child(-2n+10)
选择前十个里面的偶数元素
案例三
- 另外,选取奇数/偶数子元素有一个简写方法
nth-child(odd)
选取奇数元素nth-child(even)
选取偶数元素
实用案例
案例四、table 里的隔行变色
<style>
table{
border-collapse: collapse;
border: 1px solid #000;
}
tr:nth-child(even){ /* 这里 even 效果和 2n 是一样的,都是偶数行 */
background: #ccc;
}
</style>
<body>
<table>
<tr>
<td>aaaaaaaaaaaaaaa</td><td>bbbbbbbbbbbbbbbbb</td>
</tr>
<tr>
<td>aaaaaaaaaaaaaaa</td><td>bbbbbbbbbbbbbbbbb</td>
</tr>
</table>
</body>
案例五、响应式 table
- 在后台管理系统中,一个很常见的场景是:用一个 table 展示一个列表,但是一条记录(一行数据)可能有很多字段,那么就可能在一行里放不开那么多字段,那么就需要把一些字段隐藏掉
<style>
table{
border: 1px solid #000;
}
td{
padding: 10px 15px
}
@media (max-width: 1000px){
td:nth-child(9){
display: none;
}
}
@media (max-width: 900px) {
td:nth-child(8){
display: none;
}
}
@media (max-width: 800px){
td:nth-child(7){
display: none;
}
}
@media (max-width: 700px){
td:nth-child(6){
display: none;
}
}
</style>
<body>
<table>
<tr>
<td>field no.1</td>
<td>field no.2</td>
<td>field no.3</td>
<td>field no.4</td>
<td>field no.5</td>
<td>field no.6</td>
<td>field no.7</td>
<td>field no.8</td>
<td>field no.9</td>
</tr>
<tr>
<td>field no.1</td>
<td>field no.2</td>
<td>field no.3</td>
<td>field no.4</td>
<td>field no.5</td>
<td>field no.6</td>
<td>field no.7</td>
<td>field no.8</td>
<td>field no.9</td>
</tr>
</table>
</body>
- 通常情况下,每一行的最后一列放几个操作按钮:删除、编辑、详情
- 而被隐藏的列,一般可以通过点击详情按钮看到
- 当不知道列数时,比如使用类似 vue 里的循环渲染的方式,这时候,可以多写几个 @media,然后给最后一列加上一个特殊的 class 并添加
display: table-cell;
案例六、响应式菜单
<style>
body{
margin: 0;
}
.menu-container{
width: 900px;
margin: 0 auto;
background: #ddd;
}
.item{
width: 100px;
padding: 10px 20px;
display: inline-block;
}
.item:hover{
background: #ccc;
}
.plus{
position: relative;
display: none;
}
.collapse{
position: absolute;
top: 99%;
display: none;
background: #ddd;
}
.plus:hover .collapse{
display: block;
}
.hidden{
display: none;
width: 100px;
padding: 10px 20px;
}
.hidden:hover{
background: #ccc;
}
@media (max-width: 900px){
.menu-container{
width: 100%;
}
}
@media (max-width: 800px){
.item:nth-child(n+4){
display: none
}
.plus{
display: inline-block;
}
.hidden:nth-child(n+3){
display: block;
}
}
@media (max-width: 660px){
.item:nth-child(n+3){
display: none;
}
.hidden:nth-child(n+2){
display: block;
}
}
@media (max-width: 520px){
.item:nth-child(n+2){
display: none;
}
.hidden:nth-child(n+1){
display: block;
}
}
</style>
<body>
<div class="menu-container">
<div class="item">网页</div>
<div class="item">资讯</div>
<div class="item">图片</div>
<div class="item">音乐</div>
<div class="item">视频</div>
<div class="plus">
<div class="item">+</div>
<div class="collapse">
<div class="hidden">资讯</div>
<div class="hidden">图片</div>
<div class="hidden">音乐</div>
<div class="hidden">视频</div>
</div>
</div>
</div>
</body>
为什么这么做
以上操作都可以通过 js 来实现,那么使用 css 的优点有什么呢
- 写起来,比 js 简单
- 读起来也比较轻松
- 而最主要的一点在于:避免了样式的控制侵入到业务逻辑 => 在写业务逻辑的时候,只关心业务。当业务代码里放了很多控制样式的代码时,代码结构会显得比较复杂
- 另外,配合 less 或者 sass 的函数功能,以上 @media 部分会相当简洁
声明
- 文本中代码的效果看起来比较原始,是因为不想加太多样式,影响可读性(样式多了,都不知道哪些是重点了)
- 本文的目的是进行原理上的探讨,以上代码不适合直接复制,而更适合阅读、思考
- 以上代码和本文全部内容可随意转载、再发表,不需要附加码者的任何信息