手中有刀,心里有佛

CSS 布局和定位 (CSS Display & Position)


CSS 中的布局 display 和定位 position 可以说是两个最基本的属性,其控制着元素在网页中的显示方式。之前对布局和定位可谓是一知半解,最终奏不奏效全凭一顿乱试😂,想了想还是应该细致地了解下,后面虽不妄想写起代码来事半功倍,但至少不会再暴力遍历破解了。

盒模型

在介绍布局和定位之前,首先回顾一下 CSS 的盒模型。CSS 盒模型从外到内由外边距 margin边框 border内边距 padding内容 content 共 4 部分组成,如下图所示:

CSS 盒模型

元素的宽度 width 为内容的宽度 + 左边框 + 有边框 + 左内边距 + 右内边距,上例中为 $360+10+10+10+10=400$;元素的的高度 height 为内容的高度 + 上边框 + 下边框 + 上内边距 + 下内边距,上例中为 $240+10+10+20+20=300$。在实际中,我们并不能直接设定内容的宽度和高度,只能设置元素的宽度和高度,而显示区域的宽度和高度则通过计算自动设定。

在 CSS 中广泛使用的有两种盒子模型:块级盒子(block box)内联盒子(inline box)1

块级盒子有如下表现行为:

除非特殊指定,诸如标题 (<h1> 等) 和段落 (<p>) 默认情况下都是块级的盒子。

内联盒子有如下表现行为:

<a><span><em> 以及 <strong> 都是默认处于 inline 状态的。

布局

在 CSS 中使用 display 属性控制元素的布局方式,上文中的 blockinline 是最常用的两种布局方式。除此之外还有一种介于块级盒子和内联盒子之间的布局方式,即 inline-block,其具有如下表现行为:

这是一段包含 span 元素的文本。display: inline 的 span 元素的 width 和 height 属性无法发挥作用。

这是一段包含 span 元素的文本。display: inline-block 的 span 元素的 width 和 height 属性可以发挥作用。

上图分别展示了 display: inlinedisplay: inline-block 两种布局 span 元素的显示差异。

弹性布局

本节内容主要参考自:A Complete Guide to Flexbox

弹性布局(Flexbox Layout,Flexible Box Layout) 旨在提供一种更加有效的方式来布局、对齐和分配容器中元素之间的空间,即使元素的大小是未知或动态的,这也就是称为“弹性”的原因。

弹性布局是一套完整的模块而非一个单一的属性,其中一些属性要设置在父元素(flex container) 上,一些属性要设置在子元素(flex items) 上。常规布局是基于块级元素和内联元素的的流向,而弹性布局是基于弹性流向(flex-flow directions)。下图展示了弹性布局的基本思想:

Flexbox 基本思想

父元素属性

display

该属性启用弹性容器,为其子元素开启弹性上下文。

.container {
  display: flex; /* 或 inline-flex */
}

flex-direction

该属性定义了弹性流向,即基本思想中的 main-axis

.container {
  flex-direction: row | row-reverse | column | column-reverse;
}

flex-wrap

默认情况下会将子元素放置在一行中,该属性用于设置换行模式。

.container {
  flex-wrap: nowrap | wrap | wrap-reverse;
}

flex-flow

该属性是 flex-directionflex-wrap 两个属性的简写。

.container {
  flex-flow: column wrap;
}

justify-content

该属性用于设置主轴(main axis)方向的对齐方式。

.container {
  justify-content: flex-start | flex-end | center | space-between | space-around | space-evenly | start | end | left | right ... + safe | unsafe;
}

align-items

该属性用于设置交叉轴(cross axis)方向的对齐方式。

.container {
  align-items: stretch | flex-start | flex-end | center | baseline | first baseline | last baseline | start | end | self-start | self-end + ... safe | unsafe;
}

align-content

该属性用于设置当交叉轴上有额外的空间时容器多行的内部对齐方式,类似 justify-content 设置主轴上子元素的对齐方式。

注意

该属性仅对包含多行子元素的容器有效。
.container {
  align-content: flex-start | flex-end | center | space-between | space-around | space-evenly | stretch | start | end | baseline | first baseline | last baseline + ... safe | unsafe;
}

gap, row-gap, column-gap

该属性用于控制子元素之间的间距,其仅用于非边缘子元素之间的间距。

