深挖顯示屬性:顯示的兩個值

已發表: 2022-03-10
快速總結↬我們經常談論 Flexbox 和 CSS 網格佈局,但這些佈局方法本質上是 CSS display屬性的值,是一個沒有引起太多關注的屬性的主力。 雷切爾安德魯在一個短系列中得到了更好的表現。

flex 或 grid 佈局從您聲明display: flexdisplay: grid開始。 這些佈局方法是 CSS display屬性的值。 我們傾向於不單獨談論這個屬性,而是專注於flexgrid的值,但是,有一些有趣的事情需要了解display以及它是如何定義的,這將使您在使用時更輕鬆用於佈局的 CSS。

在這篇文章中,這是一個簡短系列的第一篇,我將看一下在 3 級規範中定義display值的方式。 這是我們在早期版本的 CSS 中定義display的方式的改變。 雖然對於我們這些從事 CSS 多年的人來說,起初這可能看起來很不尋常,但我認為這些更改確實有助於解釋當我們更改元素的display值時發生了什麼。

塊和內聯元素

我們教給剛接觸 CSS 的人的第一件事就是塊元素和內聯元素的概念。 我們將解釋頁面上的某些元素是display: block ,因此它們具有某些功能。 它們沿內聯方向延伸,佔用了它們可用的盡可能多的空間。 他們打破了一條新路線; 我們可以給它們設置寬度、高度、邊距以及內邊距,這些屬性會將頁面上的其他元素推離它們。

我們也知道有些元素是display: inline 。 內聯元素就像句子中的單詞; 它們不會換行,而是在它們之間保留一個空白字符。 如果您添加邊距和填充,這將顯示但不會推開其他元素。

塊和內聯元素的行為是 CSS 的基礎,正確標記的 HTML 文檔默認是可讀的。 這種佈局被稱為“塊和內聯佈局”或“正常流”,因為如果我們不對元素做任何其他事情,這就是元素自己佈局的方式。

跳躍後更多! 繼續往下看↓

display的內在價值和外在價值

我們了解塊元素和內聯元素,但是如果我們讓項目display: grid會發生什麼? 這是完全不同的東西嗎? 如果我們查看指定了display: grid的組件,就佈局中的父元素而言,它的行為類似於block level元素。 元素將伸展並在內聯維度中佔用盡可能多的空間,它將從新行開始。 就其與佈局其餘部分的行為方式而言,它的行為就像一個block元素。 我們還沒有說display: block雖然,還是我們說的?

事實證明,我們有。 在 Display 規範的 Level 3 中, display的值被定義為兩個關鍵字。 這些關鍵字定義了 display 的外部值,它將是inlineblock ,因此定義了元素在佈局中與其他元素一起的行為方式。 它們還定義了元素的內部值——或者該元素的直接子元素的行為方式。

這意味著當你說display: grid時,你真正說的是display: block grid 。 您要求的是塊級網格容器。 一個擁有所有塊屬性的元素——你可以給它高度和寬度、邊距和內邊距,它會拉伸以填充容器。 但是,該容器的子項已被賦予grid的內部值,因此它們成為網格項。 這些網格項的行為在 CSS 網格規範中定義: display規範為我們提供了一種方法來告訴瀏覽器這是我們想要使用的佈局方法。

我認為這種對display的思考方式非常有用。 它直接解釋了我們使用各種佈局方法所做的事情。 如果您要指定display: inline flex ,您會期望什麼? 希望是一個充當內聯元素的盒子,其子元素是彈性項目。

通過以這種新方式思考display ,還有一些其他的事情得到了很好的解釋,我將在本文的其餘部分介紹其中的一些內容。

我們總是回到正常流程

在考慮這些內部和外部顯示屬性時,考慮一下如果我們根本不處理 display 的值會發生什麼會很有幫助。 如果你編寫一些 HTML 並在瀏覽器中查看它,你得到的是塊和內聯佈局,或正常流。 元素顯示為blockinline元素。

請參閱 Rachel Andrew 的 Pen Block 和 Inline Layout。

請參閱 Rachel Andrew 的 Pen Block 和 Inline Layout。

下面的示例包含一些標記,我通過使div display: flex (兩個直接子項)現在變成了 flex 項,因此圖像現在與內容排成一行。 但是,如果您在內容中看到,則會再次以正常流程顯示標題和段落。 媒體對象的直接子對像變成了彈性項目; 除非我們更改 flex 項目上的 display 值,否則他們的孩子會恢復正常流程。 flex 容器本身是一個塊框,正如您從邊框延伸到其父級邊緣的事實所看到的那樣。

請參閱 Rachel Andrew 的 Pen Block and Inline Layout With Flex 組件。

請參閱 Rachel Andrew 的 Pen Block and Inline Layout With Flex 組件。

如果您使用此過程,頁面上的元素將使用這種可讀的正常流佈局來佈置自己,而不是與它對抗並嘗試放置所有內容,CSS 會容易得多。 您也不太可能陷入可訪問性問題,因為您正在處理文檔順序,這正是屏幕閱讀器或瀏覽文檔的人正在做的事情。

