日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢(xún)
選擇下列產(chǎn)品馬上在線(xiàn)溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
原生 CSS Custom Highlight 終于來(lái)了

介紹一個(gè)比較前沿但是非常有用的新特性:一個(gè)瀏覽器原生支持的 CSS? 文本高亮高亮功能,官方名稱(chēng)叫做 CSS Custom Highlight API[1],有了它,可以在不改變 dom 結(jié)構(gòu)的情況下自定義任意文本的樣式,例如:

創(chuàng)新互聯(lián)一直在為企業(yè)提供服務(wù),多年的磨煉,使我們?cè)趧?chuàng)意設(shè)計(jì),成都全網(wǎng)營(yíng)銷(xiāo)推廣到技術(shù)研發(fā)擁有了開(kāi)發(fā)經(jīng)驗(yàn)。我們擅長(zhǎng)傾聽(tīng)企業(yè)需求,挖掘用戶(hù)對(duì)產(chǎn)品需求服務(wù)價(jià)值,為企業(yè)制作有用的創(chuàng)意設(shè)計(jì)體驗(yàn)。核心團(tuán)隊(duì)擁有超過(guò)十多年以上行業(yè)經(jīng)驗(yàn),涵蓋創(chuàng)意,策化,開(kāi)發(fā)等專(zhuān)業(yè)領(lǐng)域,公司涉及領(lǐng)域有基礎(chǔ)互聯(lián)網(wǎng)服務(wù)樂(lè)山服務(wù)器托管、app開(kāi)發(fā)定制、手機(jī)移動(dòng)建站、網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)絡(luò)整合營(yíng)銷(xiāo)。

再例如搜索詞高亮。

還可以輕易實(shí)現(xiàn)代碼高亮。

多么令人興奮的功能啊,現(xiàn)在在 Chrome 105 中已經(jīng)正式支持了(無(wú)需開(kāi)啟實(shí)驗(yàn)特性),一起學(xué)習(xí)一下吧

一、偽元素 ::highlight()

要自定義任意文本樣式需要 CSS 和 JS 的共同作用。

首先來(lái)看 CSS 部分,一個(gè)新的偽元素,非常簡(jiǎn)單、

::highlight(custom-highlight-name) {
color: red
}

和::selection這類(lèi)偽元素比較類(lèi)似,僅支持部分文本相關(guān)樣式,如下

  • 文本顏色 color。
  • 背景顏色 background-color。
  • 文本修飾 text-decoration。
  • 文本陰影 text-shadow。
  • 文本描邊 -webkit-text-stroke。
  • 文本填充 -webkit-text-fill-color。

注意,注意,注意不支持background-image,也就是漸變之類(lèi)的也不支持。

但是,僅僅知道這個(gè)偽類(lèi)是沒(méi)用的,她還需要一個(gè)“參數(shù)”,也就是上面的custom-highlight-name,表示高亮的名稱(chēng),那這個(gè)是怎么來(lái)的呢?或者換句話(huà)說(shuō),如何去標(biāo)識(shí)頁(yè)面中需要自定義樣式的那部分文本呢?

這就需要借助下面的內(nèi)容了,看看如何生成這個(gè)“參數(shù)”,這才是重點(diǎn)

二、CSS Custom Highlight API

大部分操作其實(shí)和這個(gè)原理是相同的,只是把拿到的選區(qū)做了進(jìn)一步處理,具體分以下幾步

1、創(chuàng)建選區(qū)(重點(diǎn))

首先,通過(guò)Range[2]對(duì)象創(chuàng)建文本選擇范圍,就像用鼠標(biāo)滑過(guò)選區(qū)一樣,這也是最復(fù)雜的一部分,例如:

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);

這樣可以得到選區(qū)對(duì)象range1、range2。

2、創(chuàng)建高亮

然后,將創(chuàng)建的選區(qū)高亮實(shí)例化,需要用到Highlight[3]對(duì)象。

const highlight = new Highlight(range1, range2, ...);

當(dāng)然也可以根據(jù)需求創(chuàng)建多個(gè)。

const highlight1 = new Highlight(user1Range1, user1Range2);
const highlight2 = new Highlight(user2Range1, user2Range2, user2Range3);

這樣可以得到高亮對(duì)象highlight1、highlight2。

3、注冊(cè)高亮

