广州总部电话:020-85564311
广州总部电话:020-85564311

广州网站建设-小程序商城开发-广州小程序开发-企业微信开发公司-网站建设高端品牌-优网科技

20年
互联网应用服务商
请输入搜索关键词
知识库 知识库

优网知识库

探索行业前沿,共享知识宝库

CSS grid 布局如何添加分隔线?
发布日期:2025-04-29 17:12:32 浏览次数: 820 来源:前端侦探

分享一些超级实用的布局小技巧。

平时开发过程中会碰到各式各样的布局,如下是一个7* N的网格布局,不过每一行还有一条分隔线

image-20250419142949987

这种布局该如何实现呢?

一、grid 布局结构与局限

这里的内容都是后端返回的,通常是一个完整的一维数组

const list =[
 {...},
 {...},
 //...
]

众所周知,grid是二维布局,可以在扁平dom结构下直接实现网格布局

<div class="grid">
 <div class="grid-item">1</div>
 <div class="grid-item">2</div>
 <div class="grid-item">3</div>
 <div class="grid-item">4</div>
 <div class="grid-item">5</div>
 <div class="grid-item">6</div>
 <div class="grid-item">7</div>
 <div class="grid-item">8</div>
  ...
</div>

然后设置grid样式

.grid{
 display: grid;
 grid-template-columns:repeat(7,1fr);
 width:300px;
 padding:10px;
 border:1px solid #ccc;
 border-radius:5px;
 margin:20px auto;
}

效果如下,很方便就实现一个网格布局

image-20250419150527200

由于每一行还有一条单独的分隔线,看似好像无法处理?毕竟 grid 没有所谓的行选择器

这时,很多同学可能会单独给每一行包一层,合成一个二维数组

const grouplist =[
 [{...},{...},{...},{...},{...},{...},{...}],// 每一行7个
 //...
]

自然dom结构也需要包裹一层,然后给每一行单独样式。

<div class="list">
 <div class="col"><!--设置样式-->
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
 </div>
 <div class="col"> ...</div>

</div>

虽然也能实现,但还是有些繁琐,也不够优雅

那么,有没有办法在不嵌套的情况实现分隔线呢?

二、使用渐变实现

我们可以直接绘制重复平铺的渐变,原理其实也很简单

假设每一行的高度固定为--size,那么我们需要绘制一条从透明到实色的渐变,线条的高度是1px,然后背景尺寸是--size,这样渐变就会自动平铺,形成我们所需的网格线效果,原理如下

image-20250425193050298

用代码实现就是

.grid{
 /**/
 --size:54px;
 background:linear-gradient(transparent0calc(var(--size)-1px),red)01px/100%var(--size);
}

效果是这样的

image-20250425193448881

看着好像和每一行没对齐?

其实是因为我们设置了padding,渐变会默认从padding-box开始平铺,也就是起始点是从内边距开始的,所以我们要改变一下,让他从内容盒子开始

.grid{
 background-origin: content-box;
}

效果如下

image-20250425193710051

对齐了,但是上下多了两条,有没有什么办法去掉呢?

还是盒子的问题,渐变默认会充满padding-box,也需要改一下

.grid{
 background-clip: content-box;
}

这样上右左,只要在padding区域的渐变都被裁剪了,不过地下还是有一条线

image-20250425193934087

因为刚好处于平铺的最下方,仍然位于content-box内,所以没有被裁掉,那有没有办法去掉呢?

其实将整个容器的高度减少1个像素就可以让下方的线条出去了,不过试了几种方式都不能很好解决,没办法,我们将这层背景绘制在一个单独的伪元素上,使用伪元素可以方便的控制尺寸,也无需改变padding-box

.grid::before{
 content:'';
 position: absolute;
 inset:10px10px11px;/*底部多一像素*/
 background:linear-gradient(transparent0calc(var(--  size)-1px),red)00/100%var(--size);
 pointer-events: none;
}

这样就完美实现了

image-20250425200529835

你也可以访问在线demo真实体验:https://codepen.io/xboxyan/pen/azzWGYM[1]

不过这种方式要求每一行高度是固定,提前算好的,如果每一行的高度会发生变化就不适用了

三、用上下border实现

我们可以给每个子元素设置上边框来实现分隔线效果

.grid-item
 border-top:1px solid #ccc
}

缺点很明显,第一行是多余的,而且当最后一行不足时,边框就断开了,效果如下

image-20250419151636163

我们可以换个方向,用下边框实现

.grid-item{
 border-bottom:1px solid #ccc
}

稍微好点了,只是最后一行有点多余,效果如下

image-20250419151952511

如何把最后的尾巴去掉呢?也就是如何选中grid布局的最后一行?