解釋flow-rootinline-block

inline-block的價值對於我們很多從事 CSS 一段時間的人來說可能也很熟悉。 此值是一種獲取inline元素上的某些塊行為的方法。 例如, inline-block元素可以具有寬度和高度。 帶有display: inline-block的元素也以一種有趣的方式表現,因為它創建了一個B鎖定格式內容( BFC )。

BFC 在佈局方面做了一些有用的事情,例如,它包含浮動。 要更詳細地了解塊格式化上下文,請參閱我之前的文章“理解 CSS 佈局和塊格式化上下文”。 因此說display: inline-block給你一個內聯框,它也建立了一個 BFC。

正如您將發現的(如果您閱讀了上面提到的關於塊格式化上下文的文章),還有一個更新的 display 值,它也顯式地創建了一個 BFC。 這是flow-root的值。 此值在塊上創建 BFC,而不是內聯元素。

  • display: inline-block為您提供了一個在線框上的 BFC。
  • display: flow-root給你一個塊框上的 BFC。

您現在可能認為這有點令人困惑:為什麼我們在這裡有兩個完全不同的關鍵字,以及我們之前討論的雙值語法發生了什麼? 這巧妙地引出了我需要解釋的關於display的下一件事,即 CSS 有我們需要根據display屬性處理的歷史這一事實。

顯示的傳統價值

CSS2 規範詳細說明了display屬性的以下值:

  • inline
  • block
  • inline-block
  • list-item
  • none
  • table
  • inline-table

還定義了各種表格內部屬性,例如本文未涉及的table-cell

然後我們在這些值中添加了一些用於顯示的值,以支持 flex 和 grid 佈局:

  • grid
  • inline-grid
  • flex
  • inline-flex

注意該規範還定義了ruby​​ 和inline-ruby以支持 Ruby 文本,您可以在 Ruby 規範中閱讀。

這些都是display屬性的單個值,在規範更新之前定義,以這種方式解釋 CSS 佈局。 CSS 非常重要的一點是我們不會到處破壞網絡。 我們不能簡單地改變事情。 我們不能突然決定每個人都應該使用這種新的雙值語法,因此每個使用單值語法構建的網站都會崩潰,除非開發人員回去修復它!

在考慮這個問題時,您可能會喜歡這個 CSS 設計中的錯誤列表,這些錯誤在許多情況下更少,因為設計時沒有水晶球可以預見未來! 然而,事實是我們不能破壞網絡,這就是為什麼我們會出現這種情況,現在瀏覽器支持一組單一的顯示值,並且規范正在轉向兩個顯示值。

我們解決這個問題的方法是指定顯示的舊值和短值,其中包括所有這些單個值。 這意味著可以在單個值和新的兩個關鍵字值之間定義映射。 這為我們提供了下表的值:

單值兩個關鍵字值描述
block block flow 帶正常流動內部的塊箱
flow-root block flow-root 定義 BFC 的塊框
inline inline flow 內嵌正常流量的內聯盒
inline-block inline flow-root 定義 BFC 的內聯框
list-item block flow list-item 帶有正常流量內部和附加標記框的塊框
flex block flex 具有內部 flex 佈局的塊框
inline-flex inline flex 具有內部 flex 佈局的內聯框
grid block grid 具有內部網格佈局的塊框
inline-grid inline grid 具有內部網格佈局的內聯框
table block table 具有內表佈局的塊框
inline-table inline table 具有內表佈局的內聯框

為了解釋這是如何工作的,我們可以考慮一個網格容器。 在二值世界中,我們將創建一個塊級網格容器,其中包含:

 .container { display: block grid; }

但是, legacy 關鍵字意味著以下內容執行相同的操作:

 .container { display: grid; }

相反,如果我們想要一個內聯網格容器,在二值世界中,我們將使用:

 .container { display: inline grid; }

如果使用舊值:

 .container { display: inline-grid; }

我們現在可以回到對話開始的地方並查看display: inline-block 。 查看表格,您可以看到這在二值世界中被定義為display: inline flow-root 。 它現在匹配display: flow-root在雙值世界中將是display: block flow-root 。 稍微整理和澄清這些東西是如何定義的。 如果您願意,可以對 CSS 進行重構。

瀏覽器對二值語法的支持

到目前為止,瀏覽器還不支持display屬性的二值語法。 可以在此處找到 Firefox 的實現錯誤。 實現——當它發生時——本質上將涉及將遺留值別名為雙值版本。 因此,在您可以在代碼中實際使用這些雙值版本之前,可能還需要一段時間。 然而,這真的不是本文的重點。 相反,我認為根據二值模型查看 display 的值有助於解釋發生的大部分情況。

當你在 CSS 中定義一個盒子的佈局時,你是在定義這個盒子會發生什麼,即它相對於佈局中所有其他盒子的行為方式。 您還定義了該框的項的行為方式。 在將值顯式聲明為兩個獨立的事物之前,您可以以這種方式思考,因為遺留關鍵字映射到這些值,它將幫助您了解更改display的值時會發生什麼。