.container {
  display: flex;
  ...
  gap: 10px;
  gap: 10px 20px; /* row-gap column gap */
  row-gap: 10px;
  column-gap: 20px;
}

该属性产生的行为可以认为是子元素之间的最小间距。

子元素属性

order

默认情况下,子元素按照代码顺序排列。该属性可以控制子元素在容器中的顺序。

.item {
  order: 5; /* 默认为 0 */
}

flex-grow

该属性定义了子元素在必要时的扩张能力,其接受一个整数比例值用于设定子元素占用容器的空间。如果所有子元素的 flew-grow 都设置为 1,则所有子元素将评分容器的剩余空间;如果一个子元素的 flex-grow 设置为 2,则该子元素将尝试占用其他子元素 2 倍大小的空间。

.item {
  flex-grow: 4; /* 默认为 0 */
}

flex-shrink

该属性定义了子元素在必要时的收缩能力。

.item {
  flex-shrink: 3; /* 默认为 1 */
}

flex-basis

该属性定义了分配剩余空间之前子元素的默认大小。其可以为例如 20%5rem 之类的长度或一个关键字。

.item {
  flex-basis:  | auto; /* 默认为 auto */
}

flex

该属性是 flex-growflex-shrinkflex-basis 三个属性的简写。

.item {
  flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
}

align-self

该属性可以覆盖由 align-items 指定的对齐方式。

.item {
  align-self: auto | flex-start | flex-end | center | baseline | stretch;
}

网格布局

本节内容主要参考自:A Complete Guide to CSS Grid

网格布局(Grid Layout) 是一种基于网格的布局系统,相比于沿轴线 一维布局 的弹性布局,网格布局可以看做是一种 二维布局

核心概念

网格容器

网格容器即属性 displaygrid 的元素,其为所有网格项目的直接父级。如下示例中,container 即为网格容器:

<div class="container">
  <div class="item item-1"> </div>
  <div class="item item-2"> </div>
  <div class="item item-3"> </div>
</div>

网格项目

网格项目为网格容器的直接后代。如下示例中,item 即为网格项目,但 sub-item 不是:

<div class="container">
  <div class="item"> </div>
  <div class="item">
    <p class="sub-item"> </p>
  </div>
  <div class="item"> </div>
</div>

网格线

网格线即构成网格结构的分界线。其可以是位于行或列任意一侧的垂直或水平线。如下示例中,黄色的线为一条列网格线:

网格单元

网格单元即两个相邻行和两个相邻列之间的区域。如下示例中,黄色区域为行网格线 1 和 2 以及列网格线 2 和 3 之间的单元格:

网格轨道

网格轨道即 2 条相邻网格线之间的区域,可以将其视为网格的行或列。如下示例中,黄色区域为第 2 行和第 3 行网格线之间的网格轨道:

网格区域

网格区域即 4 条网格线包围的区域,一个网格区域可以由任意数量的网格单元组成。如下示例中,黄色区域为行网格线 1 和 3 以及列网格线 1 和 3 之间的网格区域:

父元素属性

display

该属性启用网格容器,为其子元素开启网格上下文。

.container {
  display: grid | inline-grid;
}

grid-template-columns, grid-template-rows

该属性通过空格分隔的值列表定义网格的列和行,值代表轨道的大小。值列表包括:

.container {
  grid-template-columns: ...  ...;
  /* 例如:
      1fr 1fr
      minmax(10px, 1fr) 3fr
      repeat(5, 1fr)
      50px auto 100px 1fr
  */
  grid-template-rows: ... ...;
  /* 例如:
      min-content 1fr min-content
      100px 1fr max-content
  */
}

网格线默认将会被分为正整数(-1 作为最后一个的替代值)。

同时也可以明确指定这些线的名称,请注意括号命名语法:

.container {
  grid-template-columns: [first] 40px [line2] 50px [line3] auto [col4-start] 50px [five] 40px [end];
  grid-template-rows: [row1-start] 25% [row1-end] 100px [third-line] auto [last-line];
}

请注意,一个行或列可以有多个名称:

.container {
  grid-template-rows: [row1-start] 25% [row1-end row2-start] 25% [row2-end];
}

使用 repeat() 可以简化重复项:

.container {
  grid-template-columns: repeat(3, 20px [col-start]);
}

上述代码等效于:

