在上一章中,我们研究了你如何使用 Tailwind 来控制单个 DOM 元素的显示。在这一章中,我们将看一下 Tailwind 如何管理多个元素的布局。

通过 Tailwind,你可以在整个页面上布局元素,并管理导航、侧边栏和页脚等常见功能。你还可以使用 Tailwind 在一个页面中把复杂的元素组合起来,如卡片或英雄块。让我们从 Tailwind 提供的一些通用工具开始,以帮助在页面上放置元素:盒子与盒子的关系。

容器

许多 CSS 框架使用一个容器类作为一般的顶级容器来指定页面宽度。虽然 Tailwind 确实提供了一个容器实用类,但 Tailwind 的版本比其他框架中的类似类的作用要小得多。在 Tailwind 中,所有的容器工具都是根据浏览器视口的宽度来指定该元素的最大宽度。例如,任何宽度在 640 到 768 像素之间的视口将被设置为最大宽度为 640 像素。一旦视口超过 768,最大宽度就会保持在 768 像素,直到视口达到 1024 像素,然后在视口达到 1280 像素时再次跳转。

使用容器的好处是,它允许你在设计中只担心这些特定的宽度,而不必考虑视口可能有的任何宽度。

:::info

视口(Viewport)

在 CSS 中,视口是用户可以看到内容的浏览器区域。通常,人们关注的尺寸是视口的宽度,因为这决定了在屏幕上可以放置多少内容而不需要水平滚动。HTML 元标签被用来控制移动屏幕上的视口宽度。在默认情况下,移动浏览器通常会假定显示屏比实际设备更宽(通常为 980 像素),并将内容按比例放大以适应屏幕。这通常看起来很糟糕。你应该使用 content="width=device-width,initial-scale=1" 属性,让浏览器使用设备的尺寸作为视口,而不是从较宽的尺寸中缩小显示。 :::

如果你熟悉其他框架,Tailwind 的容器不会有你可能期待的功能。一个 Tailwind 容器不会自动将其子元素水平居中。为了获得居中行为,你需要将容器与 mx-auto 配对。一个 Tailwind 容器也不会引入一个 Padding 或 Margin 来使其元素远离浏览器的边界。为了获得这种行为,你将容器与 m-p-实用类配对。因此,你的顶层元素的一个合理的类列表可能是 class="container mx-auto py-12 px-6"

浮动和清零

尽管一个全新的设计可能会使用本章其余部分所描述的网格和弹性框工具来定位元素,但如果你在一个传统的项目中使用 Tailwind,你可能仍然需要处理浮动和清零的问题。

在 CSS 中,float 属性将内容定位在其容器内。通常,浮动属性被用来定位一个特定的元素,通常是一个图像,在其容器的一侧或另一侧,允许容器的其他部分,通常是文本,完全留在另一侧,而不是将这些元素混在一起。

Tailwind 为位置提供了 float-leftfloat-right,以及 float-none 作为一个重置选项。

CSS 的清除属性迫使一个元素被放置在它可能与之重叠的任何元素的下面,或者两边。(技术上讲,它可以防止其他元素浮动,这相当于同样的事情)。Tailwind 提供了一些实用工具,以指定在任何一边、两边或不在任何一边的清除行为:clear-leftclear-rightclear-bothclear-none

位置和 Z-Index

在 CSS 中,z-index 属性是一个整数,它决定了如果你在垂直于屏幕的方向上向外运行一个轴,那么项目是如何沿着 “z 轴” 相互堆叠的。Tailwind 提供的模式是 z-{index},其中索引可以是0、10、20、30、40、50 或 auto。你可以通过使用 -z 模式,即 -z-20,或者用一个任意值 z-[-1]来使用这些值的负的 z- 索引。

表格

HTML 页面的经典间隔方式是表格。除非你实际上是在显示表格数据,否则就布局而言,现在更倾向于使用 CSS 网格,所以 Tailwind 并没有提供许多具体的表格实用类。

Tailwind 让你使用 table-auto 来保持默认的浏览器行为,即根据表格的内容来自动调整其列距。如果你想明确指定列的宽度,你可以在 <table> 元素上使用 table-fixed,然后在表格的每一列上放置一个明确的宽度帮助器 —— 小数点帮助器在这方面很有用:

  1. <table class="table-fixed border border-collapse">
  2. <tr>
  3. <th class="border border-black w-1/6">Small</th>
  4. <th class="border border-black w-2/6">Medium</th>
  5. <th class="border border-black w-3/6">Large</th>
  6. </tr>
  7. </table>

