盒尺寸中的 4 个盒子 content box、padding box、border box 和 margin box 分别对应 CSS 中的 content
、padding
、border
和 margin
属性,本文我们的主角是 border box。下面我们一起看看 border
都有哪些精彩的特性表现。
虽然同属盒模型基本成员,但是 border-width
却不支持百分比。例如,设置:
div { border-width: 50%; }
是无效的,直接声明无效。这一点和 margin
和 padding
都不一样,下面问题来了:为什么 border-width
不支持百分比呢?
顾名思义,border-width
是“边框宽度”,我们先来看看现实世界的物体的边框,假设我们现在有两台数码设备,分别是 iMac 和 iPhone,很显然,这两台设备的尺寸差异很大,但是,大家仔细对比就会发现,这两者的边框大小差别跟屏幕设备相比较而言就可以忽略不计了。所谓的“边框”,是不会因为设备大就按比例变大的。因此,如果支持百分比值,是不是就意味着设备大了边框也跟着变大?这显然不合“边框”的语义嘛!并且也没有需要使用百分比值的场景。
其实还有很多 CSS 属性,如 outline
、box-shadow
、text-shadow
等,都是不支持百分比值的,原因也与此类似。
我们平常使用 border-width
几乎全是固定的数值,如 border-width:1px
之类,但是,可能有些人并不知道 border-width
还支持若干关键字,包括 thin
、medium
(默认值)和 thick
,对应的尺寸大小具体如下。
thin
:薄薄的,等同于 1px
。medium
(默认值):薄厚均匀,等同于 3px
。thick
:厚厚的,等同于 4px
。不知道大家有没有想过这么一个问题:为什么 border
属性的默认宽度大小是 medium
,也就是 3px
,明明 thin
(1px
)宽度更常用吧? 为什么呢?因为……border-style:double
至少 3px
才有效果!border-style
…double
?我好像只知道 solid
、dashed
和 dotted
,这 double
是个什么?
下面我们一起看看 border-style
。
注意,border-style
的默认值是 none
,有一部分人可能会误以为是 solid
。这也是单纯设置 border-width
或 border-color
没有边框显示的原因,如下示意:
div { border: 10px; } /* 无边框出现 */
div { border: red; } /* 无边框出现 */
如果是 border-style
类型值则边框出现。例如,下面 CSS 会出现 3 像素宽的边框:
div { border: solid; } /* 有边框出现 */
平时我们使用 border-style:none
多出现在重置边框样式的时候,例如,实现一个没有下边框的边框效果:
div {
border: 1px solid;
border-bottom: none;
}
当然,我们也可以通过直接设置边框宽度为 0 进行重置:
div {
border: 1px solid;
border-bottom: 0;
}
当然,可以两个一起写,根据前辈的测试,这样写渲染性能最高:
div {
border: 1px solid;
border-bottom: 0 none;
}
这个大家耳熟能详,妇孺皆知,实线边框,没什么好说的。
虚线边框可以说是使用频率第二高的边框类型了,至于使用没什么好说的,倒是这边框本身的一些渲染数据挺有意思。这虚线颜色区的宽高比以及颜色区和透明区的宽度比例在不同浏览器下是有差异的。例如,在 Chrome 和 Firefox 浏览器下,颜色区的宽高比是 3:1,颜色区和透明区的宽度比例是 1:1,如下图所示。
而 IE 浏览器则是另外的数据,颜色区的宽高比是 2:1,颜色区和透明区的宽度比例也是 2:1,如下图所示。
本身就是方方正正的,再加上兼容性的差异,基本上就只能当作虚框来用了。
虚点边框在表现上同样有兼容性差异,虽然规范上明确表示是个圆点,但是 Chrome 以及 Firefox 浏览器下虚点实际上是个小方点,如图 4-61 所示。
而 IE 浏览器下则是小圆点,如下图所示。
双线边框,顾名思义,即两根线且为实线。虽然平常我们使用少,但是其兼容性非常好。视觉表现为线框——透明线框,根据 border-width
大小不同,其表现规则如下。
值 | 双线边框表现规则 |
---|---|
1px | 0+1+0 |
2px | 1+0+1 |
3px | 1+1+1 |
4px | 1+2+1 |
5px | 2+1+2 |
6px | 2+2+2 |
7px | 2+3+2 |
当边框宽度是 1px
和 2px
的时候,其表现和 border-style:solid
是一模一样的:当边框为 3px
的时候,才开始有双线边框的表现,包括 retina
屏幕也是如此,因为边框宽度是没有半像素的概念的。还记不记得上一节留下的问题,“为什么 border-width
的默认值是 media
(3px
)?”答案就在这里,虽然说实际开发的时候 1px
大小的 solid
类型边框是最常用的,但是却无法让 double
类型边框有合乎语义的表现,因此使用了能表现double
类型的最小边框宽度 3px
作为边框宽度默认值。
我们还可以用一句话总结出 border-style:double
的表现规则:双线宽度永远相等,中间间隔±1
。
于是,我们就可以借助 border-style:double
实现一些等宽的图形效果。例如,等比例“三道杠”图标效果如下图所示。
CSS 代码如下:
.icon-menu {
width: 120px;
height: 20px;
border-top: 60px double;
border-bottom: 20px solid;
}
inset
(内凹)、outset
(外凸)、groove
(沟槽)、ridge
(山脊)风格老土过时,且兼容性惨不忍睹。因此,它们没有任何实用价值。这里就不再赘述。
border-color
有一个很重要也很实用的特性,就是“border-color
默认颜色就是 color
色值”。具体来讲,就是当没有指定 border-color
颜色值的时候,会使用当前元素的 color
计算值作为边框色。例如,下面这个例子:
.box {
border: 10px solid;
color: red;
}
此时,.box
元素的 10px
边框颜色就是红色。
具有类似特性的 CSS 属性还有 outline
、box-shadow
和 text-shadow
等。
那这种特性对于实际开发有没有什么作用呢?我们直接看一个例子,我们在上传图片的时候,往往后面会跟着一个带有加号的框框按钮,表示可以继续传图,如图 4-68 所示,然后 hover 的时候会变个色。
这种方方正正、简简单单的图形最适合使用三三两两的 CSS 代码绘制了。通常,正常思维下,我们都是使用 width / height
外加一个 background-color
绘制加号的,核心 CSS 代码如下:
.add {
border: 2px dashed #ccc;
}
.add:before, .add:after {
background: #ccc;
}
/* hover 变色 */
.add:hover {
border-color: #06C;
}
.add:hover:before, .add:hover:after {
background: #06C;
}
功能没有任何问题,唯独当我们 hover
变色的时候,需要同时重置 3 处(元素本身以及两个伪元素)颜色。实际上,如果这里不是使用 background-color
,而是使用 border
来绘制加号,则代码要简单得多,如下:
.add {
color: #ccc;
border: 2px dashed;
}
.add:before {
border-top: 10px solid;
}
.add:after {
border-left: 10px solid;
}
/* hover 变色 */
.add:hover {
color: #06C;
}
可以看到,使用 border
实现,我们 hover
变色的时候,只需要重置 1 处,也就是重置元素本身的 color
就可以了。因为整个图形都是使用 border
绘制的,同时颜色缺省,所以所有图形颜色自动跟着一起变了。完整代码如下:
<a href class="add" title="继续上传">
添加图片
</a>
.add {
display: inline-block;
width: 76px;
height: 76px;
color: #ccc;
border: 2px dashed;
text-indent: -12em;
transition: color .25s;
position: relative;
overflow: hidden;
}
.add:hover {
color: #34538b;
}
.add::before, .add::after {
content: '';
position: absolute;
top: 50%;
left: 50%;
}
.add::before {
width: 20px;
border-top: 4px solid;
margin: -2px 0 0 -10px;
}
.add::after {
height: 20px;
border-left: 4px solid;
margin: -10px 0 0 -2px;
}
虽然 color:transparent
在 IE9 以上版本的浏览器才支持,但是 border-color: transparent
在 IE7 浏览器就开始支持了,于是,我们解决一些棘手问题的思路就更加开阔了。
在 CSS3 还没到来的时候,background
定位有一个比较大的局限性,就是只能相对左上角数值定位,不能相对右下角。这种特性有时候会给我们的工作带来一点儿麻烦。举个例子,假设现在有一个宽度不固定的元素,我们需要在距离右边缘 50 像素的位置设置一个背景图片,此时 background
属性就遭遇尴尬了:由于宽度不固定,所以无法通过设定具体数值来实现我们想要的效果,因为 background
是相对左上角定位的,我们的需求是右侧定位。
要实现上面的需求,方法挺多。其中一种方法就是使用透明边框,如下 CSS 代码:
.box {
border-right: 50px solid transparent;
background-position: 100% 50%;
}
此时,对 50px
的间距我们使用 transparent
边框表示,这样就可以使用百分比 background-position
定位到我们想要的位置了。因为,默认 background
背景图片是相对于 padding box 定位的,也就是说,background-position:100%
的位置计算默认是不会把 border-width
计算在内的。
即使在移动端,使用 CSS 的 border
属性绘制三角形等图形仍是性价比最高的方式。例如,一个朝下的等腰直角三角形,直接用:
div {
width: 0;
border: 10px solid;
border-color: #f30 transparent transparent;
}
则有下图所示的效果。