若是下面這段代碼,在瀏覽器中打開。最終的頁面顏色是什麼?css
<html> <body> <h1>Hello World</h1> </body> </html>
你可能意識到這個是陷阱問題,大部分同窗會說是白色,但頁面其實並非白色的: 它是透明的。這是由於瀏覽器的底色是白色的,咱們透過了頁面的透明色,看到了瀏覽器的底色而已。html
若是咱們但願有一個黃色背景的頁面,咱們能夠在 body 上添加一個背景色:前端
body { background-color: yellow; }
咱們看到的整個頁面背景都是黃色,確定有同窗會認爲:這是因爲 body 填充了整個視圖窗口。算法
但這不是真的,若是咱們在 body 上添加一個邊框:canvas
body { background-color: yellow; border: 3px dashed black; }
您能夠看到,其實 body 只包裹了 Hello World 內容區域。瀏覽器
爲何整個頁面都是黃色的?
咱們來看看 w3c:fetch
根元素的背景將成爲 canvas 的背景,其背景繪製區域擴展到覆蓋整個 canvas。
大白話解釋一下:若是你在 body 上設置一個背景。瀏覽器將使用這個背景做爲 canvas 的背景。spa
問題又來了,什麼是 canvas ?日誌
canvas 是瀏覽器在渲染頁面時,生成的畫布,頁面上的全部內容都會在畫布上進行渲染。
這個 canvas 是至關大的。code
儘管 canvas 是瀏覽器中一個很是重要的部分,但相關的資料卻很是少。正如咱們看到的,canvas 基於 body,爲整個視區(viewport)提供了一個背景。
有很長一段時間,我認爲 canvas 就是 body,可是 canvas 只是使用了 body 的信息,canvas 自己可比 body 大得多。
有趣的是,即便咱們將 body 設置爲黃色,實際上 body 真實的顏色仍然是透明的。 正如 w3c 所言:
當根元素的背景成爲 canvas 的背景後,瀏覽器將不會再繪製根元素的背景,根元素的背景實際值是透明的。
對於瀏覽器來講,繪製與 canvas 顏色相同的 body 是沒有意義的,這也是它透明的緣由。
換句話說:當您在 body 上設置背景色時,您其實是在設置 canvas 背景。 canvas 從 body 上「偷走」了背景色。
其實影響 canvas 的元素不僅 body,還有 html,咱們來依次分析一下。
先來看看什麼是 body 元素?
根據 w3c 的說法,body 是展現內容的地方,包括:文本、圖像、顏色、圖形等。
若是 body 用來展現內容,那麼 body 以外的東西就不能展現內容。
因此你們是否會有這樣一個疑問:在 html 元素上設置一個背景色不會有任何效果,由於它不是內容的一部分?
咱們仔細想想: 下面這個頁面會顯示成什麼樣子?
html { background-color: green; } body { background-color: yellow; }
如今頁面的顏色是什麼?是黃色仍是綠色?仍是二者都有?
答案是:二者都有。
當前頁面上咱們能看到什麼?
錯!咱們又一次被愚弄了。
讓咱們給 html 元素添加邊框,看看會發生什麼:
因此實際上,html 的行爲就像 body 同樣:它的大小也是根據頁面內容動態渲染的。
爲何當前整個頁面都是綠色呢?
W3c 給出了一樣的答案:
- 根元素的背景將成爲 canvas 的背景。
- W3c 中指的根元素能夠是 body 或者 html。
因此,與第一個示例同樣,html 真正的顏色是透明的,它的綠色被 canvas 「偷走」了。
咱們如今有了瀏覽器用來選擇 canvas 顏色的完整算法:
if (html 存在背景顏色) { // 使用 html 的背景顏色,做爲 canvas 的背景 } else if (body 存在背景顏色) { // 使用 body 的背景顏色,做爲 canvas 的背景 } else { // 使用 canvas 的默認透明顏色 }
好吧,我想這個謎團解開了。 你能夠認爲 w3c 這樣作是至關聰明的,咱們不用給根元素設置明確的尺寸,就能讓根元素的背景色填充整個視口。
理解白色和透明之間的區別,是解決一些 css 之謎的關鍵。
讓咱們玩一玩 css 中的在混合模式 mix-blend-mode
。 這個 css 屬性容許咱們定義一個元素應該如何與它的父元素混合。 有時被稱爲「瀏覽器中的 Photoshop」。 無論有沒有誇大,這個屬性都是很是厲害的。
咱們從一個簡單的示例開始:
h1 { color: green; mix-blend-mode: difference; }
上面的實例表示,咱們經過 mix-blend-mode
去改變原本爲綠色的 h1 標題, mix-blend-mode: difference
意味着將文本的顏色改變成:原始顏色(綠色)與背景顏色之間的混合色值。
between(綠色 + 白色)= 粉紅色,因此但願咱們的標題是粉紅色。
但事實證實,它不是粉紅色的。
若是背景色是白色的話,混合出來的顏色就是粉紅色的,但它不是,證實當前的背景色並非白色,事實上是透明色。
between(綠色 + 透明)= 綠色,所以標題的顏色沒有變化。
讓咱們回顧一下:
因此咱們的 h1 沒有什麼能夠混合的。
解決方法很簡單:只須要在 body 上添加一個背景色便可!
body { background-color: white; }
它如今起做用了!
讓咱們再來理一理:
因此咱們的綠色標題與 canvas 融合,變成粉紅色。 這個標題固然能夠是一張圖片,一段視頻,任何東西。
咱們的話題即將結束,但還有最後一個問題。。。
到目前爲止,咱們理想中的頁面層級(從上到下)是這樣的:
根據咱們所學到的,若是 body 和 html 是透明的,那麼畫布也是透明的。
可是最底層的 canvas 怎麼多是透明的呢? 若是是這樣的話,咱們能夠經過瀏覽器看到桌面和其餘窗口!
聽我說完,若是在下面還有另外一層,其實是白色的呢?
w3c 再次給出了答案:
若是 canvas 背景是透明的,那麼所顯示的背景是依賴於用戶界面(UA-dependent)
用大白話說:在 canvas 後面還有一個用戶界面,若是 canvas 是透明的,你能夠看到它。你看到什麼取決於瀏覽器。
目前我見過的全部瀏覽器中,用戶界面底層都是白色的。
有什麼辦法能夠真正看出白色和透明 canvas 之間的區別? 讓咱們能證實 canvas 默認是透明的嗎?
讓咱們回到一個很是簡單的 css:
html, body { border: 3px dashed black; }
咱們的頁面是這樣的:
讓咱們用 iframe 標籤把這個頁面包含在另外一個頁面中:
<iframe src="..." width="100%" height="300px"></iframe>
如下是咱們獲得的結果:
因此,問題是: iframe 是有一個透明的仍是白色的 canvas?
咱們能夠經過在父頁面上設置背景色來回答這個問題。
body { background-color: lightblue; }
如您所見,iframe 的 canvas 是透明的,咱們能夠透過它看到父頁面。
它真的能證實 canvas 是透明的嗎? 也許 iframe 就是沒有 canvas?
這是一個很好的問題,爲了回答這個問題,讓咱們在 iframe 的 body 標籤上加上一個白色背景:
body { background-color: white; }
如下是咱們獲得的結果:
若是 iframe 沒有 canvas,那麼它 body 外部的區域就不會被填充。 可是因爲 canvas 機制,body 的背景顏色能夠用來覆蓋整個 iframe 視區。
這就是爲何咱們能夠在任何頁面上看到,默認的畫布不是白色的,而是透明的。
因此當你打開一個空白頁面時,你看到的不是一個白色的畫布。 它只是瀏覽器的「底部」 ,是瀏覽器這個軟件的背景色。
所以,咱們獲得的瀏覽器最終的層級是這樣的(從上到下):
用一張三維圖來看一下:
咱們經過幾段 css 代碼,咱們發現了瀏覽器存在一個繪圖區 canvas,這個繪圖區是很是大的,這個繪圖區會受頁面根元素的影響:
繪圖區域的顏色計算:
最後,若是你對此有任何想法,歡迎留言評論!