image.png
border-collapse 实用类的帮助下,Tailwind 还可以让你合并相邻表格单元格的边框,这是可以用 border-separate 重置的。

Tailwind 提供了 odd:even: 模式,以给表格交替提供行的颜色,例如 class="odd:bg-white even:bg-gray-300"

网格

第一轮 CSS 框架的伟大创新之一是对网格布局的支持,你可以很容易地把东西放在 12 列的网格上。网格间距的存在使页面布局变得更加容易。随着时间的推移,这些框架变得更加灵活,最终网格支持被直接内置到了 CSS 中。

网格仍然是很多布局选择的好帮手,Tailwind 为使用 CSS 网格属性设置网格布局提供了有用的工具。首先,有一个 grid,它是 CSS 属性 display: grid 的一个工具。你需要把 grid 实用类作为你的网格顶层的类列表的一部分,在网格的各个元素之上。

一旦你创建了一个网格元素,你可以使用 Tailwind 来指定该网格的行数或列数。你还可以调整网格中各个元素的行为。你可以为网格中的元素指定一个起点或终点,你可以指定该元素所占的行或列的跨度,或者你可以改变网格内每个元素的间距。

网格最常见的用途是将页面分成一系列的列,你可以在 Tailwind 中使用 grid-cols-{count} 帮助器来实现。这些工具从 .grid-cols-1.grid-cols-12,每一个都将页面分隔成那么多列。重置网格的方法是 grid-cols-none

与其他一些 CSS 网格框架不同,你不需要明确指定行。在一个网格内,CSS 会根据你声明的列数自动向下填充到下一行。例如,你可以使用这样的东西:

  1. <div class="grid grid-cols-2 w-1/4 gap-4">
  2. <div class="border bg-gray-300 text-center">A</div>
  3. <div class="border bg-gray-300 text-center">B</div>
  4. <div class="border bg-gray-300 text-center">C</div>
  5. <div class="border bg-gray-300 text-center">D</div>
  6. </div>

你会得到一个 2x2 的网格,A 和 B 在顶行,C 和 D 在底行,像这样:
image.png
CSS 网格的一个很酷的功能,在其他一些 CSS 框架中很难做到,就是你可以通过指定行数来使用 90 度的扭曲。在 Tailwind 中,这是用 grid-rows-{count} 帮助器完成的,它的后缀可以是 1 到 12 或者没有。

你还可以指定数据在网格中的流动方向。默认情况下,grid-flow-row会使网格内的元素以行为单位水平流动,正如你在前面的例子中看到的那样。这是你可能熟悉的 DOM 元素的正常行为。

或者你可以使用 grid-flow-col,在这种情况下,网格中的元素会垂直地逐列填充,就像这样:

  1. <div class="grid grid-rows-2 w-1/4 gap-4 grid-flow-col">
  2. <div class="border bg-gray-300 text-center">A</div>
  3. <div class="border bg-gray-300 text-center">B</div>
  4. <div class="border bg-gray-300 text-center">C</div>
  5. <div class="border bg-gray-300 text-center">D</div>
  6. </div>

这给你一个 2x2 的网格,但 A 和 B 是左列,而 C 和 D 是右列,像这样:
image.png
正如你在前面的例子中所看到的,你可以用方便命名的 gap-{size} 助手在表格单元格之间添加一个间隙,它的后缀是间隙的大小,使用与我们看到的填充和边距相同的 “从 0 到 96 的一些数字,还有 px” 测量方案。如果你想让间隙的大小仅是水平的,你可以使用 gap-x-{size}。而如果你想让间隙只在垂直方向上,就用 gap-y-{size}

跨度

与 CSS 表格一样,有时你想让一个单元格覆盖多于一行或一列。Tailwind 提供了两种方法来管理这个问题:spanstart/end

使用 span,你可以用 col-span-{count}row-span-{count} 来指定你希望单元格占用的列数或行数,其中的后缀是列数或行数。默认是 col-span-1row-span-1。重置的辅助工具是 col-span-autorow-span-auto

