【譯】CSS 十六進位制顏色揭祕

sunshine小小倩發表於2019-03-04

CSS 十六進位制顏色揭祕

簡介

作為一個長期在世界各地主持技術峰會的主持人,我有機會和許多技術傳播者交流,我將這些人稱為“專業的技術作者”,忙於他們的工作。

一個主題反覆出現的是 CSS 中的顏色 —— 特別是它們在 CSS 的屬性值中使用十六進位制表示法。你可以在你的 CSS 中各個地方看見這些看起來怪怪的字串:#FF0080#9AC0B3#B5CBE8。我的意思是 #WTF,不是嗎?

雖然大部分的技術作者都會在某些時候遇到十六進位制編碼的顏色值,它通常情況下是一個模糊的問題,所以從來沒有人花時間去解釋他們。我聽到最多的評論大都是這樣的:

  • 我一直在使用十六進位制編碼的色值,但是我真的不明白
  • 其實我知道一些十六進位制編碼的色值代表什麼顏色,但是我不知道為什麼
  • 有時候我可以修改十六進位制的編碼來達到我想要的效果,但是我不理解它們是怎麼工作的。
  • 使用一個像 #BADA55 這樣的不易理解的十六進位制編碼是錯誤的嗎?

好的,就拿最後一個來說,但是答案是否定的,不,使用 #BADA55 這樣的十六進位制表示顏色不是錯誤的。如果你是想要一個黃綠色,那麼你就可以使用 #BADA55

CSS 中的顏色

在 CSS 中顏色無處不在,它們可以作為前景、背景、陰影、表格、邊框、連結、底紋等等這些屬性的值。正因為顏色對於 CSS 是如此的重要,所以我們需要一個通用、標準的方式來引用它們,以便在所有瀏覽器中得到相同的顏色,這樣使用者就可以看到作者希望展現的顏色。

在 CSS 中設定顏色有很多種方式,我們稍後會討論其中的幾種。但本文的重點是十六進位制顏色,因為它具有明確性、一致性,而且還十分優雅。雖然它有這麼多優點,但是有個缺點就是它並不是很直觀。

物理學

讓我們從色彩的基本原理開始:白光其實是由彩虹的所有顏色組成。知道 Roy G. Biv 嗎?它是紅、橙、黃、綠、藍、靛、紫七種顏色的英文首字母縮略詞,我們看到的白光僅僅是有這七種顏色混合組成的。

如果你認為這是一個笑話,那麼你太年輕了
如果你認為這是一個笑話,那麼你太年輕了

顏料

要了解顏色是如何工作的,讓我們先來回顧一下顏料中的物理光線。

顏料的三原色
顏料的三原色

學習顏料的第一件事情就是你可以把原色組合成第二種顏色。例如,你可以將藍色和紅色混合在一起得到紫色。同樣,還有其他的選擇,你可以將紅色和黃色混合成橙色,黃色和藍色混合成綠色 —— 全新的第二種顏色。

顏料中的生成色
顏料中的生成色

你當時不知道的是它的成色原理:顏料減色法原理。也就是說,它們吸收或減去白光中的某些色光,只反射它們沒有減去的光。

對於那些沒有試驗過的人來說,這意味著一個看起來是單一顏色的物體實際上不是那種顏色。因為物體吸收了所有的光波長,但是隻反射回來一種顏色的光(我們看到的),它實際上是所有的顏色。換句話說,是除了它顯示的顏色之外的所有顏色。我們看到的橘色實際上並不是橙色。雖然不符合常理,但事實如此。

在不知道它的物理特性的情況下,我們早都理解將兩種或兩種以上的顏色組合在一起會得到其他顏色,而且我們新增的顏色越多,新的顏色就越多,每種顏色都比原色更深。我們最終了解到,如果把所有的顏色混合在一起,我們最終會得到黑色,或者是非常接近黑色的顏色。我們現在知道,這是因為從原來的白光開始,隨著越來越多的顏料被加入,越來越多的光被吸收或減去。所以,明顯的是,光線越少 = 顏色越深。 提示:請記住這一點,這在後面將會很重要。

