尽管名字听起来很有趣,魔力数是一个坏事情。他是一种<a href="http://en.wikipedia.org/wiki/Magic_number_(programming)#Unnamed_numerical_constants">老的“未命名数字常量”的学院派 </a>处理方法。因此,一些可能是对样式至关重要的数字“扑通”沉进代码里,但是却对那些不怎么熟悉这部分代码的人来说,十分难去理解为什么去这么做。CSS 和未命名常量一起载入进来,但是他们通常和其他样式成对出现,而且有上下文关联,所以看来有点神秘。尽管我们一直能看到CSS中的魔力数,但是他们还是不好的。
CSS中的魔力数通常在某些特定的场景下生效,但是很脆弱,换了个场景他很就很容易失效。他们通常和字体在某种程度上有关。他们通常被一个只在自己的浏览器中,理想环境下测试的人创造。让我们看一些例子来让我们了解他们究竟是什么,并且希望能在未来避免他们。
看看这个tab的例子:
<img src="http://cdn.css-tricks.com/wp-content/uploads/2013/04/tabs-1.png" alt="">
每一个tab都被设置成width:100px;
.在这个例子中100px
就是我们所说的神奇数
。很可能各种错误都会因此发生。简单点加上另外一个有着稍长文本的tab就能解释了:
<img src="http://cdn.css-tricks.com/wp-content/uploads/2013/04/tabs-2.png" alt="">
有点奇怪,并且是我们不希望看到的结果。我们可以用white-space:nowrap
来防止文字换行,但是结果可能更糟糕:
<img src="http://cdn.css-tricks.com/wp-content/uploads/2013/04/tabs-3.png" alt="">
如果用min-width
来代替的话,我们的tabs可能不那么容易崩溃:
<img src="http://cdn.css-tricks.com/wp-content/uploads/2013/04/tabs-4.png" alt="">
或者干脆不设定width
:
<img src="http://cdn.css-tricks.com/wp-content/uploads/2013/04/tabs-5.png" alt="">
当然,如果你坚定地要把所有tab的大小统一,你可以这样overflow:hidden
和 text-overflow:ellipsis
,大概就会是这样:
<img src="http://cdn.css-tricks.com/wp-content/uploads/2013/04/tabs-6.png" alt="">
在这种情况下,你可能就需要一个title
属性来用某种方式显示整个tab的名称。你可能觉得这可以在CMS中直接限定tab的字符长度来防止这样的事情发生。但是如果用户他在客户端为了方便增大了字体大小呢?这会让他们很受伤。
在最近一个叫Line-On-Sides_Headers的post中,我使用的line-height
值也是一个魔力数。我让你在有有着华丽的@font-face
属性的文本中使用这个技术。假设这个字体没有被载入或者用户覆盖了他或者用户的浏览器根本不支持这个属性。那么后备的字体就会被载入。后备字体可能和我们定制的大小相差很多,那么使用后备的字体后,行就会被摆出一种奇怪的样式,不是我们想要的居中样式。魔力数跪了。
<img src="http://cdn.css-tricks.com/wp-content/uploads/2013/04/custom-font-magic-number.png" alt="">
这个特别的例子有点做作,但是我肯定你已经见过很多有着超夸张的X字高的定制字体。
小科普,X字高是,或corpus size 是指字母的基本高度,精确地说,就是基线(baseline)和主线之间的距离,是字体设计的重要因素。
在西文的具体字体以及排版术语中,x字高通常被称为一个 ex,这和把大写字母M宽度称为一个em的习惯类似。
假设你有一堆有着不同多内容的盒子模型。你想把他们排列整齐进入一个网格,就把他们float:left;
了,有点乱:
<img src="http://cdn.css-tricks.com/wp-content/uploads/2013/04/grid-mess.png" alt="">
如果他们有同样的高度你就不用愁了!
<img src="http://cdn.css-tricks.com/wp-content/uploads/2013/04/Screen-Shot-2013-04-22-at-8.19.55-AM.png" alt="">
这样的前提是,如果用户在浏览网站时用的恰巧是和你一样的字体设置。但是用户可以变啊。
<img src="http://cdn.css-tricks.com/wp-content/uploads/2013/04/chrome-font-size.png" alt="">
现在就像一个忧伤的长号:
<img src="http://cdn.css-tricks.com/wp-content/uploads/2013/04/Screen-Shot-2013-04-22-at-8.22.34-AM.png" alt="">
使用min-height代替可以防止这样的重叠的尴尬,但那是盒子将会形状不同并且浮动问题会再次出现。我不打算在解决方案上花太多力气因为现在已经够抽象的了,但是你也许可以在盒子里使用滚动条,或者用一些JavaScript来调整大小,或者用其他的样式。
Harry Roberts 指出了一个典型的在CSS中使用了魔力数的例子
<pre>
.site-nav > li:hover .dropdown {
position: absolute;
top: 37px;
left: 0;
}
</pre>
这本该是一个CSS控制的下拉框。菜单只有在父元素被hover
上时被打开,下拉框出现。他应当在父菜单的下面。写这个代码的开发者在他当时的浏览器中,这个菜单确实是37px
的高度。我敢确定你能想象出这不可能永远都是对的。37px
是一个魔力数。Harry建议使用top: 100%
来取代,这个属性的意思是从顶部开始计算,相比起来不容易出差错。
在文章Fighting the Space Between Inline-Block Elements中,-4px
是一个可以除掉分割的数字。那绝对是一个神奇数。4px
只有在默认16px
下的某些情况可以解决这些问题。
换一个类似Monaco
的字体?你跪了。换大一点或者小一点的字体呢?你还是跪了。
<img src="http://cdn.css-tricks.com/wp-content/uploads/2013/04/inline-block.png" alt="">
看看这篇文章的补救方法。
定义的困惑
因为我们一直在说“别这么干”,如何去正确区分他们也是相当重要的。我看到过去有很多的问题上大家对于魔力数的定性意见不一
(1) (2) (3)。
这里有一些例子:
-webkit-transform: translateZ(0);
魔力数?不。这只是性能调优的一个hack。
.parent {
padding: 22px;
}
.child {
bottom: 22px;
left: 22px;
}
魔力数?不是。这数字的确奇怪但是不属于那个范畴。子元素被定位于底部左边的元素,sams-padding.因为这些数字互相匹配,所以他们在一起就会make-sense。如果数字都不相同的话,那么就意味着很可能和字体大小等有一点关系,也很可能就是一个魔力数。
top: 37px;
假设这是一个魔力数,就像上面提到的下拉框例子。我们能用Sass解决他么?
$topDistance: 37px;
.dropdown {
top: $topDistance;
}
这就不再是一个“未命名”的变量了,但是就因为我们命名了它?他依然是个CSS中的魔力数,并且和原来的看起来一样奇怪。
letter-spacing: -.05em;
魔力数?不。如果它是用px的话很可能是,因为像素的值是不变的常量所以他的变化是依据现在的字体大小。Huge font-size, barely any change, small font-size, big change
(这句还是英文比较顺口)。因为em是相关联的,所以没那么容易出差错。
所以结论是
我不喜欢这样的blog, 但是对于那些“仅此适用”的东西,这也是一个不错的吐嘈。
WordPress 的CSS 代码规范说你不该学他们。还有什么其他的?
如果你在使用icon 字体,记住他们是字体,所以他们会变换大小。你不能为他们设一个px 的值来“保留空间”,因为字体大小会变但是px 的值也许会不工作。
我愿意更新这些有趣的使用魔力数导致跪了的例子,请跟去原文评论。
如果你尝试居中一个图片和文本的时候,vertical-align这个属性干得不错,但是我发现总有1px左右的偏差, 所以我写postion: relative; top: 1px;
来矫正。这是个魔力数吗?不太确定。
译后记:内容太多还未消化完全,如果有翻译不太对的地方请指正