.container {
  grid-template-columns: 20px [col-start] 20px [col-start] 20px [col-start];
}

如果多行或多列共享相同的名称,可以通过行名或列名和计数来引用它们:

.item {
  grid-column-start: col-start 2;
}

fr 单位允许将轨道的大小设置为网格容器可用空间的一定比例。例如,如下示例将每个项目设置为容器宽度的三分之一:

.container {
  grid-template-columns: 1fr 1fr 1fr;
}

可用空间是在所有非弹性项目之后计算得到。在上述示例中,fr 单位的可用空间总量不包括 50px

.container {
  grid-template-columns: 1fr 50px 1fr 1fr;
}

grid-template-areas

该属性通过引用网格区域的名称 grid-area 来定义网格。重复网格区域名称会导致内容跨越这些单元格。句点表示一个空单元格。语法本身提供了网格结构的可视化。

.container {
  grid-template-areas: 
    "<grid-area-name> | . | none | ..."
    "...";
}
.item-a {
  grid-area: header;
}
.item-b {
  grid-area: main;
}
.item-c {
  grid-area: sidebar;
}
.item-d {
  grid-area: footer;
}

.container {
  display: grid;
  grid-template-columns: 50px 50px 50px 50px;
  grid-template-rows: auto;
  grid-template-areas: 
    "header header header header"
    "main main . sidebar"
    "footer footer footer footer";
}

上述示例将创建一个 4 列 3 行的网格。整个顶部为 header 区域,中间一行由 mainsidebar 两个区域和一个空单元格组成,最后一行为 footer

声明中的每一行都需要有相同数量的单元格。可以使用任意数量的句点声明一个空单元格,只要句点之间没有空格,就代表一个单元格。

注意使用此语法仅可以命名区域,不可命名线。使用此语法时,区域两端的线会自动命名,如果网格区域名称为 foo,那么该区域的起始行线和起始列线名称为 foo-start,该区域的终止行线和终止列线名称为 foo-end。这意味着某些线可能有多个名称,上述示例中最左边的行线将有 3 个名称:header-startmain-startfooter-start

grid-template

该属性是 grid-template-rowsgrid-template-columnsgrid-template-areas 三个属性的简写。

.container {
  grid-template: none | <grid-template-rows> / <grid-template-columns>;
}

其接受更复杂但更方便的语法来指定这三个值,例如:

.container {
  grid-template:
    [row1-start] "header header header" 25px [row1-end]
    [row2-start] "footer footer footer" 25px [row2-end]
    / auto 50px auto;
}

上述代码等效于:

.container {
  grid-template-rows: [row1-start] 25px [row1-end row2-start] 25px [row2-end];
  grid-template-columns: auto 50px auto;
  grid-template-areas: 
    "header header header" 
    "footer footer footer";
}

由于 grid-template 并不会重置网格的隐含属性(grid-auto-columnsgrid-auto-rowsgrid-auto-flow)。因此,建议使用 grid 属性而非 grid-template

column-gap, row-gap, grid-column-gap, grid-row-gap

该属性用于指定网格线的大小,你可以将其看做列和行之间的间距。

.container {
  /* standard */
  column-gap: <line-size>;
  row-gap: <line-size>;

  /* old */
  grid-column-gap: <line-size>;
  grid-row-gap: <line-size>;
}
.container {
  grid-template-columns: 100px 50px 100px;
  grid-template-rows: 80px auto 80px; 
  column-gap: 10px;
  row-gap: 15px;
}

间距仅在列和行之间创建,不在边缘创建。注意,带有 grid- 前缀的属性将被废弃。

gap, grid-gap

该属性为 row-gapcolumn-gap 两个属性的简写。

.container {
  /* standard */
  gap: <grid-row-gap> <grid-column-gap>;

  /* old */
  grid-gap: <grid-row-gap> <grid-column-gap>;
}
.container {
  grid-template-columns: 100px 50px 100px;
  grid-template-rows: 80px auto 80px; 
  gap: 15px 10px;
}

如果未指定 row-gap,则它将被设置为与 column-gap 相同的值。注意,带有 grid- 前缀的属性将被废弃。

justify-items

沿 inline(行)轴对齐网格项(与沿 block(列)轴对齐 align-items 相反)。该属性将应用于容器内所有网格项。