非常非常深的灰色就接近黑色
非常非常深的灰色就接近黑色

我們發現顏料混合的另一件事是,除了被混合的顏色外,混合顏色的比列也會影響結果。即同為藍黃混合,黃色多一點,會產生一個淡淡的“春綠”,而藍色多一點則會產生一個暗暗的“森林綠”。所以很明顯,混合的比例也很重要。

色光

你明白了嗎?那好,現在忘了它,因為所有的計算機螢幕都是基於光而不是顏料。顏料的知識只是為光學做準備,稍後你會感謝我的。事實證明,光學的物理現象是和顏料相同的,只是稍有不同(這是真的)。

就像上面討論顏料一樣,我們先從原色開始,在光學上它們是紅色、綠色和藍色。

我們一起來看,這可能有一點粗糙
我們一起來看,這可能有一點粗糙

就像顏料一樣,我們可以將原色混合獲得第二種顏色。並且,就和顏料一樣,並且也有很多種混合結果。藍光和紅光混合得到名為 purple-y 的顏色,我們稱之為洋紅;綠光和藍光混合得到名為 teal-y 的顏色,我們稱為青色;好吧,很合理,有紅燈了也有綠燈了……什麼?!?

是的,最後一個確實和前面的不一樣,並不像直觀感受的那樣,但是這就是光學的工作原理:紅光和綠光相加得到黃光。

這是為什麼呢?本來就是如此,光學的工作原理就是這樣的。你可能會對此感到困惑,如果對此感到困惑,你可以諮詢這裡面的 專家

這是因為色光是加色法,和顏料相反。我們組合的光波波長越多,新的顏色就越多,直到所有顏色都以最大比例混合時 —— 最終將得到白光。很容易看出,我們得到的每一種混合色都比它的原色更亮。因此,對於顏料我們的推論是:光線越少 = 顏色越深,而對於色光則是:光線越多 = 顏色越亮

三種原色的光聚集在一起就成了白光
三種原色的光聚集在一起就成了白光

回到 CSS

在 CSS 中,我們要達到預期的顏色效果,我們需要一種方式,不僅指定選哪一種原色,而且還要指定每一種顏色的比例。也就是說,我們需要精確地指定多少紅色、綠色和藍色的光線相加以獲得特定的顏色。嘿,這是物理學!

在計算機世界,值的範圍一般是在 0-255 之間。當然,這是有原因的,但現在你可以不用在意。因為要解釋二進位制是如何工作的,是另一篇文章的內容。現在,請相信我,每種顏色的最小值是 0,最大值是 255,謝謝。

設定顏色的方法

雖然我在本文中提倡十六進位制表示色值的方法,但我不能忽視這一事實,它決不是唯一指定 CSS 顏色的方法。在繼續之前,讓我們快速看看其他三種方法。

注意: 如果你對這部分的內容完全不感興趣,你可以直接跳到下一主題,快速瀏覽。說真的,你不會錯過任何關於十六進位制的重要資訊。這個小插曲主要是未來完整性,很大程度上是為了避免文末出現大量“但是,但是,但是...”的評論。

顏色名

通過顏色名設定顏色是一種簡單的方式,所有現代瀏覽器都能解釋各種顏色名,它們可以用作 CSS 屬性值。很多名字都很有道理,比如 black(黑)、white(白)、red(紅)、green(綠)、blue(藍)、yellow(黃)、purple(紫)、orange(橙)等等。有些不是很明顯,像 aquamarine(海藍寶石),blueviolet(藍紫色),cornsilk(花絲),khaki(卡其布)。然後有些是荒謬的,像 aliceblue(愛麗絲藍)、lavenderblush(淡紫紅)、burlywood(原木色)、和 gainsboro(淡灰色)。

問題是,顏色名不夠靈活,也不常見。purple 只對應一種顏色,那就是“紫色”。如果你想要一個特定的紫色,比如“淡紫”、“薰衣草紫”,那它做不到。當然,有 “mediumorchid”、“plum” 和 “thistle” 這些名稱可供選擇,但這些可能並不是你想要的顏色,並且你怎麼通過名稱知道是什麼顏色呢?正如剛才提到的,名稱越奇特,顏色越不直觀。我認為沒有人能猜到 “peru” 是什麼顏色。