接著,需要將實(shí)例化的高亮對(duì)象通過(guò)[CSS.Highlight](HighlightRegistry - Web APIs | MDN (mozilla.org "CSS.Highlight"))注冊(cè)到頁(yè)面。

有點(diǎn)類(lèi)似于Map對(duì)象的操作。

CSS.highlights.set("highlight1", highlight1);
CSS.highlights.set("highlight2", highlight2);

目前兼容性比較差,所以需要額外判斷一下。

if (CSS.highlights) {
//...支持CSS.highlights
}

注意看,上面注冊(cè)的key名,highlight1就是上一節(jié)提到的高亮名稱(chēng),也就是 CSS 中需要的“參數(shù)”

4、自定義樣式

最后,將定義的高亮名稱(chēng)結(jié)合::highlight,這樣就可以自定義選中樣式了

::highlight(highlight1) {
background-color: yellow;
color: black;
}

以上就是全部過(guò)程了,稍顯復(fù)雜,但是還是比較好理解的,關(guān)鍵是第一步創(chuàng)建選區(qū)的過(guò)程,最為復(fù)雜。

原理就是這樣,下面看一些實(shí)例。

三、彩虹文本

現(xiàn)在來(lái)實(shí)現(xiàn)文章開(kāi)頭圖示效果,彩虹文本效果??偣?種顏色,文字依次變色,不斷循環(huán),而且僅有一個(gè)標(biāo)簽。

CSS Custom Highlight API

這里總共有7?種顏色,所以需要?jiǎng)?chuàng)建7?個(gè)高亮區(qū)域,可以先定義高亮 CSS,如下:

::highlight(rainbow-color-1) { color: #ad26ad;  text-decoration: underline; }
::highlight(rainbow-color-2) { color: #5d0a99; text-decoration: underline; }
::highlight(rainbow-color-3) { color: #0000ff; text-decoration: underline; }
::highlight(rainbow-color-4) { color: #07c607; text-decoration: underline; }
::highlight(rainbow-color-5) { color: #b3b308; text-decoration: underline; }
::highlight(rainbow-color-6) { color: #ffa500; text-decoration: underline; }
::highlight(rainbow-color-7) { color: #ff0000; text-decoration: underline; }

現(xiàn)在肯定不會(huì)有什么變化,因?yàn)檫€沒(méi)創(chuàng)建選區(qū)

先創(chuàng)建一個(gè)高亮區(qū)域試試,比如第一個(gè)文字。

const textNode = document.getElementById("rainbow-text").firstChild;
if (CSS.highlights) {
const range = new Range();
range.setStart(textNode, 0); // 選區(qū)起點(diǎn)
range.setEnd(textNode, 1); // 選區(qū)終點(diǎn)
const Highlight = new Highlight(range);
CSS.highlights.set(`rainbow-color-1`, Highlight);
}

效果如下:

下面通過(guò)循環(huán),創(chuàng)建7個(gè)高亮區(qū)域。

const textNode = document.getElementById("rainbow-text").firstChild;

if (CSS.highlights) {

const highlights = [];
for (let i = 0; i < 7; i++) {
// 給每個(gè)顏色實(shí)例化一個(gè)Highlight對(duì)象
const colorHighlight = new Highlight();
highlights.push(colorHighlight);

// 注冊(cè)高亮
CSS.highlights.set(`rainbow-color-${i + 1}`, colorHighlight);
}

// 遍歷文本節(jié)點(diǎn)
for (let i = 0; i < textNode.textContent.length; i++) {
// 給每個(gè)字符創(chuàng)建一個(gè)選區(qū)
const range = new Range();
range.setStart(textNode, i);
range.setEnd(textNode, i + 1);

// 添加到高亮
highlights[i % 7].add(range);
}
}

這樣就在不改變dom的情況下實(shí)現(xiàn)了彩虹文字效果。

完整代碼可以查看以下任意鏈接:(注意需要Chrome 105+)

  • CSS Custom Highlight API (juejin.cn)[4]
  • CSS Custom Highlight API (codepen.io)[5]
  • CSS Custom Highlight API (runjs.work)[6]

四、文本搜索高亮

大家都知道瀏覽器的搜索功能,ctrl+f就可以快速對(duì)整個(gè)網(wǎng)頁(yè)就行查找,查找到的關(guān)鍵詞會(huì)添加黃色背景的高亮,如下:

以前一直很疑惑這個(gè)顏色是怎么添加的,畢竟沒(méi)有任何包裹標(biāo)簽?,F(xiàn)在有了CSS Custom Highlight API ,完全可以手動(dòng)實(shí)現(xiàn)一個(gè)和原生瀏覽器一模一樣的搜索高亮功能。

到目前為止,還無(wú)法自定義原生搜索高亮的黃色背景,以后可能會(huì)開(kāi)放。

假設(shè)HTML結(jié)構(gòu)是這樣的,一個(gè)搜索框和一堆文本。




閱文旗下囊括 QQ 閱讀、起點(diǎn)中文網(wǎng)、新麗傳媒等業(yè)界知名品牌,匯聚了強(qiáng)大的創(chuàng)作者陣營(yíng)、豐富的作品儲(chǔ)備,覆蓋 200 多種內(nèi)容品類(lèi),觸達(dá)數(shù)億用戶(hù),已成功輸出《慶余年》《贅婿》《鬼吹燈》《全職高手》《斗羅大陸》《瑯琊榜》等大量?jī)?yōu)秀網(wǎng)文 IP,改編為動(dòng)漫、影視、游戲等多業(yè)態(tài)產(chǎn)品。



《盜墓筆記》最初連載于起點(diǎn)中文網(wǎng),是南派三叔成名代表作。2015年網(wǎng)劇開(kāi)播首日點(diǎn)擊破億,開(kāi)啟了盜墓文學(xué) IP 年。電影于2016年上映,由井柏然、鹿晗、馬思純等主演,累計(jì)票房10億元。



慶余年》是閱文集團(tuán)白金作家貓膩的作品,自2007年在起點(diǎn)中文網(wǎng)連載,持續(xù)保持歷史類(lèi)收藏榜前五位。改編劇集成為2019年現(xiàn)象級(jí)作品,播出期間登上微博熱搜百余次,騰訊視頻、愛(ài)奇藝雙平臺(tái)總播放量突破160億次,并榮獲第26屆白玉蘭獎(jiǎng)最佳編?。ǜ木帲?、最佳男配角兩項(xiàng)大獎(jiǎng)。


《鬼吹燈》是天下霸唱?jiǎng)?chuàng)作的經(jīng)典懸疑盜墓小說(shuō),連載于起點(diǎn)中文網(wǎng)。先后進(jìn)行過(guò)漫畫(huà)、游戲、電影、網(wǎng)絡(luò)電視劇的改編,均取得不俗的成績(jī),是當(dāng)之無(wú)愧的超級(jí)IP。


簡(jiǎn)單美化一下后效果如下:

然后就是監(jiān)聽(tīng)輸入框,遍歷文本節(jié)點(diǎn)(推薦使用原生的treeWalker,當(dāng)然普通的遞歸也可以),根據(jù)搜索詞創(chuàng)建選區(qū),詳細(xì)代碼如下。

const query = document.getElementById("query");
const article = document.querySelector("article");

// 創(chuàng)建 createTreeWalker 迭代器,用于遍歷文本節(jié)點(diǎn),保存到一個(gè)數(shù)組
const treeWalker = document.createTreeWalker(article, NodeFilter.SHOW_TEXT);
const allTextNodes = [];
let currentNode = treeWalker.nextNode();
while (currentNode) {
allTextNodes.push(currentNode);
currentNode = treeWalker.nextNode();
}

// 監(jiān)聽(tīng)inpu事件
query.addEventListener("input", () => {
// 判斷一下是否支持 CSS.highlights
if (!CSS.highlights) {
article.textContent = "CSS Custom Highlight API not supported.";
return;
}

// 清除上個(gè)高亮
CSS.highlights.clear();

// 為空判斷
const str = query.value.trim().toLowerCase();
if (!str) {
return;
}

// 查找所有文本節(jié)點(diǎn)是否包含搜索詞
const ranges = allTextNodes
.map((el) => {
return { 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;
}

// 根據(jù)搜索詞的位置創(chuàng)建選區(qū)
return indices.map((index) => {
const range = new Range();
range.setStart(el, index);
range.setEnd(el, index + str.length);
return range;
});
});

// 創(chuàng)建高亮對(duì)象
const searchResultsHighlight = new Highlight(...ranges.flat());

// 注冊(cè)高亮
CSS.highlights.set("search-results", searchResultsHighlight);
});

最后,通過(guò)CSS設(shè)置高亮的顏色。

::highlight(search-results) {
background-color: #f06;
color: white;
}

實(shí)時(shí)搜索效果如下:

完整代碼可以查看以下任意鏈接:(注意需要Chrome 105+)

  • CSS Highlight search (juejin.cn)[7]
  • CSS Highlight search (codepen.io)[8]
  • CSS Highlight search (runjs.work)[9]

還可以將高亮效果改成波浪線(xiàn)。

::highlight(search-results) {
text-decoration: underline wavy #f06;
}

效果如下,是不是也可用作錯(cuò)別字標(biāo)識(shí)呢?

除了避免dom?操作帶來(lái)的便利外,性能也能得到極大的提升,畢竟創(chuàng)建、移除dom也是性能大戶(hù),下面是一個(gè)測(cè)試 demo,搬運(yùn)自

??https://ffiori.github.io/highlight-api-demos/demo-performance.html??[10]

測(cè)試代碼可以查看以下任意鏈接:

  • Highlight performance demo (juejin.cn)[11]
  • Highlight performance demo (codepen.io)[12]
  • Highlight performance demo (runjs.work)[13]

測(cè)試效果如下:

在10000?個(gè)節(jié)點(diǎn)的情況下,兩者相差100倍的差距!而且數(shù)量越大,性能差距越明顯,甚至直接導(dǎo)致瀏覽器卡死!

五、代碼高亮編輯器

最后再來(lái)看一個(gè)非常實(shí)用的例子,可以輕易實(shí)現(xiàn)一個(gè)代碼高亮的編輯器。

假設(shè) HTML結(jié)構(gòu)是這樣的,很簡(jiǎn)單,就一個(gè)純文本的標(biāo)簽。

ul{
min-height: 0;
}
.sub {
display: grid;
grid-template-rows: 0fr;
transition: 0.3s;
overflow: hidden;
}
:checked ~ .sub {
grid-template-rows: 1fr;
}
.txt{
animation: color .001s .5 linear forwards;
}
@keyframes color {
from {
color: var(--c1)
}
to{
color: var(--c2)
}
}

簡(jiǎn)單修飾一下,設(shè)置為可編輯元素。

.editor{
white-space: pre-wrap;
-webkit-user-modify: read-write-plaintext-only; /* 讀寫(xiě)純文本 */
}

效果如下:

那么,如何讓這些代碼高亮呢?

這就需要對(duì)內(nèi)容進(jìn)行關(guān)鍵詞分析提取了,我們可以用現(xiàn)有的代碼高亮庫(kù),比如highlight.js[14]。

hljs.highlight(pre.textContent, {
language: 'css'
})._emitter.rootNode.children

通過(guò)這個(gè)方法可以獲取到CSS語(yǔ)言的關(guān)鍵詞以及類(lèi)型,如下:

簡(jiǎn)單解釋一下,這是一個(gè)數(shù)組,如果是純文本,表示普通的字符,如果是對(duì)象,表示是關(guān)鍵詞,例如第一個(gè),children?里面的ul?就是關(guān)鍵詞,類(lèi)型是selector-tag?,也就是選擇器,除此之外,還有attribute、number、selector-class等各種類(lèi)型。有了這些關(guān)鍵詞,我們就可以把這些文本單獨(dú)選取出來(lái),然后高亮成不同的顏色。

接下來(lái),就需要對(duì)代碼內(nèi)容進(jìn)行遍歷了,方法也是類(lèi)似的,如下:

const nodes = pre.firstChild
const text = nodes.textContent
const highlightMap = {}
let startPos = 0;
words.filter(el => el.scope).forEach(el => {
const str = el.children[0]
const scope = el.scope
const index = text.indexOf(str, startPos);
if (index < 0) {
return
}
const item = {
start: index,
scope: scope,
end: index + str.length,
str: str
}
if (highlightMap[scope]){
highlightMap[scope].push(item)
} else {
highlightMap[scope] = [item]
}
startPos = index + str.length;
})
Object.entries(highlightMap).forEach(function([k,v]){
const ranges = v.map(({start, end}) => {
const range = new Range();
range.setStart(nodes, start);
range.setEnd(nodes, end);
return range;
});
const highlight = new Highlight(...ranges.flat());
CSS.highlights.set(k, highlight);
})
}
highlights(code)
code.addEventListener('input', function(){
highlights(this)
})

最后,根據(jù)不同的類(lèi)型,定義不同的顏色就行了,如下:

::highlight(built_in) {
color: #c18401;
}
::highlight(comment) {
color: #a0a1a7;
font-style: italic;
}
::highlight(number),
::highlight(selector-class){
color: #986801;
}
::highlight(attr) {
color: #986801;
}
::highlight(string) {
color: #50a14f;
}
::highlight(selector-pseudo) {
color: #986801;
}
::highlight(attribute) {
color: #50a14f;
}
::highlight(keyword) {
color: #a626a4;
}

這樣就得到了一個(gè)支持代碼高亮的簡(jiǎn)易編輯器了。

相比傳統(tǒng)的編輯器而言,這個(gè)屬于純文本編輯,非常輕量,在高亮的同時(shí)也不會(huì)影響光標(biāo),因?yàn)椴粫?huì)生成新的??dom??,性能也是超級(jí)棒。

完整代碼可以查看以下任意鏈接:

  • CSS highlight editor (juejin.cn)[15]
  • CSS highlight editor (codepen.io)[16]
  • CSS highlight editor (runjs.work)[17]

六、最后總結(jié)一下

以上就是關(guān)于CSS Custom Highlight API的使用方式以及應(yīng)用示例了,下面再來(lái)回顧一下使用步驟:

  1. 創(chuàng)建選區(qū),new Range。
  2. 創(chuàng)建高亮,new Highlight。
  3. 注冊(cè)高亮,CSS.highlights.set。
  4. 自定義樣式,::highlight()。

相比傳統(tǒng)使用標(biāo)簽的方式而已,有很多優(yōu)點(diǎn)

  1. 使用場(chǎng)景更廣泛,很多情況下不能修改dom或者成本極大
  2. 性能更高,避免了操作dom?帶來(lái)的額外開(kāi)銷(xiāo),在dom?較多情況下性能差異至少100倍
  3. 幾乎沒(méi)有副作用,能有效減少dom變化引起的其他影響,比如光標(biāo)選區(qū)的處理

其實(shí)歸根結(jié)底,都是dom?變化帶來(lái)的,而Highlight API恰好能有效避開(kāi)這個(gè)問(wèn)題。當(dāng)然也有一些缺陷,由于僅僅能改變文本相關(guān)樣式,所以也存在一些局限性,這個(gè)就需要權(quán)衡了,目前兼容性也還不足,僅適用于內(nèi)部項(xiàng)目,敬請(qǐng)期待

參考資料

[1]CSS Custom Highlight API: https://developer.mozilla.org/en-US/docs/Web/API/CSS_Custom_Highlight_API。

[2]Range: https://developer.mozilla.org/en-US/docs/Web/API/Range。

[3]Highlight: https://developer.mozilla.org/en-US/docs/Web/API/Highlight。

[4]CSS Custom Highlight API (juejin.cn): https://code.juejin.cn/pen/7198496899391815736。

[5]CSS Custom Highlight API (codepen.io): https://codepen.io/xboxyan/pen/qByzGYr。

[6]CSS Custom Highlight API (runjs.work): https://runjs.work/projects/450431c8f0064298。

[7]CSS Highlight search (juejin.cn): https://code.juejin.cn/pen/7198488612801871929。

[8]CSS Highlight search (codepen.io): https://codepen.io/xboxyan/pen/eYjwoqo。

[9]CSS Highlight search (runjs.work): https://runjs.work/projects/a661feba3dad44c9。

[10]https://ffiori.github.io/highlight-api-demos/demo-performance.html: https://ffiori.github.io/highlight-api-demos/demo-performance.html。

[11]Highlight performance demo (juejin.cn): https://code.juejin.cn/pen/7198487962978353208。

[12]Highlight performance demo (codepen.io): https://codepen.io/xboxyan/pen/YzjoMmp。

[13]Highlight performance demo (runjs.work): https://runjs.work/projects/e5fe09f70d324d99。

[14]highlight.js: https://highlightjs.org/。

[15]CSS highlight editor (juejin.cn): https://code.juejin.cn/pen/7198487629262749756。

[16]CSS highlight editor (codepen.io): https://codepen.io/xboxyan/pen/RwBzOmK。

[17]CSS highlight editor (runjs.work): https://runjs.work/projects/9ff7ab8f12844ce1。


文章標(biāo)題:原生 CSS Custom Highlight 終于來(lái)了
文章地址:http://www.dlmjj.cn/article/cdgjsgh.html