.container {
  justify-items: stretch | start | end | center;
}
.container {
  justify-items: stretch;
}
.container {
  justify-items: start;
}
.container {
  justify-items: end;
}
.container {
  justify-items: center;
}

align-items

沿 block(列)轴对齐网格项(与沿 inline(行)轴对齐 align-items 相反)。该属性将应用于容器内所有网格项。

.container {
  align-items: stretch | start | end | center;
}
.container {
  align-items: stretch;
}
.container {
  align-items: start;
}
.container {
  align-items: end;
}
.container {
  align-items: center;
}

通过 align-self 属性可以在单个网格项上覆盖由 align-items 指定的对齐方式。

place-items

该属性在单次声明中同时设置 align-itemsjustify-items 属性。

.center {
  display: grid;
  place-items: center;
}

justify-content

当所有网格项均使用非弹性的单位(例如 px)来确定大小,则网格的总大小可能小于网格容器的大小。在这种情况下,可以在网格容器内设置网格的对齐方式。该属性沿 inline(行)轴(与沿 block(列)轴对齐 align-content 相反)对齐网格。

.container {
  justify-content: start | end | center | stretch | space-around | space-between | space-evenly;    
}
.container {
  justify-content: start;
}
.container {
  justify-content: end;
}
.container {
  justify-content: center;
}
.container {
  justify-content: stretch;
}
.container {
  justify-content: space-around;
}
.container {
  justify-content: space-between;
}
.container {
  justify-content: space-evenly;
}

align-content

当所有网格项均使用非弹性的单位(例如 px)来确定大小,则网格的总大小可能小于网格容器的大小。在这种情况下,可以在网格容器内设置网格的对齐方式。该属性沿 block(列)轴(与沿 inline(行)轴对齐 justify-content 相反)对齐网格。

.container {
  align-content: start | end | center | stretch | space-around | space-between | space-evenly;    
}
.container {
  align-content: start;    
}
.container {
  align-content: end;    
}
.container {
  align-content: center;    
}
.container {
  align-content: stretch;    
}
.container {
  align-content: space-around;    
}
.container {
  align-content: space-between;    
}
.container {
  align-content: space-evenly;    
}

place-content

该属性在单次声明中同时设置 align-contentjustify-content 属性。

grid-auto-columns, grid-auto-rows

该属性指定自动生成的网格轨道(也称为隐式网格轨道)的大小。当网格项多于网格中的单元格或当网格项放置在显示网格之外时,将创建隐式网格轨道。

.container {
  grid-auto-columns: <track-size> ...;
  grid-auto-rows: <track-size> ...;
}
.container {
  grid-template-columns: 60px 60px;
  grid-template-rows: 90px 90px;
}

上述代码将生成一个 2x2 的网格:

使用 grid-columngrid-row 来定位网格项:

.item-a {
  grid-column: 1 / 2;
  grid-row: 2 / 3;
}
.item-b {
  grid-column: 5 / 6;
  grid-row: 2 / 3;
}

.item-b 从第 5 列线开始到第 6 列线结束,但由于并未定义第 5 列线和第 6 列线,因此创建了宽度为 0 的隐式轨道用于填充间隙。使用 grid-auto-columnsgrid-auto-rows 可以指定这些隐式轨道的宽度:

.container {
  grid-auto-columns: 60px;
}

grid-auto-flow

如果有未明确放置在网格中的网格项目,自动放置算法会自动放置这些网格项目。此属性用于控制自动放置算法的工作方式。

.container {
  grid-auto-flow: row | column | row dense | column dense;
}

注意 dense 仅会改变网格项目的视觉顺序,这可能导致顺序混乱且不利于访问。

考虑如下示例:

<section class="container">
  <div class="item-a">item-a</div>
  <div class="item-b">item-b</div>
  <div class="item-c">item-c</div>
  <div class="item-d">item-d</div>
  <div class="item-e">item-e</div>
</section>

定义一个包含 5 列和 2 行的网格,并将 grid-auto-flow 设置为 row

.container {
  display: grid;
  grid-template-columns: 60px 60px 60px 60px 60px;
  grid-template-rows: 30px 30px;
  grid-auto-flow: row;
}

将网格项目放置在网格中时,只需要为其中两个指定位置:

.item-a {
  grid-column: 1;
  grid-row: 1 / 3;
}
.item-e {
  grid-column: 5;
  grid-row: 1 / 3;
}

