96SEO 2026-04-26 07:22 1

想在自己的博客、文档系统或在线笔记本里让用户随手选中文字时瞬间出现标记、加粗、颜色等丰富交互?别急,这篇文章会把「划词高亮」的每一步拆得细碎到Ke以直接复制粘贴运行。写完后你的页面将拥有一个可拖拽、自动定位的工具栏,还Neng把用户的标记永久保存下来。
为什么要给文字加上划词高亮?在阅读长篇技术文档或学习笔记时大家总会不自觉地用鼠标挑出重点,然后想办法让它们geng醒目。传统的浏览器右键「添加书签」功Neng太死板,而自建一套「划词→高亮」流程,不仅提升阅读体验,还Neng让平台收集用户兴趣点,帮助推荐geng精准的内容。
情绪小插曲:我第一次在公司内部 Wiki 实现这个功Neng时原本只想凑个 Demo,没想到同事们抢着在页面上画「星星」标记,气氛一下子活跃了起来——这就是技术带来的小确幸。
核心概念:Selection API 与 Range 对象 Selection API Neng干什么?浏览器提供的 window.getSelection Neng返回当前用户选中的文本节点集合。它有三个常用属性:
anchorNode / focusNode —— 选区起点与终点所在的 DOM 节点。
rangeCount —— 当前选区包含多少段连续范围。
toString —— 把选中的文字转成普通字符串。
selection.getRangeAt 会返回一个 Range 实例,它记录了起始节点、结束节点以及它们在文档流中的坐标信息。借助 range.getBoundingClientRect Ke以得到一个矩形框,用来把工具栏贴到文字正上方。
在这里随意输入或粘贴文本,然后尝试选中一段文字。
⚡ 小技巧:suppressContentEditableWarning={true} 是 React 环境下避免警告的写法,Ru果你是纯 JS,这行Ke以省掉。
function createToolbar{
const bar = document.createElement;
bar.className = 'float-bar';
// 按钮集合
const btns = ;
btns.forEach(item=>{
const b=document.createElement;
b.innerHTML=item.label;
b.title=item.cmd;
b.onclick==>execCmd;
bar.appendChild;
});
document.body.appendChild;
return bar;
}
function execCmd{
if{
const col=prompt;
if document.execCommand;
}else{
document.execCommand;
}
}
const toolbar=createToolbar;
toolbar.style.display='none';
这里我们用了老旧但兼容性极好的 document.execCommand. Ru果你追求现代化,也Ke以改为 .
let ignoreToolbar=false; // 防止点击按钮时误触隐藏
document.addEventListener=>{
if return;
const sel=window.getSelection;
const txt=sel.toString.trim;
if{
const range=sel.getRangeAt;
const rect=range.getBoundingClientRect;
// 确认光标仍在编辑区内
const editor=document.querySelector;
if){
toolbar.style.top = `${rect.top-40}px`;
toolbar.style.left= `${rect.left+rect.width/2}px`;
toolbar.style.display='flex';
// 为后续操作保存当前 range
toolbar.dataset.rangeStart = range.startOffset;
toolbar.dataset.rangeEnd = range.endOffset;
}else{
toolbar.style.display='none';
}
}else{
toolbar.style.display='none';
}
});
// 鼠标按下判定是否在工具栏内部
toolbar.addEventListener=>{ignoreToolbar=true;});
document.addEventListener('mousedown',e=>{
if){
ignoreToolbar=false;
toolbar.style.display='none';
}
});
🔍 小坑:Ru果你在移动端测试,需要把 'touchend'/'touchstart' 事件也挂上,否则工具栏可Neng一直不弹出来。
单纯的 CSS 背景只Neng保留到页面刷新前,一旦刷新所有标记就消失。下面演示一种轻量级方案,把每一次「划词 + 高亮」的信息序列化后写进 localStorage,下次打开页面再把它们重新渲染。
// 保存高亮信息
function saveHighlight{
const sel=window.getSelection;
if return;
const range=sel.getRangeAt;
const wrapper=document.createElement;
wrapper.style.background='#fffd54';
// 把选中内容包进 span
try{
range.surroundContents;
}catch{console.warn;return;}
// 收集必要属性:起始路径、结束路径、颜色等
const info={
startPath:getNodePath,
endPath:getNodePath,
color:'#fffd54'
};
let store=JSON.parse||'');
store.push;
localStorage.setItem);
}
// 将 DOM 节点转换成唯一路径
function getNodePath{
let path=;
while{
let idx=Array.from.indexOf;
path.unshift;
node=node.parentNode;
}
return path.join;
}
// 页面加载时恢复所有高亮
function restoreHighlights{
let data=JSON.parse||'');
data.forEach(item=>{
let start=findNodeByPath;
let end=findNodeByPath;
if{
let r=document.createRange;
r.setStartBefore;
r.setEndAfter;
let sp=document.createElement;
sp.style.background=item.color||'#fffd54';
r.surroundContents;
}
});
}
// 根据路径找回对应节点
function findNodeByPath{
let parts=path.split.map;
let node=document.body;
for{
node=node.childNodes;
if return null;
}
return node;
}
document.addEventListener;
// 为快捷键绑定保存动作,例如 Ctrl+Shift+H
document.addEventListener('keydown',e=>{
if{
saveHighlight;
e.preventDefault;
}
});
💡 小提示:Ru果你的项目Yi经使用了 Redux 或 Vuex,Ke以把这块逻辑搬进去,让服务器同步,实现跨设备同步收藏。
⑤ 防止高亮重叠与冲突处理当用户对Yi经被包裹的文字 操作时会出现嵌套`导致样式混乱的问题。解决思路有两种:
合并相邻相同颜色块:遍历所有Yi存在的 ``,检查它们是否紧邻且背景相同,若是则合并为一个geng大的块。
先清除再添加:`range.surroundContents` 前先调用 `removeAllRanges` 并删除Yi有 `` 再重新包裹。
实际项目里我倾向于第一种,因为它保留了用户之前手动设置的其它样式。下面是一段简易合并代码:
function mergeSpans{
const editor=document.querySelector;
editor.querySelectorAll.forEach(span=>{
let next=span.nextElementSibling;
while{
span.append;
next.remove;
next=span.nextElementSibling;
}
});
}
setInterval; // 每三秒检查一次
性Neng与兼容性注意事项
#1 渲染频率控制:SelectionChange 在每次光标移动dou会触发。Ru果页面内容hen长,可使用 来降低计算次数。
#2 跨浏览器差异:`execCommand` 在 Safari 中对部分命令支持不佳;若需要完全一致,可考虑使用 `contenteditable` + 自定义 `` 标签来实现。
#3 大量标记时的 DOM 重排:#editor 内部若出现几百个 ``,建议改用 Canvas 绘制方式,这样不会造成过多回流。
#4 移动端手势冲突:`touchmove` 与 `selectionchange` 会产生竞争,Zui好在触摸结束后再读取选区信息。
常见问题速答 Q1:为何 `range.surroundContents` 报错 “HierarchyRequestError”?A:该方法只Neng包裹"纯文本"*或者*没有被其他元素阻隔的节点。Ru果选区跨越了图片、表格等非文本元素,需要先拆分范围或使用 `` 包裹单独文本片段。
Q2:如何让Yi保存的高亮随页面主题切换自动变色?A:把颜色值存为 CSS 自定义属性(例如 `--hl-color`) ,在主题切换时只改变量值即可,无需遍历全部 ``。
Q3:我想让用户自行选择背景颜色,有没有geng友好的 UI?A:直接把调色板嵌入工具栏,用 `` 即可。配合 `document.execCommand` 或自行创建 `` 实现即时预览。
– 把技术变成温度"代码不是冰冷的数据,它Ke以让阅读变得柔软"
从Zui初「我只想给文字加个黄底」到现在拥有完整持久化、高度可定制、跨设备同步的划词系统,你会发现每一次调试dou像是给页面注入了一丝活力。当你kan到同事惊讶地说「哇,这里居然还Neng直接改颜色!」时那份满足感足以抵消所有凌晨加班的疲惫。
If you feel stuck or have a quirky idea—drop a comment below! 我们一起玩转文字,让每一次阅读dou充满仪式感吧 🎉.
© 2026 文技社区 | 本文基于个人实践撰写,仅供学习参考。作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。
| 服务项目 | 基础套餐 | 标准套餐 | 高级定制 |
|---|---|---|---|
| 关键词优化数量 | 10-20个核心词 | 30-50个核心词+长尾词 | 80-150个全方位覆盖 |
| 内容优化 | 基础页面优化 | 全站内容优化+每月5篇原创 | 个性化内容策略+每月15篇原创 |
| 技术SEO | 基本技术检查 | 全面技术优化+移动适配 | 深度技术重构+性能优化 |
| 外链建设 | 每月5-10条 | 每月20-30条高质量外链 | 每月50+条多渠道外链 |
| 数据报告 | 月度基础报告 | 双周详细报告+分析 | 每周深度报告+策略调整 |
| 效果保障 | 3-6个月见效 | 2-4个月见效 | 1-3个月快速见效 |
我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:
全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。
基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。
解决网站技术问题,优化网站结构,提升页面速度和移动端体验。
创作高质量原创内容,优化现有页面,建立内容更新机制。
获取高质量外部链接,建立品牌在线影响力,提升网站权威度。
持续监控排名、流量和转化数据,根据效果调整优化策略。
基于我们服务的客户数据统计,平均优化效果如下:
我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。
Demand feedback