使用CSS给标题添加书名号并超出省略

欢迎关注我的公众号:前端侦探

分享一些CSS处理文本小技巧。

比如,有一些书名或者标题,默认是没有书名号的,结构如下

html 复制代码
<h3 class="books">灵境行者</h3>
<h3 class="books">斗破苍穹</h3>
<h3 class="books">我师兄实在太稳健了</h3>
...

有没有什么办法在不改变HTML的情况下加上书名号呢?🤔(例如某些情况下HTML由其他框架生成,无法直接改底层源码)

进一步,还需要书名号内部实现文本超出省略,如下

这就需要CSS动态生成技术了,你有什么想法呢?一起看看吧

一、使用伪元素生成书名号

没错,很多同学可能会想到用伪元素,前后各添加一个就好了

css 复制代码
.books::before{
  content: '《'
}
.books::after{
  content: '》'
}

效果如下

除了手动使用伪元素生成伪元素外,还可以用 CSS quotes 来生成书名号

css 复制代码
.books{
  quotes: "《" "》"
}

但是,普通元素直接写这个没什么效果,只有q标签才会显示书名号

html 复制代码
<q class="books">灵境行者</q>
<h3 class="books">斗破苍穹</h3>
<h3 class="books">我师兄实在太稳健了</h3>
...

原因是,q标签会自带默认样式,自动创建了伪元素

所以,普通元素如果也想用quotes属性,可以手动添加

css 复制代码
.books::before{
  content: open-quote
}
.books::after{
  content: close-quote
}

效果如下

不过这样好像还不如直接使用伪元素方便了吧?😂

二、书名号内文本超出省略

CSS 单行文本超出省略很容易,只需要下面 3 行

css 复制代码
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;

当宽度比较小时,部分标题也发生了省略,如下

有设计师表示,这样不是很好看🙅🏻‍♀️,这个省略号能否在书名号里面呢,就像这样

正常情况下,我们会选择给中间的文本额外新增一层标签,然后把文字省略设置在这个标签上

html 复制代码
<q class="books"><span>灵境行者</span></q>
<h3 class="books"><span>斗破苍穹</span></h3>
<h3 class="books"><span>我师兄实在太稳健了</span></h3>
...

但是如果无法更改HTML结构,这里有办法只用一层标签实现吗?

当然也是有的,下面介绍两个思路

三、好用的绝对定位

书名号之所以会连同文本一起被省略,在于和标题文本处于同一文本流中,所以需要将这个书名号提取出来,脱离这个文本流。

首先可以想到的是绝对定位,需要注意给右侧留一点内边距(不然就重叠了),这里给一个字号宽度

css 复制代码
.books{
  position: relative;
  padding-right: 1em;/*只能大概给一个固定距离*/
}
.books::after{
  position: absolute;
  right: 0;
}

效果如下

由于是块级元素,宽度默认撑满,所以书名号跑到最右边了,可以给元素加一个最大宽度为文本宽度

css 复制代码
.books{
  /**/
  max-width: fit-content;
}

这样就正常了

完整代码可以查看:codepen.io/xboxyan/pen...

四、有些冷门的浮动

除了前面的绝对定位,浮动也能实现类似的效果。

css 复制代码
.books::after{
  float: right
}

效果如下

但是当文本过长时,浮动元素掉下来了,并没有实现环绕效果。

其实,这个跟文档的顺序有关,浮动元素必须位于前面才行,也就是::before元素才可以,我们试试

css 复制代码
.books::before{
  float: right
}

效果如下,很好的位于最右侧(红色部分)

那么现在问题来了,::before被用掉了,用于生成右书名号,那通过什么来生成左书名号呢?

思索了一番,整个CSS中还有一个伪元素可以生成文本,那就是::marker,而且也位于左侧。不过需要设置display属性为list-item才会出现

css 复制代码
.books{
  /**/
  display: list-item;
  list-style-position: inside;
}
.books::marker{
  content: '《';
}
.books::before{
  content: "》";
  float: right;
  color: red;
}

这样就能代替原本的::before生成左书名号了(左侧是::marker,右侧是::before

同样还有最大宽度的问题

css 复制代码
.books{
  /**/
  max-width: fit-content;
}

同样能实现类似的效果,相比绝对定位来说,无需给一个"大概"的右内边距

完整代码可以查看:codepen.io/xboxyan/pen...

五、总结一下

以上就是本文的全部技巧了,你学到了?下面总结一下

  1. 某些情况下HTML由其他框架生成,无法直接改底层源码,这就需要使用CSS动态生成技术了
  2. 使用两个伪元素可以很轻松生成前后两个书名号
  3. 还可以用 CSS quotes 来生成书名号,不过只针对q元素生效
  4. 默认情况下,文本省略会把右侧的书名号也省略
  5. 书名号之所以会连同文本一起被省略,在于和标题文本处于同一文本流中,需要把右侧书名号脱离文本流。
  6. 绝对定位居右定位可以脱离文本流,不过需要预留一点空间,不然会和下面的文本重叠
  7. 块级元素宽度默认撑满,可以设置宽度为fit-content自适应文字宽度
  8. 浮动布局也可以脱离文本流,不过要求浮动元素在HTML结构中的左侧,::after元素在文本右侧,无法使用浮动实现该效果
  9. 除了伪元素,还可以通过::marker来生成内容,而且也位于文本左侧
  10. 使用::marker生成左侧书名号,::brfore生成右侧书名号,相比绝对定位的优势是,无需给定一个"大概"的右内边距

希望能对你的工作带来帮助和不一样的思考,最后,如果觉得还不错,对你有帮助的话,欢迎点赞、收藏、转发 ❤❤❤

欢迎关注我的公众号:前端侦探

相关推荐
小满zs1 分钟前
Zustand 第三章(状态简化)
前端·react.js
普宁彭于晏3 分钟前
元素水平垂直居中的方法
前端·css·笔记·css3
恋猫de小郭14 分钟前
为什么跨平台框架可以适配鸿蒙,它们的技术原理是什么?
android·前端·flutter
云浪18 分钟前
元素变形记:CSS 缩放函数全指南
前端·css
明似水33 分钟前
用 Melos 解决 Flutter Monorepo 的依赖冲突:一个真实案例
前端·javascript·flutter
独立开阀者_FwtCoder42 分钟前
stagewise:让AI与代码编辑器无缝连接
前端·javascript·github
清沫44 分钟前
Cursor Rules 开发实践指南
前端·ai编程·cursor
江城开朗的豌豆1 小时前
JavaScript篇:对象派 vs 过程派:编程江湖的两种武功心法
前端·javascript·面试
不吃糖葫芦31 小时前
App使用webview套壳引入h5(二)—— app内访问h5,顶部被手机顶部菜单遮挡问题,保留顶部安全距离
前端·webview
江城开朗的豌豆1 小时前
JavaScript篇:字母侦探:如何快速统计字符串里谁才是'主角'?
前端·javascript·面试