重要的是,流动行为仍然继续。如果你在第一个元素上添加一个跨度,我们的四单元的例子就是这样:

  1. <div class="grid grid-cols-2 w-1/4 gap-4">
  2. <div class="border bg-gray-300 text-center col-span-2">A</div>
  3. <div class="border bg-gray-300 text-center">B</div>
  4. <div class="border bg-gray-300 text-center">C</div>
  5. <div class="border bg-gray-300 text-center">D</div>
  6. </div>

image.png
您还可以逐行跨元素:

  1. <div class="grid grid-cols-2 w-1/4 gap-4">
  2. <div class="border bg-gray-300 text-center row-span-2">A</div>
  3. <div class="border bg-gray-300 text-center">B</div>
  4. <div class="border bg-gray-300 text-center">C</div>
  5. <div class="border bg-gray-300 text-center">D</div>
  6. </div>

image.png

起和止

你可以通过用 col-start-{column}col-end-{column} 或者 row-start-{row}row-end-{row} 来指定网格项目的开始和结束,其中后缀是位置的编号或者重置值 auto,来调整网格项目的位置。关键点是最低的开始位置是 1,结束位置是排他的,意味着它不是项目的一部分。将一个项目声明为 class="col-start-2 col-end-4" 意味着该元素将包括第 2 列和第 3 列,但不包括第 4 列。

默认情况下,开始和结束的位置是由前面的项目在网格中的位置自动决定的,跨度是 1。 你可以指定开始、结束和跨度项目中的任何两个,布局就会正常。例如,class="col-span-3,col-end-5" 将占用第 2、3、4 列,横跨 3 列,在第 5 列前结束。

分栏

如果你想要一个更经典的杂志布局,你可以使用列流,这也适用于照片布局。

你以两种方式之一在 Tailwind 中指定列式布局。你可以用 column-{count} 的模式指定从 1 到 12 的任何列数。另外,你可以用 column-{size} 按宽度指定列,其中列的范围从 2xsxssmmdlgxl,然后是 2xl7xl。宽度不规则地从 16rem 到 80rem,你可以用方括号符号 column-[{size}] 指定一个任意的宽度。使用 column-auto 可以重新设置列。就像使用网格一样,你可以使用类的间隙系列来分隔列。

Flexbox

Flexbox 是一种安排多个相关元素的不同方式。网格被设计成二维布局,而弹性框布局是一维的,在一行或一列中一个接一个地放置项目。

我意识到这听起来不如一个完整的网格有用。但是,灵活盒对你来说可能比网格布局更有用,原因有三:

  • Flexbox 容器对动态管理元素的大小有更好的控制。
  • 虽然从概念上讲,Flexbox 容器是一个单一的行,但当内容变得太宽时,它可以在屏幕上自动包裹其内容。
  • Flexbox 容器可以嵌套,这意味着你可以从一个 Flexbox 行开始,但该行内的元素本身可以是 Flexbox 列,这又可以包含 Flexbox 行。嵌套的 Flexbox 为你提供了很多控制布局的选择。

网格对于管理具有表格性质的内容还是很有用的,这在一些数据显示中是真实的,但不是每一种布局都是如此。

想想一个常见的页面结构,你有一个全宽的页眉,下面是左右两个侧边栏,中间是主要内容,再下面是全宽的页脚。你可以把这种布局看作是一个网格:页眉是网格的第一行,有一个元素,列跨度为 3。第二行有三个元素,分别是边栏和主要内容,宽度调整后,第三行有另一个元素,列跨度为 3,像这样:

  1. <div class="grid grid-cols-3 gap-4 w-1/3">
  2. <div class="text-center col-span-3">Header</div>
  3. <div class="text-center w-1/5">Left Sidebar</div>
  4. <div class="text-center w-3/5">Content</div>
  5. <div class="text-center w-1/5">Right Sidebar</div>
  6. <div class="text-center col-span-3">Footer</div>
  7. </div>

这还不错,但你也可以把布局看成是一个 Flexbox。你的 Flexbox 可以是一个有三个元素的列,其第二个元素是一个有三个元素的行,就像这样(我们稍后会看一下这些实用程序的含义):

  1. <div class="flex flex-col w-1/3">
  2. <div class="flex-grow">Header</div>
  3. <div class="flex flex-row">
  4. <div class="text-center w-1/5">Left Sidebar</div>
  5. <div class="text-center w-3/5">Content</div>
  6. <div class="text-center w-1/5">Right Sidebar</div>
  7. </div>
  8. <div class="flex-grow">Footer</div>
  9. </div>