这里可以一一列举,比如当最后一行只有一个元素时(其实是「最后一个元素并且是每一行的第一个,需同时满足」

.grid-item:last-child:nth-child(7n+1){
 border: none
}

同时满足这两个条件即可确定是最后一行的第一个, 示意如下

image-20250421101716395

然后是最后一行只有两个元素(「倒数第二个元素并且是每一行的第一个」

.grid-item:nth-last-child(2):nth-child(7n+1),
.grid-item:nth-last-child(2):nth-child(7n+1)~.grid-item{
 border: none
}

示意如下

image-20250421101909227

依次类推,完整选择器代码是

/*1*/
.grid-item:last-child:nth-child(7n+1),
/*2*/
.grid-item:nth-last-child(2):nth-child(7n+1),
.grid-item:nth-last-child(2):nth-child(7n+1)~.grid-item,
/*3*/
.grid-item:nth-last-child(3):nth-child(7n+1),
.grid-item:nth-last-child(3):nth-child(7n+1)~.grid-item,
/*4*/
.grid-item:nth-last-child(4):nth-child(7n+1),
.grid-item:nth-last-child(4):nth-child(7n+1)~.grid-item,
/*5*/
.grid-item:nth-last-child(5):nth-child(7n+1),
.grid-item:nth-last-child(5):nth-child(7n+1)~.grid-item,
/*6*/
.grid-item:nth-last-child(6):nth-child(7n+1),
.grid-item:nth-last-child(6):nth-child(7n+1)~.grid-item,
/*7*/
.grid-item:nth-last-child(7):nth-child(7n+1),
.grid-item:nth-last-child(7):nth-child(7n+1)~.grid-item{
 border:0;
}

这样就能选中最后一行行了,虽然看着很多(别急,后面还有其他方案),但是效果很不错

image-20250419154146111

还有其他情况也表现完美

image-20250419154215435

你也可以访问在线demo真实体验:https://codepen.io/xboxyan/pen/PwwqLXM[2]

四、借助伪元素实现

上面虽然能够实现,也非常灵活,如果仅仅是实现分隔线,其实还有另外更巧妙的方案。

还是前面的结构,我们可以给每一行的第一个元素添加一个伪元素,用伪元素实现分隔线

.grid-item:nth-child(7n+1)::before{
 content:'';
 display: block;
 height:1px;
 background-color:#ccc;
}

效果如下

image-20250419160711227

看着好像相差甚远?没关系,我们可以使用绝对定位,需要注意的是,我们需要让伪元素贯穿整行,所以要给外层添加相对定位

.grid{
 position: relative;
}
.grid-item:nth-child(7n+1)::after{
 content:'';
 position: absolute;
 left:10px;/*只设置水平方向定位*/
 right:10px;
 height:1px;
 background-color:#ccc;
}

注意这里只设置了水平方向上的定位(leftright),垂直方向上仍然保持原位,我称之为「不完全绝对定位」,关于这个小技巧,可以参考之前的这篇文章:

你可能不知道的绝对定位

XboxYan,公众号:前端侦探你可能不知道的绝对定位

效果如下

image-20250419160947752

由于不能使用垂直方向定位,这里就用transform实现,然后可以用:not排除掉第一行的元素,具体实现如下

.grid-item:nth-child(7n+1):not(:first-child)::after{
 /*...*/
 transform:translateY(-15px);
}

效果就很完美了,实现也比较简单

image-20250419161739021

你也可以访问在线demo真实体验:https://codepen.io/xboxyan/pen/dPPoLYa[3]

四、总结一下

以上就本文的全部内容了,非常实用的布局小技巧,其实都是选择器的实际运用,你学会了吗?下面总结一下

  1. grid
    布局无法直接选择行
  2. 嵌套的方式实现分隔线有些繁琐,不够优雅
  3. 渐变可以很方便的实现平铺的线条
  4. 默认情况下,渐变会从padding-box开始平铺,也会充满整个padding-box
  5. 使用伪元素可以方便的控制尺寸,可以无需改变padding-box来控制渐变的起始点,也能控制渐变的平铺区域
  6. grid
    布局最后一行可以一一列举处理,比如当最后一行只有一个元素时其实是「最后一个元素并且是每一行的第一个」
  7. 最后一行只有两个元素的条件是「倒数第二个元素并且是每一行的第一个」
  8. 还可以借助伪元素的不完全绝对定位贯穿整行

grid布局现在已经非常普遍了,碰到这种布局都可以尽量用朝这方面考虑,比嵌套二维数组要高效地多。最后,如果觉得还不错,对你有帮助的话,欢迎点赞、收藏、转发 ❤❤❤

[1]https://codepen.io/xboxyan/pen/azzWGYM: https://codepen.io/xboxyan/pen/azzWGYM

[2]https://codepen.io/xboxyan/pen/PwwqLXM: https://codepen.io/xboxyan/pen/PwwqLXM

[3]https://codepen.io/xboxyan/pen/dPPoLYa: https://codepen.io/xboxyan/pen/dPPoLYa

优网科技,优秀企业首选的互联网供应服务商

优网科技秉承"专业团队、品质服务" 的经营理念,诚信务实的服务了近万家客户,成为众多世界500强、集团和上市公司的长期合作伙伴!

优网科技成立于2001年,擅长网站建设、网站与各类业务系统深度整合,致力于提供完善的企业互联网解决方案。优网科技提供PC端网站建设(品牌展示型、官方门户型、营销商务型、电子商务型、信息门户型、DIY体验、720全景展厅及3D虚拟仿真)、移动端应用(手机站APP开发)、微信定制开发(微信官网、微信商城、企业微信)、微信小程序定制开发等一系列互联网应用服务。


我要投稿

姓名

文章链接

提交即表示你已阅读并同意《个人信息保护声明》

专属顾问 专属顾问
扫码咨询您的优网专属顾问!
专属顾问
马上咨询
联系专属顾问
联系专属顾问
联系专属顾问
扫一扫马上咨询
扫一扫马上咨询

扫一扫马上咨询

和我们在线交谈!