CSS 世界中的方位與順序

在 CSS 中,咱們常常會與各類方向方位打交道。css

譬如 marginpadding,它們就會有 margin-leftmargin-right 或者是 padding-leftpadding-right。還有定位中的 lefttoprightbottom,它們表示了上下左右不一樣的方位。html

還有一種狀況是從x方位到x方位,譬如 writing-modedirection,它表明了一種順序,表示塊流動方向,或者文字書寫的方向等。前端

本文將捋一捋 CSS 世界中的方位與順序,探尋其中一些有意思的點。git

writing-mode & direction & unicode-bidi

在 CSS 世界中,這 3 個屬性都與排版順序相關,互有關聯但做用各異。github

  • writing-mode:定義了文本水平或垂直排布以及在塊級元素中文本的行進方向。
  • direction:設置文本排列的方向。 rtl 表示從右到左 (相似希伯來語或阿拉伯語), ltr 表示從左到右。
  • unicode-bidi:它與 direction 很是相似,兩個會常常一塊兒出現。在現代計算機應用中,最經常使用來處理雙向文字的算法是Unicode 雙向算法。而 unicode-bidi 這個屬性是用來重寫這個算法的。

單純看定義有點懵逼,咱們簡單的看幾個應用示意圖:web

writing-mode 示意

writing-mode 基本只須要留意最多見的 horizontal-tbvertical-lrvertical-rl 。表示文本的行進方向,下圖表示瀏覽器對 writing-mode 的支持完整的狀況下輸出的外觀:算法

direction 示意

OK,那 direction 又爲什麼呢?它表示文本排列的方向瀏覽器

  • direction: ltr:默認屬性。可設置文本和其餘元素的默認方向是從左到右。
  • direction: rtl:可設置文本和其餘元素的默認方向是從右到左。

有點繞,因此上 Demo 最爲直觀。假設,咱們有以下結構:ide

<ul class="wrap">
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
</ul>
<p>這是一段正常順序的文本</p>

簡單的 CSS 以下:wordpress

p, ul {
    background: #ff00ff50;
    padding: 10px;
}
ul {
    display: flex;
    justify-content: space-between;
    
    & > li {
        border: 1px solid #333;
    }
}

正常狀況下的樣式以下:

咱們分別給兩組元素的父容器 <p><ul> 加上 direction: ltrdirection: rtl,則最終效果以下:

能夠看到,direction 能夠改變子元素的排列方向,可是它確沒法改變單段文本內(或是內聯元素內),每個文字的書寫順序

那若是,我但願 這是一段正常順序的文本 這段文字,不是從左向右進行書寫,而是反過來,從右到左進行書寫,又該如何設置呢?

unicode-bidi 示意

這就須要請出 unicode-bidi 了。

單獨使用 direction: rtl 沒法使單段文本內(或是內聯元素內),文字的書寫順序改成從右至左。須要配合 unicode-bidi

CSS 中的 unicode-bidi 屬性,和 direction 屬性,共同決定如何處理文檔中的雙書寫方向文本。

仍是上述的代碼,咱們改造一下:

<p>這是一段正常順序的文本</p>
p {
    direction: rtl;
    unicode-bidi: bidi-override;
}

結果以下:

放到一塊兒比較:

這裏除了 unicode-bidi: bidi-overrideunicode-bidi: isolate-override 也能獲得一樣的效果。

這裏涉及了一個很是重要的知識 -- Unicode 雙向算法

Unicode 雙向算法

雙向文字就是一個字符串中包含了兩種文字,既包含從左到右的文字又包含從右到左的文字。

對於文字書寫習慣,分爲:

  1. 大多數文字都是從左到右的書寫習慣:好比拉丁文字(英文字母)和漢字;
  2. 少數文字是從右到左的書寫方式好比阿拉伯文(ar)跟希伯來文(he)。

在現代計算機應用中,最經常使用來處理雙向文字的算法是 Unicode 雙向算法(Unicode Bidirectional Algorithm)。

一個區域內有整體方向,決定從這個區域的哪邊開始書寫文字,一般稱爲基礎方向。瀏覽器會根據你的默認語言來設置默認的基礎方向,如英語、漢語的基礎方向爲從左到右,阿拉伯語的基礎方向爲從右到左

