DOOFOX BLOG

5月 29 2019 Category:

绘制一个正方形

writing-mode 的多样化应用

在有限条件下绘制一个正方形是很多前端开发者在页面开发时都会遇到的场景,
通常会有两种情况,最常见的是已知宽度(%),需要自适应高度、还有已知高度(%),需要自适应宽度。
前者是最为常见的,在网络上几乎全部都是关于这一类的教程。
后者情况比较少见,也是本文主要想讲述的内容。

已知宽度

1. padding/margin

在已知宽度的情况下(%),主要是利用:
margin 和 padding 的 top 以及 bottom 是以包含当前元素的宽度为基准进行计算
规范来实现效果。
Page-relative (Physical) Padding Properties

例如使用 CSS 生成一个正方形头像框,已知宽度占据窗口宽度的 100%,如何让这个头像框永远是一个正方形。
只要我们使用 padding-bottom: 100% 参数即可实现。

当我们设置 padding-bottom:100% 时,实际的 div 高度为 height + width(padding-bottom:100% = width:100%),所以是一个长方形。我们只需设置 height:0; 即可让元素成为一个正方形

Demo

See the Pen css-square__demo-1 by Hoyt (@hoythan) on CodePen.light

虽然实现了效果,但是如果你需要的是固定值 px 来控制或者需要调整百分比大小,那么你在改变宽度的同时,还需要去定义 padding 值才能实现所谓的自适应。所以更好的办法是使用伪类的方式实现,如下节所述

2. :after

padding/margin 的原理一样,区别是我们可以直接使用伪类元素来撑开这个 div 实现正方形效果。

你可能会遇到,在使用 margin 的时候无法撑开元素高度,这是因为发生了所谓的 外边距折叠
块级元素的上外边距和下外边距有时会合并(或折叠)为一个外边距,其大小取其中的最大者,这种行为称为外边距折叠
我们只要在父元素上触发 BFC特性(Block Formatting Context,块格式化上下文)即可解决这个问题。

Ps: CSS深入理解流体特性和BFC特性下多栏自适应布局。我们也可以直接使用 padding-top 来替换 margin-top 来实现同等效果,这样也没有外边距折叠问题了。

Demo

See the Pen css-square__demo-2 by Hoyt (@hoythan) on CodePen.0

已知高度

已知高度的情况在 Web 页面设计中非常常见,例如在需要横向无限滚动的页面设计,需要窗口高度占据屏幕的 100%,宽度永远是一个正方形。或对于高度不确定(%)但需要宽度永远保持一定比例的时候。

Demo

上面提到margin 和 padding 的 top 以及 bottom 是以包含当前元素的宽度为基准进行计算,但是似乎没有 CSS 属性可以以高度为基准进行计算(反驳点此)。

writing-mode

那么我唯一能想到的 CSS 属性就是 writing-modewriting-mode 大部分人都很陌生,寻常的网页开发基本看不见它。虽然它是一个非常古老的属性,在 IE7 时代就出现了,但它在很久以后才被各个浏览器厂商所支持。不过当你看到这篇文章的时候,你已经不需要过多考虑它的兼容性问题了。虽然它的实际效果可能会和你想要的不太一样#注意事项

浏览器支持

它的目的是为了实现垂直文字效果,如中文或日文,然而有趣的是,当我们把它放在其他用途时,它的作用将会被无限放大。因为 writing-mode 是一个非常神奇的属性,它能够改写 CSS 的流规则,例如让横向属性一转身变成纵向属性,你只要记得这个规则就能理解为什么我可以用已知高度(%)来实现自适应宽度了。
关于这个属性,这里有对其非常详尽的描述 改变CSS世界纵横规则的writing-mode属性

writing-mode为什么能实现(横向属性一转身变成纵向属性),其实核心在于它能够通过修改 CSS 逻辑方向来实现修改指定块的流动方向。

我们给原来的 .avatar 外包裹一层 div ,并赋予属性 writing-mode: vertical-rl;,就会改变内部元素属性的流方向为垂直靠右(rl:right-left,从右到左)。当元素的逻辑方向被改变时padding-top 的逻辑方向实际上变成了 padding-right,bottom 变成了 left。

Demo

See the Pen css-square__demo-3 by Hoyt (@hoythan) on CodePen.light

注意事项

在 Chrome 浏览器中,当我们改变窗体高度的时候,这个正方形大小不会按照我们预计的情况进行自适应调整,只有在调整宽度时候才会触发。不过在 Safari 中则不会有此问题。

逻辑属性

所谓CSS逻辑属性,指的是*-start*-end以及*-inline-start*-inline-end*-block-start*-block-start这类CSS属性,其元素最终的渲染方式是有逻辑性的,而 书写模式(writing-mode) 则用来调整这些逻辑属性的流顺序。

在 2017 年 W3C CSS 组推出的 CSS Logical Properties and Values Level 1 – CSS 逻辑属性与值的草案中,详细描述了不同的书写模式(writing-mode)中,可以抽取出共性的抽象概念。这些逻辑抽象概念需要在不同书写模式下映射到左或右、上或下等物理的概念上。

技术说明

CSS Writing Modes
CSS Writing Modes Level 3
A Chinese typography experiment (Speaker: Chen Hui Jing) – Talk.CSS