或者,你可以把这个页面看作是一个单行,恰好像这样包起来:

  1. <div class="flex flex-row flex-wrap w-1/3">
  2. <div class="w-full">Header</div>
  3. <div class="text-center w-1/5">Left Sidebar</div>
  4. <div class="text-center w-3/5">Content</div>
  5. <div class="text-center w-1/5">Right Sidebar</div>
  6. <div class="w-full">Footer</div>
  7. </div>

所有这三种方法都会给你或多或少的这种布局:
image.png
事实证明,Flexbox 比网格更,更灵活。特别是,Flexbox 布局更容易适应不同的屏幕尺寸。

方向和轴

Flexbox 如何布局元素的基础是它的方向,这是你用 Tailwind 工具设置的。方向可以是水平的,用 flex-row,也可以是垂直的,用 flex-column。你可以用 flex-row-reverseflex-col-reverse 在你的流程中向后走。流动方向的轴被称为主轴,而另一个方向被称为交叉轴。

在 Tailwind 中,父级 Flexbox 容器必须包括类 flex(与网格需要有类 grid 的方式相同)。

关于行的方向,需要知道的一个重要事情是,它不一定是从左到右;行的流动方向是文本的方向。所以,如果你将你的文本国际化,比如说,希伯来语,你所有的 Flexbox 将自动翻转方向。列的主轴总是从上到下。

顺序和包裹

Flexbox 的下一个最重要的属性是它是否会包起来,这是该盒子的父类的属性。默认情况下是不包裹,即 flex-no-wrap,但如果你指定了 flex-wrap,那么如果项目会溢出容器的主轴,你的行容器会自动将项目移到下一行。通常情况下,这将是超过行 Flexbox 的宽度,但你也可以明确设置列框的高度,并让它包起来。如果由于某种原因,你生活在颠倒世界中,Tailwind 提供了 flex-wrap-reverse

你可以用 order-{integer} 实用类明确指定 Flexbox 中元素的顺序,其中后缀是 1 到 12 之间的任何整数,或者你可以使用 order-firstorder-lastorder-none。如果你有超过 12 个项目,这也是一个使用任意值语法的好地方,比如 order-[42]。如果为 Flexbox 中的一个或多个元素指定了顺序,那么该顺序属性就决定了该元素在盒子中的位置,而不是该元素在源 HTML 中出现的顺序。

这个属性的一个伟大用途是允许主要内容在源顺序中排在其他元素之前,但仍能正确显示。这段代码提供了与前面所示片段相同的布局:

  1. <div class="flex flex-row flex-wrap w-1/3">
  2. <div class="text-center w-3/5 order-3">Content</div>
  3. <div class="w-full order-1">Header</div>
  4. <div class="text-center w-1/5 order-2">Left Sidebar</div>
  5. <div class="text-center w-1/5 order-4">Right Sidebar</div>
  6. <div class="w-full order-5">Footer</div>
  7. </div>

你想这样做的一个原因是,允许自适应屏幕阅读器快速进入内容,同时仍然允许页面的视觉显示将内容放在中间。

弹性伸缩

Flexbox 中的 Flex 来自于 Flexbox 容器动态改变其项目大小和位置的能力。Tailwind 为您提供了对通用默认值的访问。这些是放置在 Flexbox 内的元素上的属性,而不是放在父类上的属性。

如果你想指定一个 Flexbox 内的元素的大小,你可以使用 basis-{size} Tailwind 类,它使用了 CSS 标准,使用 CSS 的 flex-basis 属性。Flex basis 指定了元素沿着 Flex 的主轴的尺寸,意味着行框的宽度和列框的高度。如果设置了,Flex basis 将被用来代替 Flexbox 内元素的适用宽度或高度属性。base 的尺寸选项与宽度的选项几乎相同。你有一套相同的标准数字,最低为 0,最高为 80,再加上半数、三分之二、四分之一、五分之一、六分之一和十二分之一的分数,加上 autopxfull,所以 basis-4basis-3/5,或 basis-auto。请记住,你可以选择任意值,如 basis-[20px]

