Refer: 为什么 CSS 这么难学?
我先来解释一下什么是正交。你调过显示器的「亮度」、「色调」和「饱和度」吧。
「亮度」就是明暗程度,值越大,屏幕越亮。
「色调」就是颜色,你通过调色调,可以把红色调成绿色。
「饱和度」就是鲜艳程度,值越大越鲜艳。
「正交」就是,你调节这三者中的一个时,不影响其他两个效果。你调节「亮度」的时候「色调」和「饱和度」不会变化。你调节「色调」的时候「亮度」和「饱和度」不会变化。你调节「饱和度」的时候「亮度」和「色调」不会变化。
「正交」看起来应该是理所当然的,对吧。想象一下「不正交」的情况:你调节「亮度」的时候,「色调」和「饱和度」会跟着无规律的变化。如果是这样,你会调得想死,因为你很难调到你想要的效果。而 CSS,就是「不正交」的。
我以 width 对 margin-left 的影响为例,假设有如下代码:
.parent 里面的 .child 宽度为 300px,现在我给他添加一个 margin-left: -10px,会发现
好的,于是我们知道 margin-left: -10px 会让元素整体左移。
真的是这样吗?
这个时候把 width 去掉重新做实验,这是在添加 margin-left 之前:
这是在添加 margin-left 之后:
我们发现 margin-left: -10px 并没有让整个元素左移,只是让左边缘左移了,右边缘并没有动。
现在来总结一下:如果指定了 width,那么 margin-left: 10px 会使元素整体左移如果没有指定 width,那么 margin-left: 10px 只会使做边缘左移(也就是宽度扩大)
到了这里 就会发现之前写swfit的时候经常蛋疼的不得了但是却无法描述这种感觉,现在知道了 这种感觉叫:不正交。
更深一步去想:
为什么 width 的存在与否会影响 margin-left 的作用?
有没有 width 之外的其他属性也会影响 margin-left 的作用?恐怕你无法得知。
这就是不正交的恐怖之处,你只有把所有属性与 margin-left 一起用一下,才能得知 margin-left 的真正规律。
这还只是两个属性的影响,你能想象三个属性互相影响的情况吗?
虽然是这样的复杂 但是为什么有些人用起来就那么得心应手呢?
这是因为他们写的足够多了…
第二个例子:
大家都知道 position: fixed 是相对于视口(viewport)定位的。
先看正常情况:
网页右边是一个 iframe,红色的 .fixed 元素相对于 iframe 视口左上角定位,与我们预期一致。
接下来我在 .box 上面加一个 CSS3 中的属性,就会改变你的认知:
父容器加了 transform 之后,fixed 定位的元素居然相对于父容器定位。
天知道以后 CSS 会不会加更多元素来影响我已经认为是真理的事情?我说一个更实际的问题吧,你敢在接手一个项目时,在任意一个元素上加 transform 属性吗?你不敢!除非你把它的每个子元素的属性都检查一遍……确定没有 fixed 定位。
这就是「不正交」的恶心之处。
第三个例子,大家都知道给固定宽度的 div 加 margin: 0 auto 可以让它水平居中,很多人就问,那为什么 margin: auto 0(注意 auto 和 0 的位置反过来了)不能做到垂直居中呢?其实是可以的:
但是必须是在当前元素有 position: absolute; top: 0; bottom:0; 的情况下才能垂直居中。或者与 flex 结合起来用也行。
这就很「不正交」了……
当然 像这样不正交的例子还有很多 根本没办法去记忆…
怎么样学习不正交的东西呢?
有一个办法:试。
你试的组合情况越多,就越能了解各种奇怪的现象。
其实不用那么悲观,常用的组合也就几十种吧,都试出来并记下来就行了。