因为将 grid-auto-flow 设置为了 row,未放置的三个网格项目(item-bitem-citem-d)如下所示:

.container {
  display: grid;
  grid-template-columns: 60px 60px 60px 60px 60px;
  grid-template-rows: 30px 30px;
  grid-auto-flow: column;
}

如果将 grid-auto-flow 设置为 column,未放置的三个网格项目(item-bitem-citem-d)如下所示:

grid

该属性为 grid-template-rowsgrid-template-columnsgrid-template-areasgrid-auto-rowsgrid-auto-columnsgrid-auto-flow 属性的简写。

如下示例中的代码是等效的:

.container {
  grid: 100px 300px / 3fr 1fr;
}

.container {
  grid-template-rows: 100px 300px;
  grid-template-columns: 3fr 1fr;
}
.container {
  grid: auto-flow / 200px 1fr;
}

.container {
  grid-auto-flow: row;
  grid-template-columns: 200px 1fr;
}
.container {
  grid: auto-flow dense 100px / 1fr 2fr;
}

.container {
  grid-auto-flow: row dense;
  grid-auto-rows: 100px;
  grid-template-columns: 1fr 2fr;
}
.container {
  grid: 100px 300px / auto-flow 200px;
}

.container {
  grid-template-rows: 100px 300px;
  grid-auto-flow: column;
  grid-auto-columns: 200px;
}

它还接受更复杂但更方便的语法来一次性设置所有内容。如下示例中的代码是等效的:

.container {
  grid: [row1-start] "header header header" 1fr [row1-end]
        [row2-start] "footer footer footer" 25px [row2-end]
        / auto 50px auto;
}

.container {
  grid-template-areas: 
    "header header header"
    "footer footer footer";
  grid-template-rows: [row1-start] 1fr [row1-end row2-start] 25px [row2-end];
  grid-template-columns: auto 50px auto;    
}

子元素属性

grid-column-start, grid-column-end, grid-row-start, grid-row-end

该属性通过网格线来设置网格项在网格中的位置。grid-column-startgrid-row-start 为网格项起始的线,grid-column-endgrid-row-end 为网格项结束的线。

.item {
  grid-column-start: <number> | <name> | span <number> | span <name> | auto;
  grid-column-end: <number> | <name> | span <number> | span <name> | auto;
  grid-row-start: <number> | <name> | span <number> | span <name> | auto;
  grid-row-end: <number> | <name> | span <number> | span <name> | auto;
}
.item-a {
  grid-column-start: 2;
  grid-column-end: five;
  grid-row-start: row1-start;
  grid-row-end: 3;
}
.item-b {
  grid-column-start: 1;
  grid-column-end: span col4-start;
  grid-row-start: 2;
  grid-row-end: span 2;
}

如果 grid-column-endgrid-row-end 未声明,则该网格项将默认跨越一个轨道。网格项目之间可以相互重叠,使用 z-index 可以控制它们的重叠次序。

grid-column, grid-row

分别是 grid-column-start + grid-column-endgrid-row-start+ grid-row-end 的简写。

.item {
  grid-column: <start-line> / <end-line> | <start-line> / span <value>;
  grid-row: <start-line> / <end-line> | <start-line> / span <value>;
}
.item-c {
  grid-column: 3 / span 2;
  grid-row: third-line / 4;
}

如果未设置结束线的值,则该网格项将默认跨越一个轨道。

grid-area

为一个网格项命名以便它可以使用 grid-template-areas 属性创建的模板引用。此属性可以作为 grid-row-start + grid-column-start + grid-row-end + grid-column-end 的简写。

用作为网格项分配名称:

.item-d {
  grid-area: header;
}

用作 grid-row-start + grid-column-start + grid-row-end + grid-column-end 的简写:

.item-d {
  grid-area: 1 / col4-start / last-line / 6;
}

justify-self

沿 inline(行)轴对齐单元格内的网格项(与沿 block(列)轴对齐 align-self 相反)。该属性仅应用于单个单元格内的网格项。

.item {
  justify-self: stretch | start | end | center;
}
.item-a {
  justify-self: stretch;
}
.item-a {
  justify-self: start;
}
.item-a {
  justify-self: end;
}
.item-a {
  justify-self: center;
}

通过 justify-items 属性可以为容器中所有的网格项设置对齐方式。