例如,這是一個有紅色背景的黃色文字,使用顏色名設定:

span.hilite { color: yellow; background-color: red; }

RGB

另一種方法被稱為 RGB,對於……嗯,我希望你能解決那個問題。這種方法使用普通的數字,並且相當整齊地用十進位制記數法或百分比指定每個顏色的比例。但這種方法,冗長並複雜;有額外的括號,逗號,和/或百分比符號,很容易寫成不是你想要的顏色或者出錯。

這是一個有紅色背景的黃色文字,使用 RGB 設定:

span.hilite { color: rgb(255, 255, 0); background-color: rgb(255, 0, 0); }

或者

span.hilite { color: rgb(100%, 100%, 0%); background-color: rgb(100%, 0%, 0%); }

HSL

只是為了進一步把水攪渾,另一種方法稱為 HSL,分別表示色調,飽和度,亮度。這種方法 —— 具有多種我不想使用的子方法,使用十進位制值和百分比的值。十進位制值表示色輪上的顏色從 0 到 360,其中 0 是紅色,120 是綠色,240 是藍色。百分比表示光的數量,其中 0% 是無色的,100% 是全色的。亮度百分比然後修改顏色的亮度或光度,其中 0% 是黑色的,100% 是白色的。我一直覺得這個方法有點混亂,根據我的經驗,開發人員很少使用這種方法。

這是一個有紅色背景的黃色文字,使用 HSL 設定:

span.hilite { color: hsl(60, 100%, 50%); background-color: hsl(0, 100%, 50%) }

十六進位制表示

另外一種,十六進位制記數法,通常是最流行的 CSS 顏色命名方法。它是具體的、一致的、緊湊的和精確的。使用三個字元的十六進位制碼在範圍 00-FF 的指定 RGB 值,其中 00 是沒有顏色和 FF 是所有顏色聚集在一起形成的白色。

這是一個有紅色背景的黃色文字,使用十六進位制色值設定:

