सीएसएस कस्टम हाइलाइट एपीआई की मदद से, डीओएम स्ट्रक्चर में बदलाव किए बिना, पेज पर मौजूद किसी भी टेक्स्ट रेंज को स्टाइल किया जा सकता है. इससे खोज के नतीजों को हाइलाइट करने, सिंटैक्स को कलर करने, साथ मिलकर बदलाव करने वाले कर्सर या स्पेलिंग और व्याकरण की गड़बड़ी के मार्कर को चालू किया जा सकता है. इसके लिए, टेक्स्ट को अतिरिक्त एलिमेंट में रैप करने या innerHTML में बदलाव करने की ज़रूरत नहीं पड़ती.
मुख्य तौर पर लागू करना
टेक्स्ट की रेंज हाइलाइट करने के लिए, आपको टारगेट टेक्स्ट नोड इकट्ठा करने होंगे. साथ ही, Range और Highlight ऑब्जेक्ट बनाने होंगे और उन्हें HighlightRegistry में रजिस्टर करना होगा. इसके बाद, उन्हें ::highlight() स्यूडो-एलिमेंट की मदद से स्टाइल करना होगा.
1. टेक्स्ट नोड इकट्ठा करना और रेंज बनाना
टारगेट एलिमेंट में मौजूद सभी टेक्स्ट नोड इकट्ठा करने के लिए, TreeWalker का इस्तेमाल करें. इसके बाद, उन वर्ण ऑफ़सेट पर ले जाने वाले Range ऑब्जेक्ट बनाएं जिन्हें आपको हाइलाइट करना है.
const article = document.querySelector("article");
// MANDATORY: Use TreeWalker to collect text nodes — do not manipulate innerHTML.
const treeWalker = document.createTreeWalker(article, NodeFilter.SHOW_TEXT);
const allTextNodes = [];
let currentNode = treeWalker.nextNode();
while (currentNode) {
allTextNodes.push(currentNode);
currentNode = treeWalker.nextNode();
}
// MANDATORY: Set range start/end on text nodes, not element nodes.
const range = new Range();
range.setStart(textNode, matchStartIndex);
range.setEnd(textNode, matchEndIndex);
टेक्स्ट-नोड की सूची को कैश मेमोरी में सेव करें और उसे सिर्फ़ तब फिर से बनाएं, जब डीओएम कॉन्टेंट में असल में बदलाव हो. ऐसा इसलिए, क्योंकि ट्री को फिर से बनाना मुश्किल होता है.
2. रेंज से हाइलाइट बनाना
एक या उससे ज़्यादा Range ऑब्जेक्ट को Highlight में ग्रुप करें. एक ही स्टाइल वाली कई रेंज, एक ही हाइलाइट में शामिल होती हैं.
const searchHighlight = new Highlight(...matchingRanges);
3. रजिस्ट्री में हाइलाइट को रजिस्टर करना
CSS.highlights का इस्तेमाल करके, हर Highlight को पसंद के मुताबिक नाम के साथ रजिस्टर करें. यह Map की तरह HighlightRegistry है.
// MANDATORY: Clear previous highlights before registering new ones
// to avoid stale ranges persisting on the page.
CSS.highlights.clear();
CSS.highlights.set("search-results", searchHighlight);
जब एक से ज़्यादा हाइलाइट ओवरलैप हों, तो स्टैकिंग ऑर्डर को कंट्रोल करने के लिए priority प्रॉपर्टी का इस्तेमाल करें. ज़्यादा प्राथमिकता वाली हाइलाइट सबसे ऊपर दिखती हैं.
const primary = new Highlight(...primaryRanges);
primary.priority = 1;
const secondary = new Highlight(...secondaryRanges);
secondary.priority = 0; // painted first (behind primary)
CSS.highlights.set("primary", primary);
CSS.highlights.set("secondary", secondary);
4. ::highlight() के साथ स्टाइल करें
सीएसएस में ::highlight() सूडो-एलिमेंट का इस्तेमाल करके, रजिस्टर की गई हर हाइलाइट को नाम के हिसाब से स्टाइल करें.
::highlight(search-results) {
background-color: #ffdd00;
color: black;
}
::highlight() में सिर्फ़ कुछ सीएसएस प्रॉपर्टी काम करती हैं: color, background-color, text-decoration और इसके लॉन्गहैंड, text-shadow, -webkit-text-stroke-color, -webkit-text-fill-color, और -webkit-text-stroke-width. background-image, font-size या padding जैसी प्रॉपर्टी को अनदेखा कर दिया जाता है.
सुलभता
AVOIDसिमेंटिक एचटीएमएल की जगह, कस्टम हाइलाइट का इस्तेमाल न करें.
कस्टम हाइलाइट, सिर्फ़ प्रज़ेंटेशन के लिए होती हैं. इन्हें सुलभता ट्री में नहीं दिखाया जाता. अगर हाइलाइट किया गया टेक्स्ट, दस्तावेज़ के हिसाब से काम का है (जैसे, उपयोगकर्ता का चुना गया कोई पैसेज), तो इसके बजाय <mark> का इस्तेमाल करें. कस्टम हाइलाइट को कुछ समय के लिए दिखने वाले विज़ुअल इफ़ेक्ट के लिए रिज़र्व करें. जैसे, खोज के नतीजे या सिंटैक्स को कलर करना.
हाइलाइट किए गए टेक्स्ट का मतलब समझाने के लिए, सिर्फ़ रंग पर निर्भर नहीं रहना चाहिए. अगर हाइलाइट से किसी गड़बड़ी का पता चलता है, तो उसे किसी दूसरे विज़ुअल इंडिकेटर के साथ जोड़ें. जैसे, text-decoration: wavy underline या बगल में मौजूद टेक्स्ट लेबल. पक्का करें कि हाइलाइट किए गए बैकग्राउंड और टेक्स्ट के रंग के बीच का कंट्रास्ट, WCAG 2.1 की ज़रूरी शर्तों के मुताबिक हो. सामान्य टेक्स्ट के लिए, यह कंट्रास्ट कम से कम 4.5:1 होना चाहिए.
फ़ॉलबैक रणनीतियां
CSS Custom Highlight API के साथ काम न करने वाले ब्राउज़र के लिए, आपको एक ऐसा बुनियादी अनुभव देना चाहिए जिसमें टेक्स्ट को विज़ुअल तौर पर हाइलाइट न किए जाने पर भी पढ़ा जा सके.
एपीआई का इस्तेमाल करने से पहले, यह पता लगाया जा सकता है कि डिवाइस पर यह सुविधा काम करती है या नहीं:
if (CSS.highlights) {
// CSS Custom Highlight API is supported.
} else {
// Fallback: wrap matches in <mark> elements.
}
अगर हाइलाइट करना उपयोगकर्ता अनुभव के लिए ज़रूरी है, तो मैच होने वाले टेक्स्ट को <mark> एलिमेंट में रैप करें. इससे डीओएम में बदलाव होता है. इसलिए, इवेंट लिसनर को सुरक्षित रखें और दस्तावेज़ के स्ट्रक्चर को टूटने से बचाएं.
if (!CSS.highlights) {
// Walk text nodes and wrap matches in <mark>, preserving structure.
const walker = document.createTreeWalker(article, NodeFilter.SHOW_TEXT);
const nodes = [];
for (let n = walker.nextNode(); n; n = walker.nextNode()) nodes.push(n);
const term = searchTerm.toLowerCase();
for (const textNode of nodes) {
const text = textNode.textContent;
let pos = text.toLowerCase().indexOf(term);
if (pos === -1) continue;
const frag = document.createDocumentFragment();
let last = 0;
while (pos !== -1) {
frag.append(text.slice(last, pos));
const mark = document.createElement("mark");
// textContent assignment avoids HTML injection.
mark.textContent = text.slice(pos, pos + term.length);
frag.append(mark);
last = pos + term.length;
pos = text.toLowerCase().indexOf(term, last);
}
frag.append(text.slice(last));
textNode.replaceWith(frag);
}
}