Skip to content

CSS 实现自适应分隔线的 N 种方法 #122

@iiuhuy

Description

@iiuhuy

分割线是网页中比较常见的一类设计了,比如说知乎的更多回答

image

这里的自适应是指两边的横线会随着文字的个数和父级的宽度自适应

偷偷的看了一下知乎的实现,很显然是用一块白色背景覆盖的,加一点背景就露馅了

image

心想:知乎的前端也不怎么样? 可能别人的重点不在这些上面吧

下面列举几种更好的实现方式,不会露馅的那种

1. 伪元素 + transform:translateX (-100%);

主要原理是设置文本居中 text-align: center;,然后给定两个伪元素,分别绝对定位,那么此时伪元素也是跟随着水平居中的,设置足够的宽度,然后把左边的往左位移 100% 就可以了,父级记得超出隐藏。

具体实现如下

html 结构为

<div class="title">我是分割线</div>

css 样式为

.title {
  position: relative;
  text-align: center;
  overflow: hidden;
  font-size: 14px;
  color: #999;
}
.title::before,
.title::after {
  content: '';
  display: inline-block;
  width: 100%;
  height: 1px;
  position: absolute;
  background: #ccc;
  top: 50%;
}
.title::before {
  margin-left: -10px;
  transform: translateX(-100%);
}
.title::after {
  margin-left: 10px;
}

See the Pen CSS 分隔线 (伪元素 + transform) by XboxYan (@xboxyan) on CodePen.

<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

2. 伪元素 + flex

这个比较好理解了,设置 display:flex,然后两个伪元素分别铺满剩余空间。

具体实现如下

html 结构为

<div class="title">我是分割线</div>

css 样式为

.title {
  display: flex;
  align-items: center;
  font-size: 14px;
  color: #999;
}
.title::before,
.title::after {
  content: '';
  flex: 1;
  height: 1px;
  background: #ccc;
}
.title::before {
  margin-right: 10px;
}
.title::after {
  margin-left: 10px;
}

See the Pen CSS 分隔线 (伪元素 + flex) by XboxYan (@xboxyan) on CodePen.

<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

3. 伪元素 + box-shadow/outline+clip-path

同样利用 text-align: center 使文本和伪元素居中,然后生成足够大的 box-shadow 或者 outline,由于不支持单个方向,所以用 clip-path 或者 clip 裁剪掉

具体实现如下

html 结构为

<div class="title">我是分割线</div>

css 样式为

.title {
  text-align: center;
  font-size: 14px;
  color: #999;
  overflow: hidden;
}
.title::before,
.title::after {
  content: '';
  display: inline-block;
  width: 0;
  height: 1px;
  box-shadow: 0 0 0 9999px #ccc;
  vertical-align: middle;
}
.title::before {
  margin-right: 10px;
  clip-path: polygon(0 0, -9999px 0, -9999px 100%, 0 100%);
}
.title::after {
  margin-left: 10px;
  clip-path: polygon(0 0, 9999px 0, 9999px 100%, 0 100%);
}

See the Pen CSS 分隔线 (伪元素 + box-shadow/outline+clip-path) by XboxYan (@xboxyan) on CodePen.

<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

4. 伪元素 + right:100%

这个实现需要多一层标签,外部仍然是 text-align: center,内部文本里添加两个伪元素绝对定位,其中左边的设置距离右边 100%(相对于文本标签)即可

具体实现如下

html 结构为

<div class="title">
    <span class="inner">我是分割线</span>
</div>

css 样式为

.title {
  text-align: center;
  font-size: 14px;
  color: #999;
  overflow: hidden;
}
.inner {
  position: relative;
}
.inner::before,
.inner::after {
  position: absolute;
  content: '';
  width: 9999px;
  height: 1px;
  background: #ccc;
  top: 50%;
}
.inner::before {
  right: 100%;
  margin-right: 10px;
}
.inner::after {
  margin-left: 10px;
}

See the Pen CSS 分隔线 (伪元素 + right:100%) by XboxYan (@xboxyan) on CodePen.

<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

5. border+transform

这个思路可以不用到伪元素,不过需要额外的标签,给内部文本左右足够大的 1px 边框,此时需要设置 line-height:1px,由于内部整体以及足够大了(超过父级),可以使用绝对定位和 transform: translateX(-50%) 居中

具体实现如下

html 结构为

<div class="title">
    <span class="inner">我是分割线</span>
</div>

css 样式为

.title {
  position: relative;
  text-align: center;
  font-size: 14px;
  color: #999;
  overflow: hidden;
  padding: 0.6em 0; /**把高度撑起来**/
}
.inner {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  white-space: nowrap;
  line-height: 1px;
  border-left: 9999px solid #ccc;
  border-right: 9999px solid #ccc;
  padding: 0 10px;
}

See the Pen CSS 分隔线 (border+transform) by XboxYan (@xboxyan) on CodePen.

<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

6. 伪元素 + border+left/right

这个思路只需要一个伪元素,在文本内部生成一个伪元素,利用足够大的 border 和相同的负值(绝对定位 + left/right)还原位置

具体实现如下

html 结构为

<div class="title">
    <span class="inner">我是分割线</span>
</div>

css 样式为

.title {
  text-align: center;
  font-size: 14px;
  color: #999;
  overflow: hidden;
}
.inner {
  position: relative;
  padding: 0 10px;
}
.inner::before {
  content: '';
  position: absolute;
  height: 1px;
  top: 50%;
  border-left: 9999px solid #ccc;
  border-right: 9999px solid #ccc;
  right: -9999px;
  left: -9999px;
}

See the Pen CSS 分隔线 (伪元素 + border+left/right) by XboxYan (@xboxyan) on CodePen.

<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

7. 伪元素 + table-cell

主要思路为父级设置 display:table,伪元素设置 display:table-cell,并设置足够大的宽度即可

具体实现如下

html 结构为

<div class="title">
    <span class="inner">我是分割线</span>
</div>

css 样式为

.title {
  display: table;
  font-size: 14px;
  color: #999;
}
.inner {
  display: table-cell;
  white-space: nowrap;
  padding: 0 10px;
}
.title::before,
.title::after {
  content: '';
  display: table-cell;
  width: 9999px;
  overflow: hidden;
  background: linear-gradient(#ccc 0, #ccc) center no-repeat; /**这里用线性渐变生成的,也可以用其他方式**/
  background-size: 100% 1px;
}

See the Pen CSS 分隔线 (伪元素 + table-cell) by XboxYan (@xboxyan) on CodePen.

<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

8.fieldset+legend

利用 fieldsetlegend 标签组合,可以天然实现分隔线效果,参考至张鑫旭的这篇文章

具体实现如下

html 结构为

<fieldset class="title">
    <legend class="inner">我是分割线</legend>
</fieldset>

css 样式为

.title {
  font-size: 14px;
  color: #999;
  border: 0;
  border-top: 1px solid #ccc;
  padding: 0;
}
.inner {
  margin: 0 auto;
  padding: 0 10px;
}

See the Pen CSS 分隔线 (fieldset+legend) by XboxYan (@xboxyan) on CodePen.

<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

小结

上面一共列举了 8 中方式来实现分隔线的效果,每种方法思路各不相同,重要的是可以发散自己的想象力,可能这才是 CSS 与其他语言所不同的吧~

这里整理了一下,整体效果如下,可访问这里查看,大家在实际项目中可自行选取所需要的方式

image

可能还有其他方式没有想到,欢迎大家集思广益,在下方留言讨论

Metadata

Metadata

Assignees

No one assigned

    Labels

    CSSCSS 相关

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions