CSS色域、色彩空間、CSS Color 4新標(biāo)準
當(dāng)前位置:點晴教程→知識管理交流
→『 技術(shù)文檔交流 』
引言近期,三大主流瀏覽器引擎均發(fā)布最新版本,支持W3C的CSS Color 4標(biāo)準,包含新的取色方法 本文首先會先簡單介紹幾個色彩的基礎(chǔ)概念,了解為何需要新標(biāo)準,之后會介紹新標(biāo)準中的方法和語法使用。 基礎(chǔ)概念色域(color gamut)指顏色的可選范圍。如sRGB色域,目前web廣泛應(yīng)用的色域標(biāo)準,使用紅(red)綠(green)藍(blue)作為基礎(chǔ)色,色值范圍0~255,三種基礎(chǔ)色互相混合起來可展示255*255*255種顏色,這大致可理解為sRGB的色域。 現(xiàn)代web css使用的sRGB色域僅滿足基礎(chǔ)性的色彩需求,能展示的色彩范圍遠小于人類肉眼所能感知的顏色范圍,也遠低于高清展示的要求。 以下是sRGB與其他幾種色域標(biāo)準的色值范圍大小比較: 以下是sRGB與人類肉眼可感知的色域比較: 色彩空間(color space)色彩空間可以理解為一個基于某一色域標(biāo)準下構(gòu)建的空間數(shù)學(xué)模型,例如一些簡單的方塊、圓柱的3D模型,可以用來標(biāo)記出色域中每個顏色的空間位置,各個顏色之間的關(guān)系等。 再用sRGB舉例,紅(red)綠(green)藍(blue)三種基礎(chǔ)色可設(shè)置為3個直線坐標(biāo)軸,每種顏色便可標(biāo)記為這個立方體中的一個點,在css中便是使用rgb()方法來取色,參數(shù)為指定顏色在色彩空間中的坐標(biāo)(R, G, B)。 再再比如css的另一個取色方法hsl(),使用的是一套完全不同的色彩空間HSL,H色相(hue)是取值范圍為0~360的角度,可作為角軸;S飽和度(Saturation)和L亮度(Lightness)作為兩個直線軸,可構(gòu)建為一個圓柱形的空間,css中使用hsl(H, S, L)表示顏色。 一種色域標(biāo)準可以使用不同的色彩空間來描述,不同的色域標(biāo)準也可以使用的是同一類的色彩空間表示。例如sRGB可以使用 為什么要支持高清色彩高清意味著更高范圍的色域,讓我們先直觀感覺一下窄色域與廣色域的視覺差距: 在實際的css顏色取值中,我們常用的方法有很多 雖然目前的網(wǎng)絡(luò)顯示設(shè)備很多還是sRGB標(biāo)準,并不支持顯示更廣色域標(biāo)準的色彩,僅部分HDR顯示器、或視頻錄制設(shè)備、電影制造中使用了如Display P3這類更廣的色域標(biāo)準。但對于高清的需求只會越來越多,支持更廣色域標(biāo)準注定也是未來web端顯示的目標(biāo)之一。 為應(yīng)對這一趨勢,W3C的CSS Color 4標(biāo)準定義了新方法 CSS Color 4回顧現(xiàn)有的色彩空間2000年以來,我們有多種方式指定色值: 不同的方法對應(yīng)的是不同的色彩空間,但色域都是同一個,即sRGB。 HEX使用十六進制的數(shù)字來分別表示R、G、B、A的值 .valid-css-hex-colors { /* 一般標(biāo)準 */ --3-digits: #49b; --6-digits: #4499bb; /* 帶透明度 */ --4-digits-opaque: #f9bf; /* 不透明 */ --8-digits-opaque: #ff99bbff; /* 不透明 */ --4-digits-with-opacity: #49b8; /* 透明度88% */ --8-digits-with-opacity: #4499bb88; /* 透明度88% */} RGB使用0255的十進制數(shù)字,或是0%100%的百分比來指明R、G、B,透明度A使用百分比或0~1的數(shù)字表示 .v]alid-css-rgb-colors{ --classic:rgb(64, 149, 191); --modern:rgb(64 149 191); --percents:rgb(25% 58% 75%); --classic-with-opacity-percent:rgba(64, 149, 191, 50%); --classic-with-opacity-decimal:rgba(64, 149, 191, .5); --modern-with-opacity-percent:rgb(64 149 191 / 50%); --modern-with-opacity-decimal:rgb(64 149 191 / .5); --percents-with-opacity-percent:rgb(25% 58% 75% / 50%); --percents-with-opacity-decimal:rgb(25% 58% 75% / 50%); --empty-channels:rgb(none none none); } HSL這種色彩空間更符合人類自然理解,無需了解紅綠藍基礎(chǔ)色是如何混合的。參數(shù)分別表示:
.valid-css-hsl-colors{ --classic:hsl(200deg, 50%, 50%); --modern:hsl(200 50% 50%); --classic-with-opacity-percent:hsla(200deg, 50%, 50%, 50%); --classic-with-opacity-decimal:hsla(200deg, 50%, 50%, .5); --modern-with-opacity-percent:hsl(200 50% 50% / 50%); --modern-with-opacity-decimal:hsl(200 50% 50% / .5); /* 無色相和飽和度,僅用亮度可表示黑白色 */ --empty-channels-white:hsl(none none 100%); --empty-channels-black:hsl(none none 0%); } HWB形式上和HSL類似,但使用的3個維度為:
.valid-css-hwb-colors{ --modern:hwb(200deg 25% 25%); --modern2:hwb(200 25% 25%); --modern-with-opacity-percent:hwb(200 25% 25% / 50%); --modern-with-opacity-decimal:hwb(200 25% 25% / .5); /* 無色相和飽和度,僅用亮度可表示黑白色 */ --empty-channels-white:hwb(none 100% none); --empty-channels-black:hwb(none none 100%); } 新方法color()新的 .valid-css-color-function-colors { --srgb: color(srgb 1 1 1); --srgb-linear: color(srgb-linear 100% 100% 100% / 50%); --display-p3: color(display-p3 1 1 1); --rec2020: color(rec2020 0 0 0); --a98-rgb: color(a98-rgb 1 1 1 / 25%); --prophoto: color(prophoto-rgb 0% 0% 0%); --xyz: color(xyz 1 1 1); } 方法定義:color(colorspace c1 c2 c3[ / A])
使用color()描述不同的色彩空間sRGB不再支持0255取值,改為01范圍,其實和百分比的形式是等價的。如果傳了大于1的數(shù)值也默認當(dāng)作1來解析。 .valid-css-srgb-colors{ --percents:color(srgb 34% 58% 73%); --decimals:color(srgb .34 .58 .73); --percents-with-opacity:color(srgb 34% 58% 73% / 50%); --decimals-with-opacity:color(srgb .34 .58 .73 / .5); /* 色值為none或空時,表示黑色 */ --empty-channels-black:color(srgb none none none); --empty-channels-black2:color(srgb); } Linear sRGBLinear sRGB和sRGB是不同的色彩空間,sRGB的取值是通過一個伽馬曲線函數(shù)做過校正的,并不是線性變化的,更適應(yīng)人眼的感知特性,即對明暗的感知是非線性的;而Linear sRGB的顏色變化是線性的,以下是明暗從0-1漸變時,兩種色彩空間實際的漸變走向。 .valid-css-srgb-linear-colors{ --percents:color(srgb-linear 34% 58% 73%); --decimals:color(srgb-linear .34 .58 .73); --percents-with-opacity:color(srgb-linear 34% 58% 73% / 50%); --decimals-with-opacity:color(srgb-linear .34 .58 .73 / .5); /* 色值為none或空時,表示黑色 */ --empty-channels-black:color(srgb-linear none none none); --empty-channels-black2:color(srgb-linear); } Display P3、Rec2020display P3是最早由蘋果公司推行的。如今這一標(biāo)準已成為HDR顯示的基礎(chǔ)標(biāo)準,能顯示的顏色比sRGB多50%。而Rec2020標(biāo)準比display P3的色域更廣,可以用來顯示4K甚至8K的影像,但目前支持這一標(biāo)準的終端顯示器還很少。兩種色域都是使用RGB來描述的。 .valid-css-display-p3-colors{ --percents:color(display-p3 34% 58% 73%); --decimals:color(display-p3 .34 .58 .73); --percent-opacity:color(display-p3 34% 58% 73% / 50%); --decimal-opacity:color(display-p3 .34 .58 .73 / .5); /* 無色度色相,展示為黑色 */ --empty-channels-black:color(display-p3 none none none); --empty-channels-black2:color(display-p3); } .valid-css-rec2020-colors { --percents: color(rec2020 34% 58% 73%); --decimals: color(rec2020 .34 .58 .73); --percent-opacity: color(rec2020 34% 58% 73% / 50%); --decimal-opacity: color(rec2020 .34 .58 .73 / .5); /* 無色度色相,展示為黑色 */ --empty-channels-black: color(rec2020 none none none); --empty-channels-black2: color(rec2020); } CIE標(biāo)準讓我們先回到開頭的兩張色域圖,會發(fā)現(xiàn)基于RGB描述的色域基本是一個三角形,因為都是使用3個基礎(chǔ)色混合而成,但人眼所能感知的色域是形似馬蹄的圖形(具體如何繪制出的,感興趣的可自行搜索了解)?;赗GB標(biāo)準的色彩空間,都很難完全覆蓋人眼能感知的所有顏色。而基于CIE標(biāo)準(國際照明委員會制定的一種測定顏色的國際標(biāo)準,它描述了人眼對顏色的感知和色彩的測量方法)的色彩空間,理論上是能夠包括人視覺所能感知到的所有顏色。 CSS Color 4新標(biāo)準也新增了對于CIE標(biāo)準色域的支持。下面介紹的lab()、lch()、oklab()、oklch()都是基于CIE的取色新方法。 lab()
.valid-css-lab-colors{ --percent-and-degrees:lab(58% -16 -30); --minimal:lab(58 -16 -30); --percent-opacity:lab(58% -16 -30 / 50%); --decimal-opacity:lab(58% -16 -30 / .5); /* 后兩個參數(shù)為none是可表示純灰度 */ --empty-channels-white:lab(100 none none); --empty-channels-black:lab(none none none); } lch()lch使用的維度分別是:
.valid-css-lch-colors{ --percent-and-degrees:lch(58% 32 241deg); --just-the-degrees:lch(58 32 241deg); --minimal:lch(58 32 241); --percent-opacity:lch(58% 32 241 / 50%); --decimal-opacity:lch(58% 32 241 / .5); /* 后兩個參數(shù)為none是可表示純灰度 */ --empty-channels-white:lch(100 none none); --empty-channels-black:lch(none none none); } oklab()oklab是校正版的lab,優(yōu)化了圖片處理質(zhì)量,在CSS中意味著漸變優(yōu)化和顏色處理函數(shù)優(yōu)化,消除了色相偏移(hue shift,即在lab中改變顏色純度,色相也會變化),使用的維度和lab()是一致的。 .valid-css-oklab-colors{ --percent-and-degrees:oklab(64% -.1 -.1); --minimal:oklab(64 -.1 -.1); --percent-opacity:oklab(64% -.1 -.1 / 50%); --decimal-opacity:oklab(64% -.1 -.1 / .5); /* 后兩個參數(shù)為none是可表示純灰度 */ --empty-channels-white:oklab(100 none none); --empty-channels-black:oklab(none none none); } oklch()相應(yīng)的,oklch是lch的校正版,取色的邏輯和hsl類似,在圓色盤中選擇一個角度從而選中一個色相,再通過調(diào)節(jié)亮度和純度,也就是hsl中的飽和度,純度和飽和度基本可認為是等價的,區(qū)分僅在于純度和亮度的調(diào)節(jié)通常是同步進行的,否則純度很容易超出目標(biāo)色域的范圍。這里有一個oklch的拾色器,可以體驗下。 .valid-css-oklch-colors{ --percent-and-degrees:oklch(64% .1 233deg); --just-the-degrees:oklch(64 .1 233deg); --minimal:oklch(64 .1 233); --percent-opacity:oklch(64% .1 233 / 50%); --decimal-opacity:oklch(64% .1 233 / .5); /* 后兩個參數(shù)為none是可表示純灰度 */ --empty-channels-white:oklch(100 none none); --empty-channels-black:oklch(none none none); } color-mix()除了新增的一些取色方法外,新標(biāo)準還有一個混色函數(shù),可以將上邊提到的各種不同色彩空間的中顏色進行混合計算出新顏色。 color-mix(in lch, plum, pink); color-mix(in lch, plum 40%, pink); color-mix(in srgb, #34c9eb 20%, white); color-mix(in hsl longer hue,hsl(120 100% 50%) 20%, white); 方法定義:color-mix(method, color1[ p1], color2[ p2])
項目中如何使用高清色彩在我們應(yīng)用一項新語法時,我們通常會有兩種策略:優(yōu)雅降級和漸進增強,具體實施方案: 優(yōu)雅降級這種實施起來比較簡單,即同時使用新舊取色方法,讓瀏覽器自動判斷展示哪種 /* 原代碼 */color: red;color:color(display-p3 1 0 0);/* 如果瀏覽器不支持display-p3,則會只解析第一行 */color: red;/* 如果瀏覽器支持,則會最終使用第二行 */color:color(display-p3 1 0 0); 漸進增強使用@supports和@media先判斷當(dāng)前瀏覽器是否支持新的色域標(biāo)準,并在條件的情況下提供新的色值。 色域媒體查詢
@media(dynamic-range: high){ /* safe to use HD colors */ color: color(display-p3 34% 58% 73%); }
@media(color-gamut: srgb){ /* safe to use srgb colors */ color: #4499bb; }@media(color-gamut: p3){ /* safe to use p3 colors */ color: color(display-p3 34% 58% 73%); }@media(color-gamut: rec2020){ /* safe to use rec2020 colors */ color: color(rec2020 34% 58% 73%); } 除了可以直接使用css媒體查詢,還可用途Javascript中的 const hasHighDynamicRange = window.matchMedia('(dynamic-range: high)').matches; console.log(hasHighDynamicRange);// true || false const hasP3Color = window.matchMedia('(color-gamut: p3)').matches; console.log(hasP3Color);// true || false 色彩空間查詢
@supports(background:rgb(0 0 0)){ /* rgb color space supported */ background:rgb(0 0 0); }@supports(background:color(display-p3 0 0 0)){ /* display-p3 color space supported */ background:color(display-p3 0 0 0); }@supports(background:oklch(0 0 0)){ /* oklch color space supported */ background:oklch(0 0 0); } 應(yīng)用實例在實際應(yīng)用中,在新舊標(biāo)準過渡期間,可以綜合使用上邊的查詢方法,下面是一個兼容新舊標(biāo)準的實例: :root{ --neon-red:rgb(100% 0 0); --neon-blue:rgb(0 0 100%); }/* 設(shè)備是否支持展示高清 */@media(dynamic-range: high){ /* 瀏覽器是否能解析display-p3 */ @supports(color:color(display-p3 0 0 0)){ /* 安全使用display-p3 */ --neon-red:color(display-p3 1 0 0); --neon-blue:color(display-p3 0 0 1); } } 開發(fā)調(diào)試如果更新了最新版本的chrome瀏覽器的話,就能發(fā)現(xiàn)DevTools里的拾色器已經(jīng)支持了CSS Color 4中的新語法,點擊頁面元素中的顏色屬性,在彈出的拾色器中,中間色值右側(cè)的箭頭,之前的版本中,點擊箭頭是在hex、rgb、hsl和hwb之間切換,但新版本中,點擊箭頭會出現(xiàn)下拉框,可以看到所有新增的色彩空間和方法,以及當(dāng)前色值所對應(yīng)的可替換色值。 同時在選擇了不同的色彩空間后,色彩的可調(diào)節(jié)參數(shù)也會相應(yīng)改變。 當(dāng)我們選擇了一個非sRGB色域的色值后,會發(fā)現(xiàn)拾色器的上方區(qū)域里會展示一條sRGB的分界線,可以清晰地看出當(dāng)前選擇的顏色所在的色域。這能幫助開發(fā)者分辨高清色與非高清色。 而當(dāng)我們選擇一個超出sRGB范圍的顏色后,再來點擊色值右側(cè)的箭頭彈出選項列表時,會發(fā)現(xiàn)sRGB色域下的色值后邊會帶上一個三角嘆號。這說明當(dāng)前色值已超出了sRGB所能描述的范圍,只能使用相近的顏色作為替代。 關(guān)于chrome DevTools更多關(guān)于高清顏色的更新,可參閱官方文檔。 總結(jié)sRGB之外的色域和色彩空間目前雖然還剛剛在web端起步,但未來的設(shè)計和開發(fā)要求可能會慢慢出現(xiàn),尤其是H5動畫、游戲、3D圖像等等,對于色彩顯示的要求不會永遠停留在sRGB階段,希望本文簡陋的介紹能讓大家多少開始了解一些關(guān)于色彩的東西。如有錯誤或疏漏,歡迎指正討論。 參考文章: 1. https://web.dev/articles/color-spaces-and-functions?hl=en 2. https://developer.chrome.com/articles/high-definition-css-color-guide/ 3. https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/color
該文章在 2023/10/27 17:35:29 編輯過 |
關(guān)鍵字查詢
相關(guān)文章
正在查詢... |