New CSS Logical Properties! - The Next Step of CSS Evolution

原文連接:https://medium.com/@elad/new-...
原文做者:Elad Shechtercss

簡介

在過去,大多數程序猿在思考佈局時老是習慣於從「上下左右」的角度出發。這是由於在早期,互聯網主要用於上傳文檔,而不是爲了實現咱們如今熟知的複雜網站架構。html

這也是爲何沒有人思考多語言網站的需求。git

目前爲止,支持相似 RTL/LTR 這種多方向網站的最佳方式,依然是使用 SASSSASS 變量。
(若是你但願瞭解更多內容,能夠閱讀個人另外一篇文章《The Best Way to RTL Websites with SASS!》)。github

這些新的邏輯屬性讓咱們可以在改動最少樣式的狀況下控制咱們的網站,而不用擔憂網站使用的是何種語言(不管是英語、阿拉伯語、日語仍是其餘語言)。web

如今讓咱們開始吧!瀏覽器

思考 CSS 邏輯屬性的方式

當咱們討論盒模型時,咱們已經對下面這張圖很熟悉了:sass


<font color=#999>盒模型物理屬性(舊方案)架構

它在之前和如今一直是正確的,但相似 margin-left, padding-right, border-top 等經典物理特性其實已經時日很少了。佈局

在你開始使用新的邏輯屬性以前,你須要中止從 left/right 或者 top/bottom來思考問題,而是使用 inline-start/inline-endblock-start/block-end 來替代它們。學習


<font color=#999>邏輯屬性(新方案)

Inline axis (譯者理解爲內聯軸,即閱讀方向)

讓咱們用英文做爲例子,英文的閱讀方向是從左到右,這是屬性的內聯部分。當咱們想要把一系列元素排在同一行時,咱們一般會使用 display: inline,照這個思路就很容易記住 inline axis 的含義了。

舉例來講,padding-inline-start 會在當前語句開始位置的旁邊設置一個內邊距:

在英語中:       padding-inline-start = padding-left
在阿拉伯語中:padding-inline-start = padding-right
在日語中:       padding-inline-start = padding-top

Block axis (塊軸)

讓咱們忘掉 top 和 bottom 相關屬性的含義(再也不表示「上下」),而是把 top 當作網站的開始,把 bottom 當作網站的結束。只要想像幾個 display:block 的元素首尾相連,就很容易記住這點了。

到這時你仍然會問本身,難道這不是一向的作法嗎?

這個問題解釋起來有點複雜。由於目前並無其餘解決方案,因此目前全部的網站,不論是使用的是什麼語言,都是這麼處理的。

要知道使用日文或者其餘東方語言的網站(按佈局方向)多是從右到左,而非從上到下的!爲了理解這種網站的表現,咱們能夠想象一下將瀏覽器向右旋轉90度,咱們會發現網站的滾動條再也不是垂直方向了,它變成了水平方向!

舉個例子(block cases):
在英語和阿拉伯語中: padding-block-start = padding-top
在日語中:      padding-block-start = padding-right


<font color=#999>(日文網站)

新的盒模型屬性

(margin, padding and border)

在理解了 inlineblock axis 以後,你就能夠根據須要來使用它們了。

用英文網站舉例來講:

margin
margin-block-start = margin-top
margin-block-end = margin-bottom
margin-inline-start = margin-left
margin-inline-end = margin-left

padding
padding-block-start = padding-top
padding-block-end = padding-bottom
padding-inline-start = padding-left
padding-liline-end = padding-right

border
border-block-start = border-top
border-block-end = border-bottom
border-inline-start = border-left
border-inline-end = border-right

邏輯尺寸

WidthHeightinline-sizeblock-size 所取代。

WidthHeight 屬性一樣須要適應新的尺寸表達方法。一旦咱們理解了 inline/block 方法,就很是容易理解它們的尺寸要如何用新屬性來表示。在英文網站,寬度屬性用 inline-size 表示,高度屬性用 block-size 表示。

舉個栗子(inline/block size):
在英文與阿拉伯語中(LTR/RTL)
width = inline-size
height = block-size