在 Web 中,咱們有 3 種方式能夠控制文字方向:

  1. html實體 - &lrm;&rlm;
  2. <bid><bdo> 標籤 與 dir 屬性
  3. CSS 屬性 direction + unicode-bidi

本文介紹的就是 CSS 中的 direction + unicode-bidi 方式控制文字的書寫方向。關於 Unicode 雙向算法(Unicode Bidirectional Algorithm)自己仍是很是複雜的,本文也僅僅只是簡單說起,更爲詳盡的內容,你能夠參考 UNICODE BIDIRECTIONAL ALGORITHM

writing-mode & direction & unicode-bidi 的一些應用

除去自己的功能,下面咱們來看看它們其它的一些應用場景。

使用 writing-mode 進行創意排布布局

writing-mode 很是適合用於進行一些創意排版。

基礎的相似中國古詩詞的一些豎向展現:

<div class="g-wrap">
    <h2>涼州詞</h2>
    <p>葡萄美酒夜光杯,</p>
    <p>欲飲琵琶立刻催。</p>
    <p>醉臥沙場君莫笑,</p>
    <p>古來征戰幾人回。</p>
</div>

.g-wrap 分別添加 writing-mode: vertical-rl 或者 writing-mode: vertical-lr 獲得不一樣的效果:

.rl {
    writing-mode: vertical-rl;
}
.lr {
    writing-mode: vertical-lr;
}

CodePen Demo -- display poems by writing-mode

又或者像是這樣,利用 writing-mode:vertical-rl 實現標題的豎向排列,搭配內容造成有意思的報紙排版:

<div>
  <h2>Title Loomings</h2>
  <p>Call me Ishmael. Some years ago- never mind ho....
  </p>
</div>
div {
  width: 750px;
  padding-left: 150px;
}
h2 {
  position: absolute;
  writing-mode: vertical-rl;
}

獲得這樣的排版佈局:

CodePen Demo -- writing-mode Layout Demo

改變文本溢出省略位置,使之在頭部進行省略

咱們都知道,本文超長溢出的省略,經過都是在文本的最末尾。像是這樣:

