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

325 阅读7分钟

当涉及到CSS时,有时border ,而不是真的border

在这一集里,我们将介绍两者之间的区别:

  • border
  • outline
  • box-shadow

我们还将讨论什么时候可以使用一个而不是另一个。

复习一下CSS盒式模型#的内容

我们的三种边框方法之间的一个关键区别是它们被放置在元素上的位置,以及它们如何影响其尺寸。这种行为是由CSS盒状模型控制的:

An illustration of the CSS box model, with the relevant parts described following this image

  • border 正好是元素的边界,位于它的padding和margin之间,它的宽度会影响计算出的元素尺寸。
  • outline 挨着但在border 之外,与box-shadowmargin 重叠,但不影响该元素的尺寸。
  • 默认情况下,box-shadow 从边框的边缘延伸出去,覆盖定义的方向的空间,它也不会影响元素的尺寸。

border 语法和使用方法

自从网络诞生以来,边框一直是设计中的一个标准。

与我们将要介绍的其他两种方法相比,一个重要的区别是,默认情况下,边框是包含在一个元素的计算尺寸中的。即使你设置了box-sizing: border-box ,边框仍然会被计算在内。

边框最基本的语法是定义它的宽度和样式:

border: 3px solid;

如果没有定义,默认的颜色将是currentColor ,这意味着它将使用级联中最近的color 的定义。

但边框还有更多的样式,如果你愿意,使用border-style ,你可以为每一面定义不同的样式。

什么时候使用border#

边界是一个可靠的选择(双关语),当它可以接受在元素的尺寸中计算出的样式。而且默认的样式提供了很多设计上的灵活性。

继续阅读关于只有border 才能做到的额外提示!

outline 语法和使用方法

对于轮廓,使其可见的唯一必要属性是提供一个样式,因为默认的是none :

outline: solid;

像边框一样,它将通过currentColor 获得颜色,它的默认宽度是medium

outline 的典型应用是通过本地浏览器的样式在:focus 的交互式元素,如链接和按钮。

为了无障碍性的目的,这种特殊的应用应该被允许出现,除非你能够提供一个符合WCAG成功标准2.4.7焦点可见的自定义:focus 样式。

为了设计的目的,经常注意到的一个问题是outline ,它不能从任何border-radius 样式中继承曲线。

什么时候使用outline

当你不想影响元素的尺寸时,使用outline 可能是可取的,而且你不需要它遵循border-radius. 它恰好使用与border相同的样式值,所以你可以实现类似的外观。

box-shadow 语法和使用方法#

box shadow 所需的最小属性是xy 轴的值和一种颜色:

box-shadow: 5px 8px black;

可以选择添加第三个单元来创建blur ,并添加第四个单元来添加spread

为了使用它来创建一个边框,我们设置xy 轴值以及blur0 。然后为spread 设置一个正数。

box-shadow: 0 0 0 3px blue;

这将在元素周围创建一个边框的外观*,*它甚至可以跟随一个应用的border-radius

an element using box-shadow in place of a border for the effect of a rounded blue border

什么时候使用box-shadow#

你可能更喜欢box-shadow ,特别是当你想在不引起布局偏移的情况下对边框进行动画处理。下一节将演示这种情况的一个例子。

而且,由于box-shadow 可以分层,它是一个全面的好工具,可以了解它来增强你的布局。

然而,它将无法完全模仿borderoutline 所提供的一些样式。

把这一切放在一起

下面是一些你可能需要使用border 的实际场景。

按钮边框

真正的border 成为一个问题的常见情况是,当为有边框和无边框的按钮提供样式时,以及它们互相排在一起的情景。

a button using a border which appears visually larger than the second button with a background but no border

一个典型的解决方案通常是增加无边框按钮的尺寸,使其等于border-width

我们的新知识的另一个解决方案是使用box-shadowinset 关键字,将伪边框直观地放在按钮

updated styles using box-shadow on the first button resulting in the buttons appearing equal size

注意,你的padding必须大于border-width ,以防止文本内容的重叠

另外,也许你想在:hover:focus添加边框。使用真正的border ,你会有一个不理想的布局转换的视觉跳跃,因为border 会短暂地增加这些状态下的尺寸。

demo of a border being added on hover and causing the button to jump in place

在这种情况下,我们可以使用box-shadow 来创建伪边框,这样真实的尺寸就不会增加--另外我们可以使用transition 来制作动画。

demo of the box-shadow border on hover which no longer causes the button to jump

下面是上述例子的简化代码:

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

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

升级你的CSS调试方法

一个经典的CSS笑话是,要弄清CSS的问题,特别是溢出滚动或定位的问题,就是添加:

* {
  border: 1px solid red;
}

这将给每个元素添加一个红色边框。

但正如我们所了解的,这也会影响它们的计算尺寸,从而有可能意外地给你带来额外的问题。

相反,使用:

* {
  outline: 1px solid red;
}

流行问答outline ,这将被放置在哪里,为什么这是一个更好的解决方案?

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

此外,你很可能已经在为元素使用border ,所以普遍地改变border ,将导致布局的转变,这当然可能会带来新的问题。

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

确保可见的焦点

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

在这种模式下,你提供的颜色被剥离成一个缩小的高对比度调色板。不是所有的CSS属性都被允许,包括box-shadow

一个实际的影响是,如果你在:focus ,并以box-shadow 取代了outline ,那么WHCM的用户将不再获得可见的焦点。

为了消除这种负面影响,你可以在:focus 上应用一个transparent 的轮廓。

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

outlinebox-shadow#的陷阱

因为outlinebox-shadow 在盒子模型中位于边框之外,你可能会遇到的一个后果是让它们在视口的边缘消失。body 因此,如果你想让它保持可见,你可能需要在元素上添加margin ,或者在padding ,作为一种对策。

它们的位置也意味着它们可以被overflow: hidden 或使用clip-path 等属性剪切掉。

额外提示:渐变的边框

正如我们所承诺的,这里有一个额外的提示,在我们所讨论的方法中,只有border 能做到这一点。

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

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

preview of an element that has a pastel rainbow gradient applied with the text "Hello World"

这需要定义一个常规的边框宽度和样式(尽管它只会显示为solid ,而不考虑样式值),然后是border-image 属性,该属性可以使用梯度语法,只需添加一个。梯度后面的数字是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-radius ,所以如果你需要一个尊重的解决方案,你可以用Inspector偷看一下ModernCSS主页上的卡片是如何添加梯度的😉。