CSS中添加元素边框的三种方法

3,919 阅读7分钟

这篇是译文,原文地址 在CSS中,有时候边框并不是真正的边框。

在这篇文章中,我们会介绍下面三种添加边框方法的区别

  • border
  • outline
  • box-shadow

也会讨论每个方法的使用场景。

复习一下CSS的盒模型

三种实现边框的方法之间的关键区别是它们被放置在元素上的位置不同以及它们的渲染是否影响元素尺寸。这种行为是由盒模型决定的。

image.png

  • border元素的边界,位于marginpadding之间,它的宽度会影响元素尺寸
  • outline紧挨border,但在border外面,与box-shadow以及margin重叠,但不影响元素尺寸
  • 默认情况下,box-shadow会从border的边缘延伸出去,覆盖指定方面的空间,而且不影响元素尺寸

border语法及使用

自从网络出现以来,border一直是设计中的一个标准。

与其他两种属性(outline,box-shadow)比较,默认情况下,border是包含在元素的计算尺寸中的,即使你设置了box-sizing:border-box,边框仍然会被计算在内。

border最基本的语法是指定width(宽度)和style(样式)

border: 3px solid;

如果没有指定颜色,边框的默认颜色会是currentColor,即距离当前元素最近颜色定义(当前元素的color->父元素color->一直向上查找)。

border还有更多可选的样式,而且你可以使用border-style为每一面(top,right,bottom,left)定义不同的颜色。

访问 MDN 文档查看所有可用的border-style值及示例

border的使用场景

border是一个可靠的选择,当样式被计算在元素尺寸中是可以接受的情况下。而且默认的样式给了很多设计上的灵活性。

继续阅读下去,了解只有边框能实现的额外技巧。

outline语法及使用

要让outline显示,只需要提供一个样式(例如solid),因为默认是none

outline: solid;

像border一样,outline会默认使用currentColor作为颜色,此外,outline的默认的宽度是medium

outline的一个典型应用是在浏览器中为选中元素(例如按钮或者链接)提供一个聚焦样式。

出于无障碍的目的,这种特殊的应用应该被允许出现,除非你能提供一个符合 WCAG Success Criterion 2.4.7 Focus Visible标准的焦点样式。

出于设计的目的,一个常见的问题是outline不能设置圆角(border-raduis)。

outline的使用场景

当你不想影响元素的尺寸而且没有圆角的需求时,你就可以用outline实现和border一样的显示效果

box-shadow的语法及使用

box-shadow必需属性是偏移量(x,y)以及color(阴影颜色)

box-shadow: 5px 8px black;

第3个可选的参数是blur(模糊程度),第4个是spread(扩散程度)

请看我在egghead上的4.5分钟的视频演示,以了解更多扩展的语法,以及使用box-shadow的技巧。

为了模拟边框,我们将x,y和blur设置为0,只设置spread的值:

box-shadow: 0 0 0 3px blue;

这将在元素周围创建一个border的外观,而且可以继承圆角的样式。

image.png

box-shadow的使用场景

当你想要在不引起布局偏移的情况下对boder做动画处理时,就可以使用box-shadow。下一节将演示这种情况的一个例子。

而且,由于box-shadow是可以分层的(可以设置多个box-shadow),对于增强你的布局来说是个全面的好工具。

然而,它并不能完全模仿border和outline的一些样式。

总结

接下来是一些实际应用场景,你可能需要使用其他的属性代替border。

按钮的边框

一个常见的场景是,有边框的按钮无边框的按钮排列在一起的情况

image.png

一个常见的解决方案通常是增加没有边框的按钮的尺寸,让两个按钮尺寸相等。

运用我们刚学到的知识,一种替代的方式是使用box-shadowinset关键字模拟边框,让边框出现在按钮的内部。

注意为了避免覆盖文字内容,你的padding需要大于border-width。

此外,如果你想添加border的hover或者focus效果。使用border的话,会有不理想的视觉跳跃,因为border会在这种状态下增加元素尺寸。

在这种情况下,我们可以使用box-shadow来模拟边框来防止元素尺寸的增加,另外我们还可以使用transition来使用动画

下面是精简之后的关键代码

button {
  transition: box-shadow 180ms ease-in;
}

button:hover {
  box-shadow: 0 0 0 3px tomato;
}

升级你的CSS调试方式

为了弄清楚元素尺寸,特别是overflow:scroll或定位的问题,一种经典的调试方式是添加以下代码:

* {
  border: 1px solid red;
}

这会为每个元素添加一个红色的边框。

但是根据我们上面学到的,为元素添加border影响元素的计算尺寸,有可能带来额外的问题。

相反,使用下面的代码

* {
  outline: 1px solid red;
}

小测试:outline会被绘制到盒模型的哪个位置?为什么这种方式更好?

使用border的一个潜在后果是一旦内容被重新绘制,就会增加滚动条。当使用outline时,这种副作用就不会发生。

此外,你很可能已经为元素添加了边框,所以普遍地改变边框会导致布局的改变,这肯定会带来新的问题。

题外话:浏览器的DevTools也发展出了更复杂的方法来帮助你识别元素,Firefox甚至同时增加了一个 "scroll "和 "overflow "标签,在调试溢出的情况下很有帮助。我希望你花一些时间来学习更多关于DevTool的功能!

确保可见的焦点

对于可访问性,你可能不知道的一种情况是Windows高对比度模式(WHCM)的用户。

在这种模式下,你提供的颜色会被剥离成一个缩小的高对比度调色板。这种模式下很多属性都会被禁用,包括box-shadow

造成的影响是,如果你删除了focus时的outline,并将其替换为box-shadow,那么WHCM的用户焦点就不可见了。

为了避免上述影响,你可以在元素focus时为元素添加一个透明的outline

button:focus {
  outline: 2px solid transparent;
}

关于这个具体问题的更多背景,请回顾一下我的上一篇文章按钮样式指南

outline和Box-shadow的陷阱

因为outline和box-shadow在border的外面,你可能遇见的一个问题是它们在视口的边缘消失。因此,如果你想让它保持可见,你可能要给元素添加margin或者给body元素添加padding。

它们放置的位置也意味着它们可能被overflow:hidden或者clip-path等属性裁切掉。

小技巧: 渐变边框

正如上面承诺的那样,这里有一个技巧,在我们讨论过的方法中,只有border可以做到。

一个经常被遗忘的和border有关的属性是border-image。当试图将其用于实际的图像时,它的语法可能有点奇怪。

但它有一个隐藏的功能--它也允许你创建渐变的边框,因为CSS渐变在技术上就是图像。

这需要定义一个的边框宽度和样式(不管值是啥,都显示为solid),然后是border-image属性,它可以使用渐变的语法,只需要增加一个。linear-gradient后面的数字是slice值,我们可以就简单使用1,即不改变渐变的尺寸和偏移量。

div {
  border: 10px solid;
  /* simplified from preview image */
  border-image: linear-gradient(to right, purple, pink) 1;
}

要想只在一边放置边框,必须先把其他边框设置为零,否则有些浏览器仍会将其添加到所有边框。

div {
  border-style: solid;
  border-width: 0;
  border-left-width: 3px;
  /* border-image */
}

缺点是渐变的边框并不支持border-raduis,如果你需要一个支持border-radius的解决方案,可以看一眼ModernCSS主页上的解决方案。😉