CSS 世界中的方位与顺序

简介: CSS 世界中的方位与顺序

在 CSS 中,我们经常会与各种方向方位打交道。


譬如 margin、padding,它们就会有 margin-left、margin-right 或者是 padding-left、padding-right。还有定位中的 left、top、right、bottom,它们表示了上下左右不同的方位。


还有一种情况是从x方位到x方位,譬如 writing-mode、direction,它代表了一种顺序,表示块流动方向,或者文字书写的方向等。


本文将捋一捋 CSS 世界中的方位与顺序,探寻其中一些有意思的点。


writing-mode & direction & unicode-bidi



在 CSS 世界中,这 3 个属性都与排版顺序相关,互有关联但作用各异。


  • writing-mode:定义了文本水平或垂直排布以及在块级元素中文本的行进方向。
  • direction:设置文本排列的方向。 rtl 表示从右到左 (类似希伯来语或阿拉伯语), ltr 表示从左到右。
  • unicode-bidi:它与 direction 非常类似,两个会经常一起出现。在现代计算机应用中,最常用来处理双向文字的算法是Unicode 双向算法。而 unicode-bidi 这个属性是用来重写这个算法的。


单纯看定义有点懵逼,我们简单的看几个应用示意图:


writing-mode 示意


writing-mode 基本只需要留意最常见的 horizontal-tb、vertical-lr、vertical-rl 。表示文本的行进方向,下图表示浏览器对 writing-mode 的支持完整的情况下输出的外观:


c763b521fb3b4aa8a8124dfa9d984e45_tplv-k3u1fbpfcp-zoom-1.png

direction 示意


OK,那 direction 又为何呢?它表示文本排列的方向。


  • direction: ltr:默认属性。可设置文本和其他元素的默认方向是从左到右。
  • direction: rtl:可设置文本和其他元素的默认方向是从右到左。

有点绕,所以上 Demo 最为直观。假设,我们有如下结构:


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


简单的 CSS 如下:


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


正常情况下的样式如下:

4271ad184b6e4e3696a2f02ea9ae812e_tplv-k3u1fbpfcp-zoom-1.png

我们分别给两组元素的父容器 <p> 和 <ul> 加上 direction: ltr 及 direction: rtl,则最终效果如下

47f654eca630484fb7f7eb720a8cfff8_tplv-k3u1fbpfcp-zoom-1.png

可以看到,direction 可以改变子元素的排列方向,但是它确无法改变单段文本内(或是内联元素内),每一个文字的书写顺序。


那如果,我希望 这是一段正常顺序的文本 这段文字,不是从左向右进行书写,而是反过来,从右到左进行书写,又该如何设置呢?


unicode-bidi 示意


这就需要请出 unicode-bidi 了。


单独使用 direction: rtl 无法使单段文本内(或是内联元素内),文字的书写顺序改为从右至左。需要配合 unicode-bidi。


CSS 中的 unicode-bidi 属性,和 direction 属性,共同决定如何处理文档中的双书写方向文本。


还是上述的代码,我们改造一下:


<p>这是一段正常顺序的文本</p>
HTML 复制 全屏
p {
    direction: rtl;
    unicode-bidi: bidi-override;
}


结果如下:

0c972e9753084fa7bc4d3de24a3b17a1_tplv-k3u1fbpfcp-zoom-1.png


放到一起比较:


这里除了 unicode-bidi: bidi-override,unicode-bidi: isolate-override 也能得到同样的效果。

738a7aed7b154bbb9bb42b02bd33f1c8_tplv-k3u1fbpfcp-zoom-1.png



这里涉及了一个非常重要的知识 -- 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;
}


009063d4d88c4d05a4022d9265a22bff_tplv-k3u1fbpfcp-zoom-1.png

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;
}


得到这样的排版布局:

fd83543c25f146899319bba5243d51e7_tplv-k3u1fbpfcp-zoom-1.png



CodePen Demo -- writing-mode Layout Demo


改变文本溢出省略位置,使之在头部进行省略


我们都知道,本文超长溢出的省略,通过都是在文本的最末尾。像是这样:


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


bf18a8f93e7940a8a60edb33b3009a58_tplv-k3u1fbpfcp-zoom-1.png