在一個閱讀順序是每行裏自上而下的語言中,好比日語,咱們會看到相反的表達方式:
inline-size = heightblock-size = width

對於 min/max 屬性,只須要把 min/max 書寫在屬性前面:min-inline-size: 300px; max-block-size: 100px;


<font color=#999>新舊盒模型屬性對比

CSS Positions

top/right/bottom/left這些舊的位置屬性已經發展出了一組新的屬性名,它們都帶有 inset 前綴,分別是:
inset-block-start / inset-inline-end / inset-block-end / inset-inline-start

在英文網站中(LTR):
top = inset-block-start
bottom = inset-block-end
left = inset-inline-start
right = inset-inline-end

/* OLD TECHIQUE */
.popup {
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
} 

/* NEW TECHIQUE */
.popup {
    position: fixed;
    inset-block-start: 0;  /*top - in English*/
    inset-block-end: 0;    /*bottom - in English*/
    inset-inline-start: 0; /*left - in English*/
    inset-inline-end: 0;   /*right - in English*/
}

第一眼看到這些代碼,你可能會質疑爲何咱們須要如此複雜的命名?!其實這是有充分理由的。在新的屬性名中,這些屬性依然可使用相似 padding/margin/border 的書寫方式混合起來,而這種新的位置簡寫特性在之前是不存在的(以下所示)。

.popup{
   position:fixed;
   inset:0 0 0 0;   /*top, right, bottom, left - in English*/
}


CSS Floats

Float 很是簡單,它只有2個值 left/right,分別用 inline-start/inline-end 來代替。

在英文網站中(LTR):
float: left = float: inline-start
float: right = float: inline-end

Text-align

它比 floats 更簡單,只須要用 start/end 代替 left/right 便可。

在英文網站中(LTR):
text-align: left = text-align: start
text-align: right = text-align: end

更多

Resize:經常使用於 <textarea>,它的值 horizontal/vertical 升級爲 inline/block 代替。

在英文網站中(LTR):
resize: horizontal = resize: inline
resize: vertical = resize: block

background-position:目前爲止尚未任何瀏覽器中針對該屬性進行過修改,但若是你研究的足夠深刻,你就會在 Mozilla 的 MDN 中找到有關 background-position-inline & background-position-block 的資料。雖然這些文檔還不夠完善,但工做人員已經在進行相關的工做了。

其餘:正如其餘與方向有關的屬性同樣,咱們還能夠預測相似 transform-origin 這樣的屬性也會被更新。

CSS Grid & CSS Flexbox

這兩個特性自己已經使用了新的邏輯屬性方法進行構建,所以若是你以前已經使用了這兩個特性,那麼沒有必要用本文提到的新方法去替代它們。

理解邏輯屬性的工做流程

雖然剛開始看起來很複雜,但其實是很是容易使用的。在寫樣式時,再也不須要考慮跨語言支持的問題。你只須要使用邏輯屬性替代舊的物理屬性,而後讓它們匹配你喜歡的語言便可。

根據語言來應用對齊

當咱們學習了全部新邏輯屬性的更新後,咱們就能夠運用2個特性來分別定義塊軸對齊(block axis alignment)(網站文檔流方向)和內聯軸對齊(文字閱讀方向)。

Writing-mode 屬性(塊軸)

在定義網站文檔流時,大多數時候是從上到下的。但正如上文提到的,特定語言有可能從右到左(日語),甚至從左到右(蒙語)。在這兩種狀況中,咱們就得使用水平滾動條來替代慣用的垂直滾動條。

注意:writing-mode 有3個主要的值:horizontal-tb / vertical-rl / vertical-lr
這3個值的名稱有一點使人困惑。這是由於他們既能夠表示塊軸方向,還能夠表示內聯軸的文字對齊(inline-axis)。這顯然讓人很不爽,由於文字對齊實際上是多餘的,這隻能讓人感到困惑。

爲了消除這個困惑,建議忽略屬性值內表示內聯軸的部分,只關注塊軸部分。

