提要
想要在前端展示一段文本,并对文本中的部分文字实现高亮效果,常规方案是借用像 CKEditor、wangEditor 等 Web 富文本编辑器来实现高亮特性(例如:加粗、下划线、文字颜色、文字底色)。但富文本编辑器是通过对原始文本附加额外HTML结构和CSS属性实现的高亮,对原始文本有“侵入”。现在有了新的解决方案
。
TL;DR
CSS Custom Highlight API 是一种试验特性,它可以让你以“无侵入(无需额外插入HTML元素)”的方式,实现指定文本区域的高亮效果。
假设有一段文本(例如:一篇英文文章)需要在前端展示(注意:这里不考虑文本编辑,仅仅是文本展示),并且文本中的部分文字需要特别标记(例如:采用颜色、下划线、加粗、背景色进行标记),你会选择什么方案进行实现?
常规的做法是借用 Web 富文本编辑器(例如:CKEditor、wangEditor、TinyMCE 等)来实现。因为这些富文本编辑器的基础的功能就包含:文本加粗、倾斜、下划线、文字颜色、文字底色控制,与上面的问题场景很契合。
采用Web富文本编辑器作为解决方案,有一个小小问题:耦合,原始文本与HTML元素、CSS样式的耦合。
这些加粗、文字颜色、下划线、文字底色等特性是通过在原始文本上附加HTML元素和CSS样式来实现的。
这个耦合问题本身不算问题,如果你有一些对标记后文本的处理需求,这个耦合问题就可能会给你造成困扰:
某天在网页上查找文本(Ctrl+F)时,注意到,那些在网页中匹配到的文本,浏览器会对它们进行高亮显示(如下图)。可神奇的是,浏览器并不是通过给网页中匹配到的文本附加HTML结构和CSS属性来实现高亮,而是通过一种“无侵入”的方式实现。这就是我想要的实现方式。
经过一番查找,发现一个浏览器的实验特性(CSS Custom Highlight API),恰好能干这个事情(下图是MDN官网的DEMO截图)。
CSS 自定义高亮 API 提供了一种方法,它可以让你给文档(document)中的任意文本区域(text range)设置高亮样式(highlight)。
坏消息是,“CSS 自定义高亮 API”目前只是一个试验特性,并不是所有的浏览器都支持。好消息是,Chrome支持的很完美(PS:这年头谁还用IE?😕 )。
使用“CSS 自定义高亮 API”,分5步:
效果:
代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title></title>
<style type="text/css">
pre {
white-space: break-spaces;
font-size: 16px;
}
</style>
</head>
<body>
<pre id="textWrapper">
“都是那该死的萧家害的,迟早要弄跨你们。”咬牙切齿的骂了一声,加列怒略微向后偏了偏头,目光透过车窗望向后面整齐堆满的各种低级药材,面无表情的脸庞上露出一丝无奈,虽说纳戒能够让运输变得极其方便,不过低级纳戒其中不过两三平方米的空间,想要用低级纳戒来将这些药材装下,恐怕至少需要五枚才有可能,然而纳戒造价昂贵并且稀有,即使是整个加列家族,也不过区区两枚,所以,他们只得选择笨重的车辆来运药。
疲倦的眨了眨眼,刚欲小寐一会的加列怒,却是发现前方的车辆忽然的停了下来,而且隐隐有着喝骂声传来。
眉头一皱,加列怒刚欲叫人询问情况,一名加列家族的护卫便是从前方急跑过来,急声报告道:“长老,前方有位黑袍人无故的阻了去路。”
</pre>
<script>
const p = document.getElementById("textWrapper").firstChild;
// 创建文字区域
const range1 = new Range();
range1.setStart(p, 0);
range1.setEnd(p, 10);
const range2 = new Range();
range2.setStart(p, 20);
range2.setEnd(p, 30);
const range3 = new Range();
range3.setStart(p, 200);
range3.setEnd(p, 220);
const range4 = new Range();
range4.setStart(p, 100);
range4.setEnd(p, 160);
// 3种高亮方式,以及每种高亮方式对应哪些文字区域
const highlight1 = new Highlight();
highlight1.add(range1);
const highlight2 = new Highlight();
highlight2.add(range2);
const highlight3 = new Highlight();
highlight3.add(range3);
highlight3.add(range4);
// 将高亮方式注册给浏览器
CSS.highlights.set(`type-a`, highlight1);
CSS.highlights.set(`type-b`, highlight2);
CSS.highlights.set(`type-c`, highlight3);
</script>
<style>
/* 描述每种高亮方式的CSS特性 */
::highlight(type-a) {
color: #ff0000;
text-decoration: dotted underline #ff0000 2px;
}
::highlight(type-b) {
color: #2300a1;
text-decoration: wavy underline #2300a1 2px;
-webkit-text-stroke-width: 1px;
}
::highlight(type-c) {
color: #000;
text-decoration: double underline #00af1d 2px;
-webkit-text-stroke-width: 1px;
}
</style>
</body>
</html>
需要强调的是,在本文中,我能用“CSS Custom Highlight API”替换掉富文本编辑器,是因为我只是借用富文本编辑器来为我实现文本高亮。这并不意味着“CSS Custom Highlight API”是替换掉富文本编辑器的方案,因为 “CSS Custom Highlight API”只是一种实现文字高亮的方案😄 。
参考:
https://css-tricks.com/css-custom-highlight-api-early-look/ https://developer.mozilla.org/zh-CN/docs/Web/API/CSS_Custom_Highlight_API https://developer.mozilla.org/en-US/docs/Web/CSS/::highlight