css 底部划线_一个非常实用的CSS小技巧,帮你应对各种场景

在页面布局中,常需要为内容块添加底部下划线,但最后一个不应有。传统做法是通过判断并添加类名,但这在动态添加内容时可能导致问题。本文介绍一种使用CSS兄弟选择器`~`的解决方案,避免了多余的类名,适应动态元素变化,使代码更简洁。通过`li:not(:last-child)`选择器,确保只有非最后一个元素有下划线,解决了动态加载时的样式问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题背景

在设计页面时,我们经常会遇到类似这样的页面布局:

ebf11d2d435283deb37482b01c4e8fbd.png

图中一个容器内有多个内容块,每块都有一个底部的下划线,但是一般为了美观,最后一个内容块儿的下划线是要去掉的

接下来我们看看通常情况下,是如何处理这种样式的:

html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
    <style>/* 此处为基本的展示样式,可以忽略不看 */.container{border: 1px solid black;border-radius: 10px;width: 300px;height: 500px;margin: 100px auto;
        }.child{margin: 0 auto;width: 200px;height: 98px;border-bottom: 1px solid rgb(172, 163, 163);line-height: 98px;
        }/* 此处为重点要看的样式 */.last{border-bottom: 0;
        }style>
head>
<body>
    <div class="container">div>

    <script>const elementList = ['我是内容1','我是内容2','我是内容3','我是内容4','我是内容5']const container = document.querySelector('.container')// 动态地向容器添加子元素
        elementList.forEach((v, i, a) => {const el = document.createElement('div')/* 判断添加的子元素是否为最后一个
             若是,则给一个 last 类名
            */
            el.className = i == a.length - 1 ? 'child last' : 'child'
            el.innerHTML = v
            container.appendChild(el)
        })script>
body>
html>

上述代码中,假设我们不知道一共要往容器中添加多少个子元素,所以只能每次添加时都判断一下是否为最后一个,若是的话,就添加一个 last 类名用于清除 border-bottom

这样的确完成可以解决问题,但却存在一个「缺陷」,那就是如果在添加完这些内容以后,又动态地要往这个容器内追加更多的内容时,上一次的最后一个内容块儿底部是没有下划线的,因为它被添加了一个 last 类名,此时就类似于「下拉加载更多」这样一个场景,我们来非常简单地模拟一下:

html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
    <style>/* 此处为基本的展示样式,可以忽略不看 */.container{border: 1px solid black;border-radius: 10px;width: 300px;height: 500px;margin: 100px auto;overflow: scroll;
        }.child{margin: 0 auto;width: 200px;height: 98px;border-bottom: 1px solid rgb(172, 163, 163);line-height: 98px;
        }/* 此处为重点要看的样式 */.last{border-bottom: 0;
        }style>
head>
<body>
    <div class="container">div>

    <script>const container = document.querySelector('.container')const elementList = ['我是内容1','我是内容2','我是内容3','我是内容4','我是内容5']function debounce(fn, delay=500) {let timer = nullreturn function(...args) {if(timer) clearTimeout(timer);
                timer = setTimeout(() => {
                    fn.apply(this, args)
                    clearTimeout(timer)
                }, delay)
            }
        }// 防抖处理let addMore = debounce(function(container, list) {
            list.forEach((v, i, a) => {const el = document.createElement('div')
                el.className = i == a.length - 1 ? 'child last' : 'child'
                el.innerHTML = v
                container.appendChild(el)
            })
        })// 页面初次加载,向容器中动态添加内容
        addMore(container, elementList)// 为容器添加滚动事件
        container.addEventListener('scroll', function() {
            addMore(container, elementList)
        })script>
body>
html>

我们来看看容器向下滚动后会出现什么情况:

afbe6d3c0257465371b912b4de0af869.gif

在上述动图中可以很清晰地看到,每次加载的一段内容后,上一段内容的最后一个内容块儿底部是没有下划线的,这就非常得不友好了

接下来就来介绍一个css小技巧来解决上述问题的尴尬

解决方案

这里可以用到css的「兄弟选择器」,即 element1 + element2,其表示的是选择 element1 之后的处于同一层级的所有 element2

我们来看一下具体的代码实现:

html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
    <style>/* 此处为基本的展示样式,可以忽略不看 */.container{border: 1px solid black;border-radius: 10px;width: 300px;height: 500px;margin: 100px auto;overflow: scroll;
        }.child{margin: 0 auto;width: 200px;height: 98px;line-height: 98px;
        }/* 此处为重点要看的样式 */.child + .child {border-top: 1px solid rgb(172, 163, 163);
        }style>
head>
<body>
    <div class="container">div>

    <script>const container = document.querySelector('.container')const elementList = ['我是内容1','我是内容2','我是内容3','我是内容4','我是内容5']function debounce(fn, delay=500) {let timer = nullreturn function(...args) {if(timer) clearTimeout(timer);
                timer = setTimeout(() => {
                    fn.apply(this, args)
                    clearTimeout(timer)
                }, delay)
            }
        }// 防抖处理let addMore = debounce(function(container, list) {
            list.forEach((v, i, a) => {const el = document.createElement('div')
                el.className = 'child'
                el.innerHTML = v
                container.appendChild(el)
            })
        })// 页面初次加载,向容器中动态添加内容
        addMore(container, elementList)// 为容器添加滚动事件
        container.addEventListener('scroll', function() {
            addMore(container, elementList)
        })script>
body>
html>

上述代码中的 .child + .child 表示选择类名为 child 之后的所有同一层级的类名为 child 的元素,因此第一个类名为 child 的元素是无法被选择到的,因此为了达到效果,我们选择为选择到的每个元素设置 border-top,这样就达到了想要的效果,并且即使之后动态地添加了更多的元素,也不会有什么问题

效果验证:

3610919cb2d3cd2dbc6173dd89440fa1.gif

总结

简单总结一下本文介绍的css小技巧有什么「优点」

  1. 使得项目代码更加简洁
  2. 不会像传统的处理方法那样有多余的类名
  3. 能适应动态改变的元素

希望这个小技巧对你们有所帮助,如果还有别的更巧妙的方法,可以评论告诉我哈~

「推荐阅读」 ?

  • 多图生动详解浏览器与Node环境下的Event Loop
  • 学习过CSS,那你知道BFC是什么吗?
  • 快速使用Vue3最新的15个常用API
  • 关于Vue3获取当前组件实例的 getCurrentInstance 方法的补充
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值