網格、邏輯值和書寫模式
CSS 網格佈局最重要的特性之一,是在規範中內建了對不同書寫模式的支援。在本指南中,我們將瞭解 CSS 網格佈局的這一特性以及其他現代佈局方法,並在此過程中學習一些關於書寫模式以及邏輯與物理屬性的知識。
邏輯與物理屬性和值
CSS 中充滿了物理定位屬性和關鍵字——left 和 right、top 和 bottom。在下面的程式碼片段中,我們使用絕對定位來定位一個專案,並使用物理 inset 屬性作為偏移值來推動該專案。該專案被放置在距離容器頂部 20 畫素、距離左側 30 畫素的位置。
.container {
position: relative;
}
.item {
position: absolute;
top: 20px;
left: 30px;
}
<div class="container">
<div class="item">Item</div>
</div>
這個例子使用了 left 和 right 屬性;這只是 CSS 中眾多物理屬性中的兩個。我們還可以使用物理屬性新增外邊距、內邊距和邊框,例如 margin-left 和 padding-left。你可能還會看到物理關鍵字的使用,例如使用 text-align: right 將文字向右對齊。
我們稱這些關鍵字和屬性為物理的,因為它們與你正在看的螢幕有關。無論你的文字方向如何,左邊永遠是左邊。
物理屬性的問題
在開發一個需要支援多種語言(包括文字從右向左或從上到下流動的語言)的網站時,物理屬性可能會導致問題。瀏覽器被設計為能夠正確顯示內容,而無論語言如何。一些 CSS 特性可能會覆蓋瀏覽器的預設設定,導致內容顯示效果不佳。
在這個例子中,direction 屬性被設定為 rtl,這將英語文件的預設書寫模式從 ltr 切換了。我們有兩個段落。由於在祖先元素(<body>)上設定了 direction 值,這兩個段落都應該從右向左流動。第一個段落將 text-align 設定為 left,因此它與其容器的左側對齊。第二個段落與右側對齊,並從右向左流動。
body {
direction: rtl;
}
.left {
text-align: left;
}
這是一個基本演示,說明了在 CSS 中使用物理值和屬性可能出現的問題。如果我們使用物理屬性和關鍵字來編寫 CSS,我們就告訴了瀏覽器我們對文字流動方式的假設,並阻止了它處理其他書寫模式。
邏輯屬性和值
邏輯屬性和值不假定文字方向。這就是為什麼我們在 CSS 網格佈局中使用關鍵字 start 來將某個東西與容器的起始位置對齊。在處理英語內容時,start 將在左側,然而,它不一定非得如此。start 這個詞沒有暗示任何物理位置,這使得網站在使用從右到左的語言(如阿拉伯語)時,可以將內容從右側開始。
塊級與行內
當使用邏輯屬性而不是物理屬性時,我們不再將世界看作是從左到右、從上到下的。我們有一個不同的參考點。這就是理解在網格對齊指南中介紹的塊級和行內軸變得非常有用的地方。如果你從塊級和行內的角度來思考佈局,CSS 網格佈局的工作方式就非常有道理了。

