You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用原生JS给元素部分文本包裹/移除span标签?

原生JS实现指定文本包裹span及反向移除操作

现有元素:

<p id="foo">Hello world!</p>

期望最终状态:

<p id="foo"><span>Hello</span> world!</p>

问题

如何通过纯原生JS实现上述文本包裹span的效果,以及反向移除该span标签的操作?另外想知道surroundContents和createRange是否适用于这个场景?


一、实现文本包裹span的方案

方案1:用createRange + surroundContents(推荐)

这俩完全适配你的场景,代码如下:

const el = document.getElementById('foo');
const textNode = el.firstChild; // 获取p标签内的文本节点
const range = document.createRange();
// 精准选中"Hello"这段文本(从文本节点的第0位到第5位)
range.setStart(textNode, 0);
range.setEnd(textNode, 5);

const newSpan = document.createElement('span');
range.surroundContents(newSpan);

原理:createRange用来定位你要包裹的文本范围,surroundContents直接把选中的内容塞进你创建的span里,一步到位。

方案2:拆分文本节点实现

如果不想用Range API,也可以直接拆分文本节点:

const el = document.getElementById('foo');
const textNode = el.firstChild;
// 从第5个字符的位置拆分文本节点,得到后半段" world!"的节点
const remainingText = textNode.splitText(5);
// 创建span并把前半段文本移进去
const newSpan = document.createElement('span');
el.insertBefore(newSpan, remainingText);
newSpan.appendChild(textNode);

二、反向移除span标签

要移除span但保留里面的文本,直接把span的内容替换掉span本身就行:

const span = document.querySelector('#foo span');
if (span) {
  // 把span的子节点(这里是文本"Hello")替换掉span
  span.replaceWith(...span.childNodes);
}

或者用更兼容旧浏览器的写法:

const el = document.getElementById('foo');
const span = el.querySelector('span');
if (span) {
  while (span.firstChild) {
    el.insertBefore(span.firstChild, span);
  }
  el.removeChild(span);
}

关于surroundContents和createRange的适用性

  • createRange是实现这个需求的核心:它能精准定位文档中任意一段连续的内容(包括文本节点的一部分),完全适配局部文本包裹的场景。
  • surroundContents是绝佳的配套工具:它专门用来把Range选中的内容包裹到指定元素中,只要选中的内容是连续且没有跨不完整的元素节点(这里只是文本节点的一部分,完全合法),就能直接生效,非常适合你的需求。

内容的提问来源于stack exchange,提问作者Matt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 02:58:25