CSS Custom Highlight API
CSS 自定義高亮 API 提供了一種機制,可以透過 JavaScript 建立任意文字範圍,並使用 CSS 為其著色。
概念與用法
為網頁上的文字範圍著色非常有用。例如,文字編輯 Web 應用會高亮拼寫或語法錯誤,程式碼編輯器會高亮語法錯誤。
CSS 自定義高亮 API 擴充套件了其他高亮偽元素的概念,例如 ::selection、::spelling-error、::grammar-error 和 ::target-text,它提供了一種建立和樣式化任意 Range 物件的方法,而不侷限於瀏覽器定義的範圍。
使用 CSS 自定義高亮 API,您可以以程式設計方式建立文字範圍並對其進行高亮,而不會影響頁面的 DOM 結構。
使用 CSS 自定義高亮 API 為網頁上的文字範圍著色有四個步驟:
- 建立
Range物件。 - 為這些範圍建立
Highlight物件。 - 使用
HighlightRegistry註冊高亮。 - 使用
::highlight()偽元素為高亮著色。
建立範圍
第一步是透過在 JavaScript 中建立 Range 物件來定義您想要著色的文字範圍。例如:
const parentNode = document.getElementById("foo");
const range1 = new Range();
range1.setStart(parentNode, 10);
range1.setEnd(parentNode, 20);
const range2 = new Range();
range2.setStart(parentNode, 40);
range2.setEnd(parentNode, 60);
建立高亮
第二步是為您的文字範圍例項化 Highlight 物件。
多個範圍可以關聯到同一個高亮。如果您想以相同的方式高亮多個文字片段,則需要建立一個高亮,並用相應的範圍對其進行初始化。
const highlight = new Highlight(range1, range2);
但是您也可以根據需要建立任意數量的高亮。例如,如果您正在構建一個協作式文字編輯器,每個使用者都有不同的文字顏色,那麼您可以為每個使用者建立一個高亮,如下面的程式碼片段所示:
const user1Highlight = new Highlight(user1Range1, user1Range2);
const user2Highlight = new Highlight(user2Range1, user2Range2, user2Range3);
每個高亮都可以有不同的樣式。
註冊高亮
建立高亮後,使用可用的 CSS.highlights HighlightRegistry 來註冊它們。
登錄檔是一個類似 Map 的物件,用於按名稱註冊高亮,如下所示:
CSS.highlights.set("user-1-highlight", user1Highlight);
CSS.highlights.set("user-2-highlight", user2Highlight);
在上面的程式碼片段中,user-1-highlight 和 user-2-highlight 字串是自定義識別符號,可以在 CSS 中用於將樣式應用於已註冊的高亮。
您可以在登錄檔中註冊任意數量的高亮,還可以刪除高亮並清空整個登錄檔。
// Remove a single highlight from the registry.
CSS.highlights.delete("user-1-highlight");
// Clear the registry.
CSS.highlights.clear();
樣式高亮
最後一步是為已註冊的高亮著色。這可以透過使用 ::highlight() 偽元素來完成。例如,為上一步註冊的 user-1-highlight 高亮著色:
::highlight(user-1-highlight) {
background-color: yellow;
color: black;
}
介面
Highlight-
此介面用於表示要在文件上著色的一組範圍。
HighlightRegistry-
可透過
CSS.highlights訪問,這個類似Map的物件用於使用自定義識別符號註冊高亮。
示例
高亮搜尋結果
此示例顯示瞭如何使用 CSS 自定義高亮 API 來高亮搜尋結果。
HTML
下面的 HTML 程式碼片段定義了一個搜尋欄位和一個包含幾段文字的文章:
<label>Search within text <input id="query" type="text" /></label>
<article>
<p>
Maxime debitis hic, delectus perspiciatis laborum molestiae labore,
deleniti, quam consequatur iure veniam alias voluptas nisi quo. Dolorem
eaque alias, quo vel quas repudiandae architecto deserunt quidem, sapiente
laudantium nulla.
</p>
<p>
Maiores odit molestias, necessitatibus doloremque dolor illum reprehenderit
provident nostrum laboriosam iste, tempore perferendis! Ab porro neque esse
voluptas libero necessitatibus fugiat, ex, minus atque deserunt veniam
molestiae tempora? Vitae.
</p>
<p>
Dolorum facilis voluptate eaque eius similique ducimus dignissimos assumenda
quos architecto. Doloremque deleniti non exercitationem rerum quam alias
harum, nisi obcaecati corporis temporibus vero sapiente voluptatum est
quibusdam id ipsa.
</p>
</article>
JavaScript
JavaScript 用於監聽搜尋欄位的 input 事件。當事件觸發時,程式碼會在文章文字中查詢與輸入文字匹配的內容。然後,它會為匹配項建立範圍,並使用 CSS 自定義高亮 API 建立和註冊一個 search-results 高亮物件。
const query = document.getElementById("query");
const article = document.querySelector("article");
// Find all text nodes in the article. We'll search within
// these text nodes.
const treeWalker = document.createTreeWalker(article, NodeFilter.SHOW_TEXT);
const allTextNodes = [];
let currentNode = treeWalker.nextNode();
while (currentNode) {
allTextNodes.push(currentNode);
currentNode = treeWalker.nextNode();
}
// Listen to the input event to run the search.
query.addEventListener("input", () => {
// If the CSS Custom Highlight API is not supported,
// display a message and bail-out.
if (!CSS.highlights) {
article.textContent = "CSS Custom Highlight API not supported.";
return;
}
// Clear the HighlightRegistry to remove the
// previous search results.
CSS.highlights.clear();
// Clean-up the search query and bail-out if
// if it's empty.
const str = query.value.trim().toLowerCase();
if (!str) {
return;
}
// Iterate over all text nodes and find matches.
const ranges = allTextNodes
.map((el) => ({ el, text: el.textContent.toLowerCase() }))
.map(({ text, el }) => {
const indices = [];
let startPos = 0;
while (startPos < text.length) {
const index = text.indexOf(str, startPos);
if (index === -1) break;
indices.push(index);
startPos = index + str.length;
}
// Create a range object for each instance of
// str we found in the text node.
return indices.map((index) => {
const range = new Range();
range.setStart(el, index);
range.setEnd(el, index + str.length);
return range;
});
});
// Create a Highlight object for the ranges.
const searchResultsHighlight = new Highlight(...ranges.flat());
// Register the Highlight object in the registry.
CSS.highlights.set("search-results", searchResultsHighlight);
});
CSS
最後,在 CSS 中使用 ::highlight() 偽元素來為高亮著色。
::highlight(search-results) {
background-color: #ff0066;
color: white;
}
結果
結果如下所示。在搜尋欄位中輸入文字,即可高亮文章中的匹配項。
規範
| 規範 |
|---|
| CSS 自定義高亮 API 模組級別 1 |
瀏覽器相容性
api.Highlight
載入中…
api.HighlightRegistry
載入中…
css.selectors.highlight
載入中…
另見
- CSS 自定義高亮 API:Web 上高亮文字範圍的未來
- HTML
contentEditable屬性 - CSS
偽元素 - CSS 自定義高亮 API 模組