CSS 書寫模式
CSS 書寫模式模組規定了書寫模式在 CSS 中的工作方式。這些功能不僅用於支援與英語書寫模式不同的語言,還可以用於創意目的。本節中的示例利用 writing-mode 屬性來更改應用於我們網格的書寫模式,並在此過程中演示了邏輯值的工作原理。
writing-mode
書寫模式不僅僅是從左到右和從右到左的文字,writing-mode 屬性可以幫助我們顯示以其他方向排列的文字。writing-mode 屬性可以有以下值:
horizontal-tbvertical-rlvertical-lrsideways-rlsideways-lr
值 horizontal-tb,代表“水平,從上到下”,是 Web 文字的預設值。它就是你正在閱讀本指南的方向。其他值會改變文字在文件中的流動方式,以匹配世界各地不同的書寫模式。
舉個例子,下面我們有兩個段落。第一個使用預設的 horizontal-tb 值,第二個使用 vertical-rl。在第二種書寫模式中,文字仍然是從左到右書寫,但文字的方向是垂直的——行內文字現在是沿著頁面向下,從上到下排列。
<div class="wrapper">
<p class="horizontal-tb">
I have writing mode set to the default <code>horizontal-tb</code>
</p>
<p class="vertical-rl">I have writing mode set to <code>vertical-rl</code></p>
</div>
.horizontal-tb {
writing-mode: horizontal-tb;
}
.vertical-rl {
writing-mode: vertical-rl;
}
網格佈局中的書寫模式
將這一點應用到網格佈局示例中,我們可以看到改變書寫模式意味著改變我們對塊級軸和行內軸位置的看法。
預設書寫模式
在這個例子中,網格有三列和兩行軌道。這意味著有三個軌道沿著塊級軸向下延伸。在預設書寫模式下,網格會自動從左上角開始放置專案,向右移動,填滿行內軸上的三個單元格。然後它會移動到下一行,建立一個新的行軌道,並填入更多的專案。
.wrapper {
display: grid;
grid-template-columns: repeat(3, 100px);
grid-template-rows: repeat(2, 100px);
gap: 10px;
}
<div class="wrapper">
<div class="item1">Item 1</div>
<div class="item2">Item 2</div>
<div class="item3">Item 3</div>
<div class="item4">Item 4</div>
<div class="item5">Item 5</div>
</div>
設定書寫模式
如果在上一個例子中,我們給網格容器新增 writing-mode: vertical-lr,我們可以看到塊級軸和行內軸現在執行在不同的方向。塊級軸或列軸現在從左到右橫跨頁面,而行內軸則沿著頁面向下,從上到下建立行。
.wrapper {
writing-mode: vertical-lr;
}
對齊的邏輯值
隨著塊級軸和行內軸能夠改變方向,對齊屬性的邏輯值開始變得更有意義了。
在這個例子中,我們使用對齊(align-self 和 justify-self 屬性)來對齊一個設定為 writing-mode: vertical-lr 的網格內部的專案。start 和 end 屬性的工作方式與它們在預設書寫模式中的工作方式完全相同,並且保持了邏輯性,這是使用 left 和 right、top 和 bottom 來對齊專案所做不到的。一旦我們像這樣將網格翻轉到側面,就會發生這種情況。
.wrapper {
writing-mode: vertical-lr;
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 100px);
gap: 10px;
}
.item1 {
grid-column: 1 / 4;
align-self: start;
}
.item2 {
grid-column: 1 / 3;
grid-row: 2 / 4;
align-self: start;
}
.item3 {
grid-column: 3;
grid-row: 2 / 4;
align-self: end;
justify-self: end;
}
<div class="wrapper">
<div class="item1">Item 1</div>
<div class="item2">Item 2</div>
<div class="item3">Item 3</div>
</div>
如果你想看看這些是如何工作的,包括從右到左以及從上到下的書寫模式,可以將 vertical-lr 切換為 vertical-rl,這是一種從右到左執行的垂直書寫模式。
自動放置與書寫模式
正如我們在前面的例子中所看到的,書寫模式可以改變專案在網格上放置的視覺方向。預設情況下,專案會沿著行內軸放置自己,並在塊級方向上新增新的行。我們現在已經看到,行內軸並不總是從左到右,塊級軸也不總是從上到下。
基於網格線的放置與書寫模式
當按行號放置專案時,要記住的關鍵是,無論你處於哪種書寫模式,第 1 行都是起始線,第 -1 行都是結束線。
從左到右文字的基於網格線的放置
在這個例子中,我們有一個按預設 ltr 方向佈局的網格,其中有三個專案使用基於網格線的放置方式進行定位。
- 專案 1 從列網格線 1 開始,跨越一個軌道。
- 專案 2 從列網格線 -1 開始,跨越到 -3。
- 專案 3 從列網格線 1 開始,跨越到列網格線 3。
.wrapper {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(2, 100px);
gap: 10px;
}
.item1 {
grid-column: 1;
}
.item2 {
grid-column: -1 / -3;
}
.item3 {
grid-column: 1 / 3;
grid-row: 2;
}
<div class="wrapper">
<div class="item1">Item 1</div>
<div class="item2">Item 2</div>
<div class="item3">Item 3</div>
</div>
從右到左文字的基於網格線的放置
如果我們在上一個例子的網格容器中新增 direction 屬性,值為 rtl,那麼第 1 行就會被放置在網格的右側,而第 -1 行則在左側。
.wrapper {
direction: rtl;
}
如果你正在切換文字的方向,無論是整個頁面還是部分頁面,並且正在使用網格線,你可能需要為你的網格線命名,以避免佈局完全改變方向。對於某些情況,例如網格包含文字內容時,這種切換可能正是你想要的。但對於其他用途,可能並非如此。
grid-area 屬性中奇怪的值順序
你可以使用 grid-area 屬性將網格區域的所有四條線指定為一個值。當人們第一次遇到這個屬性時,他們常常驚訝於這些值的順序與 margin 的簡寫順序不同——後者是順時針的:上、右、下、左。
grid-area 值的順序是:
grid-row-startgrid-column-startgrid-row-endgrid-column-end
對於英語,從左到右意味著順序是:
topleftbottomright
這是逆時針的!這與我們對外邊距和內邊距的做法相反。如果我們記住 grid-area 將世界看作是“塊級和行內”,你會注意到我們正在設定兩個起始邊,然後是兩個結束邊,一旦你知道了這一點,這就變得更加合乎邏輯了!
混合書寫模式與網格佈局
除了為文件使用正確的語言書寫模式外,書寫模式還可以在其他方面為 ltr 文件帶來創意。在這個例子中,我們有一個網格佈局,一側有一組連結。我們使用書寫模式(writing-mode: vertical-lr)將它們在列軌道中側向旋轉。
.wrapper {
display: grid;
grid-gap: 20px;
grid-template-columns: 1fr auto;
font:
1em "Helvetica",
"Arial",
sans-serif;
}
nav {
writing-mode: vertical-lr;
}
nav ul {
list-style: none;
margin: 0;
padding: 1em;
display: flex;
justify-content: space-between;
}
nav a {
text-decoration: none;
}
<div class="wrapper">
<div class="content">
<p>
Turnip greens yarrow ricebean rutabaga endive cauliflower sea lettuce
kohlrabi amaranth water spinach avocado daikon napa cabbage asparagus
winter purslane kale. Celery potato scallion desert raisin horseradish
spinach carrot soko. Lotus root water spinach fennel kombu maize bamboo
shoot green bean swiss chard seakale pumpkin onion chickpea gram corn pea.
Brussels sprout coriander water chestnut gourd swiss chard wakame kohlrabi
beetroot carrot watercress. Corn amaranth salsify bunya nuts nori azuki
bean chickweed potato bell pepper artichoke.
</p>
<p>
Nori grape silver beet broccoli kombu beet greens fava bean potato
quandong celery. Bunya nuts black-eyed pea prairie turnip leek lentil
turnip greens parsnip. Sea lettuce water chestnut eggplant winter purslane
fennel azuki bean earthnut pea sierra leone bologi leek soko chicory
celtuce parsley jícama salsify.
</p>
</div>
<nav>
<ul>
<li><a href="">Link 1</a></li>
<li><a href="">Link 2</a></li>
<li><a href="">Link 3</a></li>
</ul>
</nav>
</div>
物理值和邏輯屬性
如果將邏輯網格屬性與物理屬性結合使用,請記住物理屬性不會根據書寫模式而改變。在我們的在 CSS 網格佈局中對齊專案指南中,我們使用自動外邊距將一個專案推離其他專案;這使用了物理屬性。大多數物理屬性都有邏輯屬性的等價物,它們以與網格放置和對齊屬性及值相同的方式遵循書寫模式。
同樣,當在網格區域內使用絕對定位時,你可以使用邏輯 inset 屬性將專案放置在網格區域內。當混合使用邏輯和物理屬性或值時,要注意它們之間的衝突。例如,你可能需要更改 CSS 以應對從 ltr 到 rtl 的切換。你透過網格對塊級和行內的理解將幫助你理解 CSS 邏輯屬性和值。