span.hilite { color: #FFFF00; background-color: #FF0000; }

好了,這就夠了,讓我們繼續來看!

快速的回顧一下

我知道你認為我在撒謊,但十六進位制真的比你想象的容易。十六進位制色值是基於十六進位制(基數為 16)計算的。為了理解十六進位制是如何工作的,你只需要理解十進位制(基數為 10)是如何工作的。哦,等等,你已經做了!很好,讓我們回顧一下。

請不要跳過這部分,好嗎?我知道你理解十進位制是怎樣工作的,我想讓你想一下為什麼它能起作用。

十進位制系統有十個單字元數字,0 到 9。你可以一直加一來獲得下一個數字,但最終你將用完數字。當這種情況發生時,你把一個 0 放在這個位置,然後在左邊再增加一位數。讓我們來思考一下這句話的含義。

這裡最重要的一點是,位置的名字表示它們中的數字的值,而每個位置的名稱代表的最大值,在其右邊的位置表示。在十進位制中,最右邊的位置稱為“個位”,右邊的第二個位置稱為“十位”。數字“9”的意思是“九個一”,如果我們加上“1”(“一個一”),我們就用完了數字,所以我們就在個位放了一個 0,在十位放了一個 1,得到了兩位數 10。

因此,十進位制值 10,我們稱之為“十”,實際上表示“一個十和零個一”。同樣,十進位制的 26 表示“兩個十和六個一”,十進位制的 33 表示“三個十和三個一”,十進位制的 42 表示“四個十和兩個二”。(當然, 這就是最終問題的答案 )。

十六進位制的偉大之處在於它工作得很像十進位制。確切地說! 不開玩笑、不誇張、並且你也只能選擇使用十進位制的方式理解十六進位制。十六進位制算術和十進位制算術完全一樣,它只有十六個字元數字而不是十個數字。

將 A ~ F 視為數字,對應十進位制中的 10 ~ 15。當然,計算機是對你友好的才提出多出這六個數字,但(a)我們必須要學習他們,(b)如何在鍵盤輸入。(c)那東西是什麼,他們只是在字母最小的惡作劇。

換句話說,十進位制值 10 用十六進位制的一個數字 A 表示,這表示“十個一”。十六進位制數字 B 表示“十一個一”,等等,直到 F,表示“十五個一”。

重複一遍,就和十進位制一樣,每一個位置的名字表示它們中的數字的值,每個位置的名稱代表的最大值可以在其右邊的位置表示。最右邊的地方仍被稱為“一”,我們現在可以數到 F(“十五個一”),右邊起第二位被稱為“16”。

十六進位制加法:9 + 1 = a
十六進位制加法:9 + 1 = a

數字“9”還表示“九個一”,但現在,如果我們加上“1”(“一個一”)的話,我們還沒有用完的數字,所以我們可以在個位使用 A(“十個一”),只需要讓十六顯示為兩位數。

就像十進位制一樣,你可以不斷地增加一個數字來獲得下一個數字,但是你仍然會用完數字。當這種情況發生時,你把一個 0 放在這個位置,然後在這位數的左邊新增一位數。就和十進位制一樣,再讓我們想想這句話的意思。

十六進位制加法:f + 1 = 10
十六進位制加法:f + 1 = 10

所以,10(數字 1 和數字 0)的十六進位制值不是十,而是十六,因為它的表示“一個十六,零個一”。然而,就像十進位制一樣,任何兩位數字的十六進位制數字都可以用同樣的方式讀取和理解。這意味著,如果我們繼續計數遞增到十六的時我們就使用“F”,重點來了:我們可以使用十六進位制的兩位數從 00 到 FF 代表任何從 0 到 255 的十進位制數

例如,在下面的圖表中,十六進位制的 14(也就是“數字一和數字四”)是十進位制的二十,因為它實際上是一個十六(16)和四個一(1),在十進位制中 16 + 4 = 20。十六進位制的 A5 代表著一百六十五,因為因為它是十個十六(10 16 = 160)和五個一(1 5 = 5)。最終,要特別注意紅色的線,因為他們是最終的範圍和範圍的中間點:十六進位制的 00(數字零和數字零)是零,十六進位制的 FF 是二百五十五(15 16 + 15 = 255),並且十六進位制的 80(數字八和數字零)是一百二十八(8 16 + 0 * 1 = 128),是 00 和 FF 的中間值。提示:記住 “80” 是中間點,我們馬上就要用到它。

十六進位制計數,00 到 FF
十六進位制計數,00 到 FF

請和我一起繼續

讓我們在這裡喘口氣,因為這個計數方案是整個事情的關鍵,是理解十六進位制表示顏色的關鍵。但請不要讓它更難理解;我不是在開玩笑,十六進位制,真的真的真的和十進位制工作原理一樣。這些概念是完全相同的;在到達下一位數之前十六進位制只不過是多了幾個可用的數字。

在你繼續之前,一定要理解這個概念。以下是一些十六進位制轉換為十進位制的例子。

  • 1F = 一個十六和十五個一 = 十進位制的 16 + 15 = 31
  • 2B = 兩個十六和十一個一 = 十進位制的 32 + 11 = 43
  • 41 = 四個十六和一個一 = 十進位制的 64 + 1 = 65
  • AA = 十個十六和十個一 = 十進位制的 160 + 10 = 170
  • F0 = 十五個十六和零個一 = 十進位制的 240 + 0 = 240

看,一旦你掌握了竅門就很容易了。這只是數學。只不過是使用字母來表示數字。

因此,三個兩位數的十六進位制數字,從 00(0)到 FF(255),將在 CSS 顏色屬性值中表示紅色、藍色和綠色的程度。

直觀性

現在我們明白如何將基色混合和如何指定的每一個顏色的程度,應該明確的是,我們可以在整整六個十六進位制數字產生任何顏色程式碼,從 #000000#FFFFFF,前面兩位表示紅色,中間兩位表示綠色,最後兩位表示藍色 - 始終是 RGB 這個順序。

我們可以用六個十六進位制數字編碼多少種顏色?嗯,這 FFFFFF 是十進位制的 16777216 ,所以正確答案是“一堆”。

當我們指定 CSS 進位制顏色程式碼之前,我們以“#”,稱為英鎊符號井號。CSS 就是這樣知道下面是一個十六進位制的顏色程式碼。另外,字母大小寫不要緊,CSS 中 #a94cb3#a94cb3 是相同的。

瞭解這些之後,一些顏色程式碼你就應該知道怎樣表達了,像黑色、白色和三基色。

十六進位制的黑色、白色和三基色
十六進位制的黑色、白色和三基色

這很簡單,對吧?這是光的物理原理:在這些顏色程式碼中,每個 RGB 分量要麼是“零”(00),要麼是“全部”(FF)。所以,例如,#000000 表示黑色。看這些零;沒有紅色,沒有綠色,沒有藍色 - 沒有光源 - 沒有光不就是黑色嗎?(如果你說“暗的”,你被解僱了。)同樣,#FF0000 代表紅色。該程式碼指定完全紅色,沒有綠色,也沒有藍色。只有紅色的光。只代表紅色。沒有其他的可能,必須是紅色,正紅。

不管你信不信,我們接著往下看,因為一旦你掌握了這個想法,其他顏色也開始變得直觀了。現在你應該將十六進位制程式碼看做的顏色,因為他們就是顏色。

考慮三基色,洋紅(全紅色,沒有綠色,沒有藍色)青色(沒有紅色,全綠色,全藍色),黃色(可直觀的全紅色,全綠色,沒有藍色)。建立這些顏色的十六進位制程式碼現在應該是顯而易見的。

十六進位制顏色值
十六進位制顏色值

好的,到目前為止,我們仍然只使用“沒有”或“全部”值。但回想十六進位制的 80(“數字八和數字零”)是 00 和 FF 的中間,所以我們現在應該能夠使用這個值,方便地構建一些半光的顏色程式碼 —— 即程式碼建立深色調的初級和中級的顏色。嗯,我想知道那些會是什麼樣子的?可能像這樣。

十六進位制初級和中級半色調
十六進位制初級和中級半色調

我們在這裡做的,通過改變三個分量的值,僅僅是改變了光的數量,我們把程式碼放入每種顏色的程式碼中,從沒有(00) 到一半(80) 到全部(FF),這個事實使我們有點頓悟。好吧,一個巨大的巨大的巨大的巨大的頓悟。實際上兩個。

更高的數字 = 更多的光線 = 接近白色 = 明亮的顏色。

較低的數字 = 較少的光線 = 接近黑色 = 較暗的顏色。

這些真的很重要,請再讀一遍。

小測驗

讓我們來做一些使用程式碼表示顏色的小測試,來吧,這將是很有趣的!用純文字回答這些問題(不是十六進位制程式碼),然後向下輪動一點來顯示答案。

問題 1. 如果 #FF00FF 是亮紅色並且 #800080 是暗紅色,那麼 #B000B0 是什麼呢?

問題 2. 如果 #00FFFF 是亮青色並且 #008080 是暗青色(也被稱為綠色),那麼 #004040 是什麼呢?

問題 3. 如果 #000000 是黑色並且 #ffffff 是白色的,那麼 #010101#323232 代表什麼顏色的範圍呢?

…向下滾動

…接著向下

…繼續

…再向下滾動一點

…馬上就到了

答案 1: #B000B0 是中等亮度的 亮紅和暗紅色之間的地方,因為 B0 小於 FF 但超過 80。

答案 2: #004040 比暗青色暗的顏色,因為 40 小於 FF 和 80。

答案 3: #010101#323232五十種深淺不同的灰色,因為十六進位制的 32 等於十進位制的 50:3 16 + 2 1 = 50。

事實上,最後一個的問題使我們頓悟了一個更多並且細微,雖然不是特別偉大但又是非常重要的道理:

當所有三個色值相同時,不管值是多少,顏色都是灰色的

確實是這樣的,#232323#a9a9a9#4b4b4b#2f2f2f#959595#dadada 和所有其他具有相同的 RGB 值的組合都是灰色 —— 有些更暗一些,一些更亮一些。而且,因為十六進位制的 80 是 00 和 FF 的中間值,這意味著 #808080 是所有灰色的中間色。是的,“灰色”包括黑色 #000000 和白色 #ffffff;這意味著,真的有 256 種的灰色。

實際的例子

讓我們來靠近一些實際的 CSS 顏色編碼的示例。基於你對十六進位制和顏色的新知識,你應該能夠理解為什麼這些十六進位制的顏色值可以表示他們想要表達的顏色。看看這些 CSS 規則中的程式碼並且想一下這三對十六進位制的數字表示什麼顏色,你應該立刻能夠回答上來。

例 1:在這裡,文字的前景色設定為深藍色並且背景色設定為偏淺一點的中灰色。

例 1
例 1

例 2:在這裡,任何帶有類名為“warning”的元素將設定為黃色背景紅色文字(注意,根據上述規則,背景仍為灰色,假設這些都在同一個頁面中。

例 2
例 2

例 3:在這裡,正常的連結顯示為藍綠色的文字,而在懸浮樣式設定為白色文字藍綠色背景。(仍然在灰色頁面背景下。)

例 3
例 3

例 4:最後,這個塊的背景為淺棕色(淡黃色),一個棕色的邊框,和深褐色的文字。(都在相同的灰色頁面背景下。)

例 4
例 4

簡寫

我要說的是你可以將十六進位制的六位 CSS 顏色值簡寫是為三位,但是請不要這樣,這對平面設設計師不利。

首先,縮寫通常會導致意外的顏色。只有當一個顏色值的兩個十六進位制數字相同,如 FF,88,或 22 時,縮寫才是準確的。例如,#fff#ffffff 相同,#d09#dd0099 是一樣的。但是如果原始顏色的十六進位制數字就不相同,那麼縮寫的程式碼只會“看起來像”原始顏色,也就是說和原始顏色很接近,但是又不完全相同。例如:#080#008800 一樣,但是肯定和 #008000一樣的,#a4d#aa44dd 是相同的,和 #a040d0不同的

其次,即使是正確使用縮寫,它也很少被一致地使用,在全域性搜尋中就可能出問題或者是無用的。如果你的 CSS 程式碼中使用 #4be 而其他人使用 #44bbee,稍後找到你需要你改變這個顏色,這就會產生匹配的問題。即使是簡單的程式碼 #000#000000 也不榮易進行匹配和替換。

第三,顏色值的縮寫僅僅能減少三個位元組,這弊大於利。

總結

讓我們來總結一下。這裡要明確一點的是,十六進位制並不難,和十進位制不同的只是多了幾個數字。你要記住你要處理的資料是的十進位制表示是 0-255,但是寫成十六進位制的兩位數表示就是 00-FF。一旦你接受了十六進位制的基數是 16,你將會發現它與是基數為 10 的十進位制原理是一樣的。十六進位制的顏色程式碼將表現的更為直觀。

有些人明白了,但有些人還是不明白
有些人明白了,但有些人還是不明白

記住,它總是三對十六進位制數字,總是以紅-綠-藍的順序排列,更高的數字總是意味著更加明亮的顏色(反之亦然)。

現在花一點時間將你的手臂在你身後,拍拍自己的背,放鬆一下。你現在知道一些你的 98% 的同伴都不瞭解的知識!

參考文獻

色彩部分

十六進位制部分

工具

整合工具

整合工具通常允許您選擇一個顏色並檢視其程式碼,或者輸入程式碼來顯示顏色,例如谷歌瀏覽器的開發者工具有一個整合的顏色選擇器,Mac 的 Sublime Text 也有一個顏色選擇器的外掛

其他

感謝!

謝謝你閱讀這篇文章,我希望你在這一過程中獲得了樂趣並學到了一些東西!評論或問題?可以在 dave@davegash.com 中聯絡作者,Dave Gash。


掘金翻譯計劃 是一個翻譯優質網際網路技術文章的社群,文章來源為 掘金 上的英文分享文章。內容覆蓋 AndroidiOSReact前端後端產品設計 等領域,想要檢視更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章