这里,我们可以通过 direction,将省略打点的位置,从尾部移动至头部:


p {
    direction: rtl;
}


结果如下:

25f5825a73ff4679a181f0304a9bd324_tplv-k3u1fbpfcp-zoom-1.png

尝试了下运用在多行省略中,多行省略的打点会出现在最后一行的左侧,不符合需求。


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 的时候,将箭头从向右➡️改为向下🔽


c4b833ed6acc4ba097cde6237b32697b_tplv-k3u1fbpfcp-zoom-1.gif

当然,现在这个功能完全可以用 transform 替代,但是在之前需要兼容 IE 系列的时候,不失为一个有意思的小技巧。


CSS 中的逻辑属性



下面一个章节,我们聊聊 CSS 中的逻辑位置。


我们知道,在我们使用类似 margin 和 padding 的时候,可以单独控制每个方向,例如 margin-top、padding-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;
}
CSS 复制 全屏

29b6bfccc8f24fc4b2254467536d7528_tplv-k3u1fbpfcp-zoom-1.png


可以看到,无论 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;
}


这次再看看效果:

f1321cc6f2124122929d71300be912df_tplv-k3u1fbpfcp-zoom-1.png

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。


逻辑属性下的盒子模型


考虑到不同排版带来的逻辑问题,整个盒子模型也可以随之进行改变。

下图,左边是物理盒子模型,右边是逻辑属性下的盒子模型。


e68079b6588844cea7e4ddea834dcac7_tplv-k3u1fbpfcp-zoom-1.png

物理方向与逻辑方向重叠


当然,还有这样一种情况,就是设置的逻辑方向和物理方向重叠,譬如我们给一个正常从左往右,从上至下的元素同时设置 padding-top 和 padding-block-start,看看会发生什么:


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


ca7249ea5cb84ed5be96fc9ecf1ad265_tplv-k3u1fbpfcp-zoom-1.png


这里如果物理方向与逻辑方向设置的 padding 重叠,将会取两个值中后面定义的那个。这里由于 padding-block-start 后于 padding-top 定义,所以 padding 的值为 100px。

margin 和 border 同理。这里我的理解是,同个方向上还是只能存在一个 margin\padding\border,无论是逻辑方向还是物理方向,取后定义的值为准。

CodePen Demo-- 物理方向与逻辑方向重叠 DEMO 展示


总结一下



总结一下,当项目开始国际化,当国内更多的业务开始出海,国际化兼容适配也会越来越重要。好在 CSS 也一直在紧跟时代,推陈出新,当你的排版布局需要考虑不同的 writing-mode 的时,你需要开始考虑使用逻辑属性替代物理属性!

目录
相关文章
|
4月前
|
前端开发 算法
CSS 选择器的优先级算法
在CSS中,选择器的优先级由四个级别和各级别的出现次数决定**。这四个级别分别为:行内选择符、ID选择符、类别选择符、元素选择符,优先级依次降低。
|
前端开发
css奇数偶数选择器
css奇数偶数选择器
324 0
|
22天前
|
前端开发
css书写位置
css书写位置
22 2
|
4月前
|
前端开发
css元素得层级顺序
css元素得层级顺序
|
4月前
|
算法 JavaScript
JS算法-颠倒二进制位
JS算法-颠倒二进制位
|
4月前
|
前端开发 C++
CSS阶详细解析一
CSS进阶 目标:掌握复合选择器作用和写法;使用background属性添加背景效果 01-复合选择器 定义:由两个或多个基础选择器,通过不同的方式组合而成。 作用:更准确、更高效的选择目标元素(标签)
43 0
|
JavaScript
利用JS求1-100之间所有偶数和奇数的和
利用JS求1-100之间所有偶数和奇数的和
利用JS求1-100之间所有偶数和奇数的和
|
前端开发
CSS实现两个元素调换位置
CSS实现两个元素调换位置
|
前端开发
伪类选择器设置奇偶数标签(1+X Web前端开发 例题)
伪类用于定义元素的特殊状态。 例如,它可以用于:设置鼠标悬停在元素上时的样式,为已访问和未访问链接设置不同的样式,设置元素获得焦点时的样式
225 0
伪类选择器设置奇偶数标签(1+X Web前端开发 例题)