网页搜索高亮样式太丑怎么办?,用CSS新特性给Ctrl+F结果换个皮肤

3,061字
13–19 分钟
in

是不是每次在网页上用Ctrl+F查找关键词,看着那一大片默认的黄色高亮,总觉得跟整个页面的设计格格不入?特别是深色背景的网站,那种亮黄色简直晃眼。现在Chrome 144版本悄悄上线了一个叫::search-text的新玩意儿,专门用来给浏览器自带的搜索匹配结果换衣服,配合其他几个早就存在的高亮伪类,终于能让页面里那些“不速之客”跟整体风格和谐相处了。

目录

搜索高亮伪类家族

主力干将::search-text

::search-text这个伪元素是专门用来对付Ctrl+F查找出来的匹配文本。默认情况下,当前选中的那个匹配结果会用橙色打底,其他匹配项则是黄色。通过这个选择器,能轻松把这两种颜色都换成想要的任何样式。比如给所有匹配项换上淡蓝色背景,当前激活的用深蓝色。

容易混淆的::target-text

::target-text针对的是URL片段高亮,也就是网址后面带着#:~:text=这种参数时自动跳转并高亮的那段文字。搜索引擎给搜索结果页跳转时经常用这招,所以这俩伪类常常被搞混。区别在于触发方式完全不同:一个是手动按快捷键搜出来的,一个是点链接自动定位过去的。

其他高亮成员

伪类选择对象使用场景
::selection鼠标框选文本用户拖拽选中的内容
::highlight()JS自定义高亮配合Custom Highlight API
::spelling-error拼写错误主要针对可编辑区域
::grammar-error语法错误主要针对可编辑区域

还有个<mark>标签,是HTML层面的高亮元素,虽然不算伪类,但视觉效果上经常跟这些家伙混在一起。

动手搞定高亮样式适配

准备一个测试页面

先搭个基础架子,确保所有高亮元素都能被样式影响到。这里用一个深色背景作为例子,看看怎么让搜索高亮既醒目又不违和。

<body style="background: #38003c; color: white; padding: 20px;">
  <p>这段文字里有需要搜索的关键词,比如“示例”和“代码”。按下Ctrl+F搜一下试试,默认的高亮是黄色的。</p>
  <p>第二个段落也放一个“示例”,看看多个匹配项怎么显示。</p>
</body>

应用基础样式

直接给这几个高亮家伙统一设置样式。这里用了一个取巧的办法:把高亮的文字颜色设成跟背景色一样,背景色则取背景色的反色。这样不管页面背景怎么变,高亮都能自动反色,保证看得清。

body {
  --bg-color: #38003c;
  background: var(--bg-color);
}

mark,
::selection,
::target-text,
::search-text {
  color: var(--bg-color);
  background: rgb(from var(--bg-color) calc(255 - r) calc(255 - g) calc(255 - b));
}

如果浏览器不支持这个相对颜色语法,可以用预先算好的颜色值代替。但用相对颜色语法的好处是,只要改了--bg-color变量,所有高亮颜色都会跟着变,不用手动调。

区分不同高亮类型

把每种高亮做成不同颜色,这样要是页面同时出现多个高亮区域(比如用鼠标框选了一段文字,这段文字里又包含搜索匹配项),能一眼看出谁是谁。这里玩了个小花招:每种高亮只反转部分颜色通道,再带上透明度,重叠的地方就能看出层次。

mark {
  /* 全通道反转,加70%透明度 */
  background: rgb(from var(--bg-color) calc(255 - r) calc(255 - g) calc(255 - b) / 70%);
}

::selection {
  /* 只反转绿色和蓝色通道,红色保留原值 */
  background: rgb(from var(--bg-color) r calc(255 - g) calc(255 - b) / 70%);
}

::target-text {
  /* 只反转红色和蓝色通道,绿色保留原值 */
  background: rgb(from var(--bg-color) calc(255 - r) g calc(255 - b) / 70%);
}

::search-text {
  /* 只反转红色和绿色通道,蓝色保留原值 */
  background: rgb(from var(--bg-color) calc(255 - r) calc(255 - g) b / 70%);

  &:current {
    /* 当前匹配项去掉透明度,更加醒目 */
    background: rgb(from var(--bg-color) calc(255 - r) calc(255 - g) b / 100%);
  }
}

用透明度叠加的好处是,当::selection::search-text重叠时,两种半透明颜色混在一起会产生第三种颜色,边界清晰可见。::search-text:current用100%不透明,确保正在定位的那一项最突出。

特殊成员单独处理

::spelling-error::grammar-error这俩家伙在可编辑区域(比如<textarea>contenteditable元素)里,浏览器已经给了一套默认的红色波浪线(拼写错误)和绿色波浪线(语法错误)。强制改掉这些波浪线可能会让用户困惑,毕竟大家已经习惯了这套视觉语言。所以一般不动它们,除非有特殊需求,比如跟整体品牌色保持一致。

<textarea rows="4" style="background: #1e1e2f; color: white;">
这段文字里故意写个错误拼写 "helllo",看看浏览器怎么显示。
</textarea>

浏览器会自动给可疑单词标红波浪线,不需要额外写样式干预。

完整解决方案代码

把上面的片段拼起来,就是一个能自动适应背景色的高亮方案。改--bg-color变量的值,所有高亮颜色都会跟着变,省去了挨个调色的麻烦。透明度的设置让不同高亮重叠时依然能分辨清楚,当前搜索项用100%不透明确保一眼定位。

:root {
  --bg-color: #38003c;
}

body {
  background: var(--bg-color);
  color: white;
  padding: 20px;
}

mark,
::selection,
::target-text,
::search-text {
  color: var(--bg-color);
}

mark {
  background: rgb(from var(--bg-color) calc(255 - r) calc(255 - g) calc(255 - b) / 70%);
}

::selection {
  background: rgb(from var(--bg-color) r calc(255 - g) calc(255 - b) / 70%);
}

::target-text {
  background: rgb(from var(--bg-color) calc(255 - r) g calc(255 - b) / 70%);
}

::search-text {
  background: rgb(from var(--bg-color) calc(255 - r) calc(255 - g) b / 70%);
}

::search-text:current {
  background: rgb(from var(--bg-color) calc(255 - r) calc(255 - g) b / 100%);
}

如果背景色是#808080这种纯灰色,反色计算会得到#808080,文字就跟背景糊在一起了。遇到这种情况,可以手动给特殊背景写个备用样式,或者直接用对比度更高的颜色。实际项目里可以先用工具跑一下对比度检查,确保万无一失。