如果没有指定具体的宽度,Flexbox 将增长或缩小其中的项目以填补可用空间。如果你不希望一个特定的项目增长或收缩,你可以将其指定为 flex-none,这将使其保持默认尺寸。如果你希望项目能够根据需要增长或收缩,以填补容器的可用尺寸,你可以使用 flex-autoflex-1。两者之间的区别是,flex-auto 从每个元素的默认尺寸开始,然后为每个能够增长或缩小的元素增加或减少尺寸,而 flex-1 将每个项目重置为零尺寸,并为所有项目平均分配空间,无论其自然尺寸如何。一般来说,在一组项目上使用 flex-1 会给你同等大小的项目,而 flex-auto 则不会。

你可以选择指定缩减行为而不触及增长行为。要允许收缩,使用 flex-shrink,要防止收缩,使用 flex-shrink-0。同样地,flex-growflex-grow-0 允许和防止元素增长,而不影响收缩行为。

对齐

除了使用 Flexbox 来放置页面上的项目外,Tailwind 还包括一些实用工具,允许你在 Flexbox 内对元素的对齐和调整进行更具体的处理。这些实用类也适用于网格布局,在适当的时候。

我说过,一个弹性框容器有一个主轴和一个横轴。影响沿主轴放置的 Tailwind 实用都以 justify- 开头,而影响横轴放置的实用类则没有。这些名称的选择是为了与底层 CSS 属性的名称相匹配。

主轴

让我们先看一下主轴。项目的放置可以通过两种方式沿主轴指定:项目沿整个 Flexbox 的主轴放置,以及单个项目沿 Flexbox 容器内自己的盒子的主轴放置。这两种放置方式都可以单独定义,并包括属于父级 Flexbox 容器属性的实用程序,而不是单个元素。

当沿主轴放置元素时,如果项目的总宽度小于 Flexbox 容器的宽度,Tailwind 包括了如何放置项目的实用程序。这些工具可以控制如何分配额外的间距。

三个实用类将元素尽可能地挤压在一起:

  • justify-start:根据文本方向,将元素放在轴的开头
  • justify-end:将项目放在轴的结尾
  • justify-center:将项目居中,这是长期以来 CSS 的困扰

三个实用类给元素留出空间,它们的不同之处在于间距的具体位置:

  • justify-between:将第一个元素放在 Flexbox 的开头,最后一个元素放在 Flexbox 的结尾,然后在内部元素之间留出均匀的间距。如果 Flexbox 有三个项目,你会得到两个大小相同的空间,模式为 AxBxC。
  • justify-evenly:在每个项目周围放置相等的空间。如果 Flexbox 有三个项目,则在其周围放置四个相同大小的空间,模式为 xAxBxCx。
  • justify-around:在每个项目的每一侧放置相同的间距。在实践中,这使得末端间距小于内部空间,因为每个内部空间包含了一个元素的左边空间和另一个元素的右边空间。如果 Flexbox 有三个项目,就会在它们周围放置六个同样大小的空间,模式为 xAxxBxxCx。

一个元素在其单独的盒子里的放置可以用容器上的一个类来控制,选项是 justify-items-startjustify-items-endjustify-items-center 来放置。如果你想让项目扩展以填满它的空间,你有 justify-items-stretch,而重置选项是 justify-items-auto。请注意,你通常会使用普通的 justify- 来给项目留出空间,或者使用 justify-items- 来给它的盒子里的项目留出空间,但你通常不需要同时这样做。如果盒子里的单个元素想要覆盖容器的对齐方式,你可以使用 justify-self-{option},其选项与 justify-items 相同。

交叉轴

横轴上的工具都是与主轴上的工具类似的。取代 justify-,Tailwind 提供了content-,有同样的六个选项,所以 content-start 将项目推到多行 Flexbox 的顶部,而 content-center 将它们垂直居中。

对于一个单独的项目,你有与 justify-items- 相同的五个选项,但前缀是简单的 items-。所以 items-center 垂直地将项目沿横轴居中。同样地,自我覆盖也有同样的五个选项,但前缀只是 self-,如 self-startself-center

最后,你可以用前缀 place-content-place-items-place-self- 同时管理两个轴,其结果相当于同时完成了主轴和横轴的间距。所以 place-content-center 相当于 justify-centercontent-center 的组合,而 place-items-start 则相当于 justify-items-startitems-start

现在,让我们看看如何使这些 Tailwind 工具提供更多的动态行为。