如何突出显示 HTML 文本而不用标签包裹它?
是否可以在不使用 或任何其他标签包装的情况下突出显示 HTML 文档中的文本?
例如,在 HTML 代码 The Quick Fox
中,我想突出显示 quick
,但不在其周围添加 DOM 元素。将 DOM 元素添加到父元素就可以了。
谢谢!
Is it possible to highlight text in an HTML document using without wrapping it with <span>
or any other tag for that matter?
For example, in the HTML code <p>The quick fox</p>
I would like to highlight quick
but without adding a DOM element around it. Adding a DOM element to a parent element is fine.
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
不,不可能以可移植的方式跨所有浏览器。
无论您是静态还是动态执行(例如,使用 Javascript 作为后处理步骤),您都无法在不本质上更改 DOM 的情况下告诉浏览器以不同方式呈现一段文本。
编辑:在 2019 年左右开始的 Chrome 中,您可以使用滚动到文本片段,但这不是 HTML或浏览器标准功能。
No, it is not possible in a portable manner across all browsers.
You can't tell the browser to render a piece of text differently without inherently changing the DOM, regardless of whether you do it statically or dynamically (with Javascript, for example, as a post processing step).
Edit: In Chrome starting around 2019, you can use Scroll To Text Fragment, but this is not an HTML or browser standard feature.
CSS 自定义突出显示 API
浏览器供应商正在努力明确支持突出显示模式 - 提供令人难以置信的多功能新“自定义突出显示”API。
自版本 105 (2022-09-02) 起,此功能已在 Chrome 衍生产品中提供,目前 Firefox Nightly 也支持此功能。
https://developer.mozilla.org/en-US/docs/ Web/API/CSS_Custom_Highlight_API
请注意我的回答,我以较长的形式对此进行了描述:
https ://stackoverflow.com/a/78051161/16376459
现在有多种方法可以在不修改 DOM 元素结构的情况下实现这种效果。
然而,它们都有自己的警告。
这个答案来自我对开源浏览器扩展标记我的搜索(存储库),它突出显示您在网页上搜索的文本。所接受的方法的自然破坏性导致我考虑了许多替代方案。如果未选中高级选项“使用经典突出显示”,则扩展程序将仅使用以下方法之一,由于我将要描述的缺点,这不是默认选项。
下面的所有方法仅涉及添加额外的绘画DOM,因此无法设置文本样式或以其他方式更改现有内容。然而,它们完全是非破坏性操作,可以提高效率,使其成为具有竞争力的替代方案。
重要提示:此答案的假设是您可以直接将样式应用于元素,或者使用样式表和生成的属性来远程应用它。这种类型的 DOM 操作仍然是必需的。
方法
整体式
用单个元素覆盖整个内容区域。
将所有突出显示绘制到元素上。
优点:
缺点:
复合
要突出显示所有文本,请查看包含部分文本范围的最低级别的不同元素。
在每个元素上突出显示。
优点:
缺点:
background-image
)。混合
display: block
处理其display: inline
子元素的突出显示)。实现
元素
优点:
缺点:
SVG
background-image
上使用url()
。优点:
缺点:
url()
,期望它提取远程内容。画布
元素。
background-image
上使用url()
。优点:
缺点:
url()
:页面 CSP 将(很少)阻止url()
的使用,期望它提取远程内容内容。胡迪尼
background-image:paint({worklet name})
以显示突出显示。元素()
background: element({突出显示元素的 ID})
以显示突出显示。优点:
缺点:
background
而不仅仅是background-image
,导致更多地覆盖元素背景。这似乎是一个疏忽。动态更新
我不会详细介绍这一点,因为它非常适合您的需求。但是,为了在应用于整个页面时获得完全最新的突出显示,我需要:
A
MutationObserver
观察subtree
、childList
和文档正文的characterData
,以检测可能影响匹配的所有更改。我的情况很极端,所以我必须观察整个文件;我使用各种方法进行优化,包括过滤掉不需要关注的事件。一个
ResizeObserver
观察当前视图中突出显示的元素,以便在布局发生变化时重新计算突出显示。一个
IntersectionObserver
观察所有突出显示的元素何时出现在视口中,以便仅在需要时绘制突出显示和ResizeObserver
。 这只是一项优化措施。信息
这里是 PR,我使用上述多种可以替换的方法实现了这一点。我使用了一种高度结构化的方法 - 涉及跨 DOM 的缓存和其他优化,例如将其分解为多个阶段 - 即使在所有平均页面都以各种颜色突出显示的情况下也能使其高效。 PR 中提供了概述。
这是最极端的可能情况之一,其他人应该完全有可能在不显着性能损失的情况下取得良好的结果。
我很乐意回答有关我的实施或开始使用这些技术的任何问题。
文章
注意
*由于在客户端矩形与实际布局+位置关联时浏览器行为复杂,因此很难确保基于覆盖的突出显示算法在所有情况下都能正确定位突出显示框。我仍然无法正确解释边界的影响(这会扰乱计算)或流内容的奇怪情况,但仅使用
Range.getClientRects() 的结果在技术上是可行的
和Element.getClientRects()
。CSS Custom Highlight API
Browser vendors are working towards explicit support for the highlighting pattern - with an incredibly versatile new "Custom Highlight" API.
This has been available in Chrome derivatives since version 105 (2022-09-02), and is currently supported in Firefox Nightly.
https://developer.mozilla.org/en-US/docs/Web/API/CSS_Custom_Highlight_API
Note my answer here, where I describe this in longer form:
https://stackoverflow.com/a/78051161/16376459
There are now multiple ways of achieving this effect without modifying the element structure of the DOM.
They all, however, come with their own caveats.
This answer is derived from research I performed for my open source browser extension Mark My Search (repository), which highlights text you search for on webpages. The natural destructiveness of the accepted approach led to my consideration of many alternatives. The extension will only use one the below approaches if the advanced option "Use CLASSIC highlighting" is unchecked, which is not default due to the disadvantages I am about to describe.
All of my approaches below only involve adding additional painting to the DOM, so there is no option to style text or otherwise change existing content. However, they are entirely non-destructive operations which can result in efficiency gains, making them a competitive alternative.
Important: The assumption through this answer is that you either apply styling directly to elements, or use a stylesheet and generated attributes to apply it remotely. This type of DOM manipulation is still required.
Approaches
Monolithic
Overlay the entire content area with a single element.
Draw all highlighting onto the element.
Pros:
Cons:
Composite
For all text to be highlighted, look at the lowest-level distinct elements which contain parts of the text ranges.
Draw highlighting onto each of these elements.
Pros:
Cons:
background-image
) is still potentially lost per highlighted element.Hybrid
display: block
to handle highlights for itsdisplay: inline
children).Implementations
Elements
Pros:
Cons:
SVG
url()
on thebackground-image
of the ancestor element.Pros:
Cons:
url()
, expecting it to extract remote content.Canvas
<canvas>
element.url()
on thebackground-image
of the ancestor element.Pros:
Cons:
url()
is used: Page CSPs will (rarely) block the use ofurl()
, expecting it to extract remote content.Houdini
background-image: paint({worklet name})
as appropriate on elements to display highlighting.element()
background: element({ID of highlighting element})
as appropriate on elements to display highlighting.Pros:
Cons:
background
instead of justbackground-image
, resulting in more overriding of element backgrounds. This seems to be an oversight.Dynamically Updating
I won't go into much detail about this, as it is very specific to your needs. However, to obtain fully up-to-date highlighting when applied to an entire page, I needed:
A
MutationObserver
observingsubtree
,childList
, andcharacterData
for the document body, in order to detect all changes that may affect matching. My case is very extreme, which is why I must observe the entire document; I optimised using various methods, including filtering out events that did not require attention.A
ResizeObserver
observing highlighted elements currently in view, in order to recalculate highlighting when layout shifts occur.An
IntersectionObserver
observing all highlighted elements for when they appear in the viewport, in order to draw highlighting and theResizeObserver
only when needed. This is an optimisation measure only.Information
Here is the PR in which I achieved this, using multiple of the above methods which could be swapped out. I used a highly structured approach - involving caching across the DOM and other optimisations, such as decomposing it into multiple stages - to make it efficient even for cases where all of an average page has been highlighted in various colours. An overview is presented in the PR.
This being one of the most extreme possible cases, it should be entirely possible for others to achieve good results without significant performance loss.
I am happy to answer any questions regarding my implementation, or getting started with these technologies.
Articles
Notes
*Due to convoluted browser behaviour when it comes to the association of client rects with actual layout+position, it is very difficult to make sure an overlay-based highlighting algorithm will position highlight-boxes correctly in all cases. I have still not managed to correctly account for the effect of border (which disrupts calculations) or strange cases of flow content, but it is technically possible using only the results of
Range.getClientRects()
andElement.getClientRects()
.如果您使用带有透明重复背景图像或透明背景颜色(使用 rgba 或 hsla)的绝对定位元素并将其放置在选定区域上,则可以实现这一点。
另一种方法是有一个绝对定位的画布元素,没有背景,占据整个浏览器视口,并在选择上绘制一个透明矩形。
It is possible if you use an absolutely positioned element with a transparent repeating background image or a transparent background color (using rgba or hsla) and position it over the selected area.
Another way to do it would be to have an absolutely positioned canvas element without a background that takes up the whole browser viewport and draw a transparent rectangle over the selection.
这是不可能的。
如果您只想在原始源代码中没有标签,则可以稍后使用 Javascript 魔法添加标签。你可以做类似的事情
,编写一个 JQuery/Prototype/plain JS 函数来动态突出显示它,但是为什么呢?如果你详细说明一下,有人可能会想出一个主意。
It's not possible.
If you just want no tags in the original source code, it might be possible by adding tags later using Javascript magic. You could do something like
and write a JQuery/Prototype/plain JS function to highlight it on the fly, but what for and why? If you elaborate a bit, someone may come up with an idea.
比我想象的唯一方法是使用
元素,并完全手动渲染所有内容。
The only way to do this than I can imagine would be to use the
<canvas>
element, and render absolutely everything by hand.