align-self

沿 block(列)轴对齐单元格内的网格项(与沿 inline(行)轴对齐 justify-self 相反)。该属性将仅应用于单个单元格内的网格项。

.item {
  align-self: stretch | start | end | center;
}
.item-a {
  align-self: stretch;
}
.item-a {
  align-self: start;
}
.item-a {
  align-self: end;
}
.item-a {
  align-self: center;
}

place-self

place-self 可以在单次声明中同时设置 align-selfjustify-self

.item-a {
  place-self: center;
}
.item-a {
  place-self: center stretch;
}

定位

本节内容主要参考自:定位技术

定位允许我们将一个元素放置在网页的指定位置上。定位并非是一种用来做主要布局的方式,而是一种用于微调布局的手段。通过 position 属性在特定的布局中修改元素的定位方式,该属性有 staticrelativefixedabsolutesticky 共 5 种可选值。

为了展示不同 position 的效果,在此采用相同的 HTML 进行比较:

<h1>XXX 定位</h1>

<p>这是一个基本块元素。</p>
<p class="position">这是一个基本块元素。</p>
<p>这是一个基本块元素。</p>

默认样式为:

body {
  width: 400px;
  margin: 0 auto;
}

h1 {
  text-align: center;
}
  
p {
  margin: 10px;
  padding: 10px;
  background-color: #916cad;
  border: 2px #523874 solid;
  border-radius: 3px;
}

静态定位

静态定位(staticposition 属性的 默认值,它表示将元素放置在文档布局流的默认位置上。

静态定位样式为:

.position {
  position: static;
}

渲染效果如下:

相对定位

相对定位(relative 表示相对于 静态定位 的默认位置进行偏移,其需要搭配 topbottomleftright 四个属性使用。

相对定位样式为:

.position {
  position: relative;
  top: 30px;
  left: 30px;
  background-color: #c7fba5cc;
  border: 2px #adf182cc solid;
}

渲染效果如下:

绝对定位

绝对定位(absolute 表示相对于 上级元素 的位置进行偏移,其需要搭配 topbottomleftright 四个属性使用。绝对定位的定位基点不能为 static 定位,否则定位基点将变成网页根元素 html

绝对定位样式为:

.position {
  position: absolute;
  top: 30px;
  left: 30px;
  background-color: #c7fba5cc;
  border: 2px #adf182cc solid;
}

渲染效果如下:

固定定位

固定定位(fixed 表示相对于 视窗(viewport,即浏览器窗口) 进行偏移,其需要搭配 topbottomleftright 四个属性使用。利用固定定位可以实现元素位置不随页面滚动而发生变化。

为了演示固定定位,修改 HTML 代码如下:

<h1>固定定位</h1>

<p>这是一个基本块元素。</p>
<p class="position">固定</p>
<p>这是一个基本块元素。</p>
<p>这是一个基本块元素。</p>
<p>这是一个基本块元素。</p>
<p>这是一个基本块元素。</p>
<p>这是一个基本块元素。</p>

固定定位样式为:

.position {
  position: fixed;
  top: 30px;
  left: 30px;
  background-color: #c7fba5cc;
  border: 2px #adf182cc solid;
}

渲染效果如下:

粘性定位

粘性定位(sticky 可以理解为 静态定位(static固定定位(fixed混合。当指定一个元素的 position 属性为 sticky 后,它会在正常布局流中滚动,直至它出现在设定的相对于容器的位置,此时它会停止滚动,表现为固定定位。

为了演示粘性定位,修改 HTML 代码如下:

<h1>粘性定位</h1>

<p>这是一个基本块元素。</p>
<p class="position">这是一个粘性定位元素。</p>
<p>这是一个基本块元素。</p>
<p>这是一个基本块元素。</p>
<p>这是一个基本块元素。</p>
<p>这是一个基本块元素。</p>
<p>这是一个基本块元素。</p>
<p>这是一个基本块元素。</p>
<p>这是一个基本块元素。</p>

粘性定位样式为:

.position {
  position: sticky;
  top: 30px;
  left: 30px;
  background-color: #c7fba5cc;
  border: 2px #adf182cc solid;
}

渲染效果如下:


  1. https://developer.mozilla.org/zh-CN/docs/Learn/CSS/Building_blocks/The_box_model ↩︎