舉例來講:

  • writing-mode: horizontal-tb; = Top to Bottom Flow,英文(默認)
  • writing-mode: vertical-rl; = Right to Left Flow,日語
  • writing-mode: vertical-lr; = Left to Right Flow,蒙語

就我而言,我更傾向於讓屬性值只包括:tb/rl/lr (block-axis part),以此消除潛在的困惑。

日語中 writing-mode 是這麼定義的:

html {
    writing-mode: vertical-rl;
}

Direction property (inline axis) - 方向屬性(內聯軸)

只有在 writing-mode 屬性處於默認的水平模式時,方向屬性纔可以定義文字方向是 left-to-right 仍是 right-to-left。若是咱們將 writing-mode 改成垂直模式中的一種後,文字方向就會發生改變:
left-to-right 會變爲 top-to-bottomright-to-left 會變爲 bottom-to-top

以阿拉伯語爲例:

html {
    direction: rtl;
}

使人驚奇的是,將一個自上而下的網站變爲一個帶有橫向滾動條的自右向左的網站是多麼的容易。

這裏是我寫的一個demo,在 Firefox 中瀏覽最佳(目前爲止 Firefox 支持更多的新屬性)

Live Example (試試選擇其餘語言選項):

瀏覽器支持狀況

  • 除 Edge 外,大部分主流瀏覽器支持全部的盒模型屬性(margin / padding / border)以及新的 width / height (inline-size, block-size) 屬性。
  • 除 Edge 外,大部分主流瀏覽器支持 text-align 的新屬性值。
  • Floats / Positions / Resize 的值或屬性只被 Firefox 所支持。

關於邏輯屬性的相關問題

隨着這些新屬性的誕生,咱們也必須面對隨之而來的新問題。好比,當咱們想用簡寫的方式把全部 margin 屬性寫出來時,像這樣:

margin: 1px 2px 3px 4px;

你是沒法預測它會如何被瀏覽器解析的。

由於若是網站使用的是物理屬性,這些屬性值就會被解析爲:margin-top / margin-right / margin-bottom / margin-left,但若是網站使用的是邏輯屬性,這些值就應該是:margin-block-start / margin-inline-end / margin-block-end / margin-inline-start

在英文網站中,物理屬性與邏輯屬性的表現是一致的。在使用其餘語言的網站中,當咱們使用相似 margin 的簡寫時,咱們但願它可以根據 direction 屬性或 writing-mode 屬性來工做。

但如何能讓簡寫自動根據directionwriting-mode 去解析呢?這一直是個懸而未決的問題。針對該問題,我曾給出一些建議:++suggestion that can solve the issue at github csswg-drafts++。若是你有更好的解決方案,歡迎你在連接中評論!

若是你如今要使用邏輯屬性,那你就必須把它們的屬性名完整地寫出來,而不能使用簡寫。

在這裏我給出一個可選的解決方案:

html{
   flow-mode:physical; 
       /*or*/
   flow-mode:logical;
}
.box{
  /*will be interpreted according to the HTML flow-mode value*/
   margin:10px 5px 6px 3px;
   padding:5px 10px 2px 7px;
}

關於響應式設計的問題

爲了製做一個完善的 demo,我嘗試在媒體查詢裏使用 max-width 的新屬性 max-inline-size,在 left-to-right 的條件下,max-inline-size 的效果會與 max-width 同樣,而在 right-to-left 的條件下,好比日語這樣的語言,新屬性的效果就會與 max-height 同樣。有點遺憾的是目前瀏覽器並不支持在媒體查詢(media query)中解析新屬性。

/*Not Working*/
@media (max-inline-size:1000px){
  .main-content{
    background:red;
    grid-template-columns:auto;
  }
}

一些值得思考的變化

在深刻學習並理解了邏輯屬性的概念後,我一邊寫文章一邊想,還有一些被忽略的改動也應該被歸入將來的更新範圍中:

  • line-height 能夠改成 line-size
  • border-width 能夠改成 border-size

不過真實狀況彷佛不太同樣,至少 border-width 和我想的不同。它更新爲邏輯屬性後,屬性名中依然帶有 width
舉個例子:border-block-start-width

相關文章
相關標籤/搜索