<p>Make CSS Ellipsis Beginning of String</p>
p {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

這裏,咱們能夠經過 direction,將省略打點的位置,從尾部移動至頭部:

p {
    direction: rtl;
}

結果以下:

嘗試了下運用在多行省略中,多行省略的打點會出如今最後一行的左側,不符合需求。

CodePen Demo -- CSS Ellipsis Beginning of String

使用 writing-mode 改變元素方位

這個小技巧是在張老師的博客中學到的:改變CSS世界縱橫規則的writing-mode屬性

咱們能夠經過 writing-mode: vertical-rl,將元素轉一個 90° 角:

<div>➤</div>
div:hover {
    writing-mode: vertical-rl;
}

看看效果,當 hover 的時候,將箭頭從向右➡️改成向下🔽 :

固然,如今這個功能徹底能夠用 transform 替代,可是在以前須要兼容 IE 系列的時候,不失爲一個有意思的小技巧。

CSS 中的邏輯屬性

下面一個章節,咱們聊聊 CSS 中的邏輯位置。

咱們知道,在咱們使用相似 marginpadding 的時候,能夠單獨控制每一個方向,例如 margin-toppadding-left

然而,這種使用了 top/left/bottom/right 物理方向維度定義的屬性,在不一樣的排版規則下,就很是容易出問題。

思考以下這樣一個 DEMO,咱們但願給古詩的題目的上方,添加一個 padding 值:

<div class="g-wrap pt">
    <h2>涼州詞</h2>
    <p>葡萄美酒夜光杯,</p>
    <p>欲飲琵琶立刻催。</p>
    <p>醉臥沙場君莫笑,</p>
    <p>古來征戰幾人回。</p>
</div>
<div class="g-wrap pt rl">
    <h2>涼州詞</h2>
    <p>葡萄美酒夜光杯,</p>
    <p>欲飲琵琶立刻催。</p>
    <p>醉臥沙場君莫笑,</p>
    <p>古來征戰幾人回。</p>
</div>
.pt {
    padding-top: 100px;
}
.rl {
    writing-mode: vertical-rl;
}

能夠看到,不管 writing-mode 如何,padding-top 始終指代物理方向的上方。

基於這種不一樣排版規則,物理方向可能會帶來必定的困擾這個問題,CSS 在 CSS Logical Properties and Values Level 1 規範中,推出了 CSS 邏輯屬性。

CSS 邏輯屬性與值是 CSS 的一個新的模塊,其引入的屬性與值能作到從邏輯角度控制佈局,而不是從物理、方向或維度來控制。

仍是上述的 DEMO,咱們可使用 padding-block-start 替代 padding-top

重點:使用 padding-block-start 替代 padding-top

.pt {
-   padding-top: 100px;
+   padding-block-start: 100px;
}
.rl {
    writing-mode: vertical-rl;
}

此次再看看效果:

padding 的位置由物理上的上方,變成了邏輯上的上方。

完整的 Demo 你能夠戳這裏:CodePen Demo-- 物理方向與邏輯方向展現

margin、padding、border、relative 物理屬性到邏輯屬性的映射

相似這樣的屬性,在規範中定義了挺多的,簡單羅列一下具體的映射規則:

margin 物理屬性到邏輯屬性的映射:

Property 屬性 Logical Property 邏輯屬性
margin-top margin-block-start
margin-left margin-inline-start
margin-right margin-inline-end
margin-bottom margin-block-end

padding 物理屬性到邏輯屬性的映射:

Property 屬性 Logical Property 邏輯屬性
padding-top padding-block-start
padding-left padding-inline-start
padding-right padding-inline-end
padding-bottom padding-block-end

border 物理屬性到邏輯屬性的映射:

Property 屬性 Logical Property 邏輯屬性
border-top{-size|style|color} border-block-start{-size|style|color}
border-left{-size|style|color} border-inline-start{-size|style|color}
border-right{-size|style|color} border-inline-end{-size|style|color}
border-bottom{-size|style|color} border-block-end{-size|style|color}

relative 物理屬性到邏輯屬性的映射:

Property 屬性 Logical Property 邏輯屬性
top inset-block-start
left inset-inline-start
right inset-inline-end
bottom inset-block-end

在邏輯屬性中沒有方向性的概念,只有開始(start)和結束(end)、塊(block)和內聯(inline)的概念。好比說,在從左到右(LTR)中,start 是 left,但在從右到左(RTL),它是 right。

邏輯屬性下的盒子模型

考慮到不一樣排版帶來的邏輯問題,整個盒子模型也能夠隨之進行改變。

下圖,左邊是物理盒子模型,右邊是邏輯屬性下的盒子模型。

左:物理盒子 | 右:邏輯盒子

物理方向與邏輯方向重疊

固然,還有這樣一種狀況,就是設置的邏輯方向和物理方向重疊,譬如咱們給一個正常從左往右,從上至下的元素同時設置 padding-toppadding-block-start,看看會發生什麼:

div {
    padding-top: 120px;
    padding-block-start: 100px;
}

這裏若是物理方向與邏輯方向設置的 padding 重疊,將會取兩個值中後面定義的那個。這裏因爲 padding-block-start 後於 padding-top 定義,因此 padding 的值爲 100px

marginborder 同理。這裏個人理解是,同個方向上仍是隻能存在一個 margin\padding\border,不管是邏輯方向仍是物理方向,取後定義的值爲準。

CodePen Demo-- 物理方向與邏輯方向重疊 DEMO 展現

總結一下

總結一下,當項目開始國際化,當國內更多的業務開始出海,國際化兼容適配也會愈來愈重要。好在 CSS 也一直在緊跟時代,推陳出新,當你的排版佈局須要考慮不一樣的 writing-mode 的時,你須要開始考慮使用邏輯屬性替代物理屬性!

最後

好了,本文到此結束,但願對你有幫助 😃

想 Get 到最有意思的 CSS 資訊,千萬不要錯過個人公衆號 -- iCSS前端趣聞 😄

更多精彩 CSS 技術文章彙總在個人 Github -- iCSS ,持續更新,歡迎點個 star 訂閱收藏。

若是還有什麼疑問或者建議,能夠多多交流,原創文章,文筆有限,才疏學淺,文中如有不正之處,萬望告知。

參考文章

相關文章
相關標籤/搜索