你什么时候使用 inline-block?

Avatar of Chris Coyier
Chris Coyier

DigitalOcean 为您旅程的每个阶段提供云产品。 立即开始使用 200 美元的免费额度!

displayinline-block 值是一个经典! 它并不新鲜,浏览器支持肯定不是您需要担心的事情。 我相信我们很多人都凭直觉使用它。 但是让我们明确一下。它实际上对什么有用? 在什么情况下你会选择它而不是其他可能类似的选项?

按钮

我听到的最常见的答案是:我总是将其用于按钮。

最终,我认为这是有道理的,但它导致了我认为的轻微误解。 想法是,您希望看起来像按钮的元素(可能使用 <a><button> 或可能是 <input> 创建)以内联方式排列——就像它们自然那样——但能够拥有边距和填充。 这就是轻微误解的部分:display: inline; 元素仍然可以拥有marginpadding,并且它可能的行为与您期望的一样。

棘手的是

  • 内联元素上的块方向边距将完全被忽略
  • 内联元素上的填充不会影响文本行的高度

因此,虽然按钮本身的样式几乎都很好,但父元素和周围的文本可能不是。 这是一个 演示,它

来自内联按钮的填充使它们超出容器,这有点奇怪。

当内联按钮开始换行时,情况会变得更糟

所以是的,我想说在按钮上使用 inline-block 很有意义。 但是…

不要忘记 inline-flexinline-grid

使用 displayinline-flexinline-grid,您将获得与 inline-block 相同的所有良好行为,但元素(通常是按钮)可以从更强大的内联布局系统中获益。

以带图标的按钮为例,如下所示

<a href="#" class="button>
  <svg> ... </svg>
  Text
</a>

要使文本和图标完美地居中对齐,尝试这样操作很诱人

.button svg {
  vertical-align: middle;
}

但这永远无法完全正确……

至少在我看来,这些图标从中心向下偏移了一两个像素。

但这可以通过 inline-flex 轻松修复

.button {
  display: inline-flex;
  align-items: center;
}
完美对齐的图标(总有一天,我们将能够 使用 lh 单位 进行很好的调整!)

使用 inline-flexinline-grid,您可以在以内联方向布局的块内使用 flexbox 或 grid 布局系统的所有功能。

仍然可以换行的块

inline-block 元素将尊重 width 这是它们与普通 inline 元素之间的另一个区别。 人们过去¹ 使用 inline-block 构建列布局系统,因为它基本上可以执行浮动可以在这里执行的操作,但无需担心清除浮动²,让人们可以利用换行,换行的效果比浮动更优雅。

内联块表现为可以换行的列(甚至可以缩减到 1 列)的想法至今仍在延续,因为它是一种技巧,可以用于 HTML 电子邮件以实现多列布局,这些布局在小屏幕上会折叠成单列而无需使用媒体查询(某些电子邮件客户端不支持媒体查询)。

Dan 的示例.

内联元素上的 transform

内联元素不能使用 transform。 因此,如果您需要它,则需要将其设置为 inline-block

列子元素不会在其自身中间断开

CSS 列可用于您不关心任何给定段落是否跨列断开的文本段落。 但有时 CSS 列用于块,在这种情况下,这会很尴尬。 假设块有自己的背景和填充。 断裂在视觉上非常奇怪。

Screenshot. Three columns of paragraphs with a tan background and padding. The last paragraph of the first column breaks into the second column, leaving no bottom or top padding on it in the columns.

这是一个我不能说我 100% 理解的奇怪技巧,但如果您在这些框上添加 display: inline-block;(可能还有 width: 100%; 以确保它们保持列宽),那么它们就不会断裂,并且填充会保留。

演示

使列表水平排列的快速方法

这是我对原始推文提出的另一个非常受欢迎的答案。 列表元素会垂直堆叠列表项,就像块级元素一样。 它们实际上不是块。 它们是 display: list-item;,这在本文中实际上很重要,我们稍后会看到。 常用的用例是“当我想水平排列列表时”

所以您有一个列表…

<ul>
  <li>Three</li>
  <li>Little</li>
  <li>Piggies</li>
</ul>

您想将其水平排列,您可以…

li {
  display: inline-block;
}

搞定。

我用 VoiceOver 听了一下,inline-block 列表仍然将元素宣布为列表,但不会朗读项目符号,这是有道理的,因为它们不存在。 这就是将列表项本身的 displaylist-item 更改为其他值的问题:它们会失去其,嗯,列表项特性。

另一种方法是将父元素设为 flexbox 容器…

ul {
  display: flex;
}

…它实现了水平排列(flexbox 的默认值),但保留了项目符号,因为您没有更改列表项本身的 display。 如果您想要删除它们,则需要手动操作。

演示

居中列表

说到列表,Jeff Starr 刚刚发表了一篇关于 居中文本内的列表 的博文,这也会变得很尴尬。 尴尬之处在于,列表项内的文本可以居中,但列表项本身仍然是全宽,从而导致项目符号保持左对齐。

Screenshot. Shows an unordered list with centered list items. The text of the list items is centered, but the bulletpoints are still aligned to the left.

Jeff 的解决方案是将整个列表设置为 inline-block。 这使列表仅与内容的自然宽度一样宽,允许项目符号离开左边缘并随居中内容一起移动。 只要在前后有块级元素,这就是一个很好的解决方案。

作为替代方案,如果目标是将列表的宽度缩小到内容的宽度,则也可以 这样实现,而不会阻止列表成为块级。

ul {
  width: max-content;
  margin: 0 auto;
  text-align: left;
}

  1. inline-block 还有另一个棘手的问题。 与 inline 元素一样,它们之间的任何空白本质上都会呈现为空格。 因此,如果两个 50% 宽的 `inline-block` 元素之间有任何空白,它们将无法在一行上显示。 好消息是有技巧可以解决这个问题。
  2. 我说“过去”是因为,如果您今天要创建列系统,您几乎肯定会使用 flexbox 或 grid——或者根本不构建“系统”,因为仅使用这些系统的语法就很大程度上消除了对系统的需求。