4.4 justify-self
沿着内联(行)轴对齐一个单元格内的网格项(与沿着块(列)轴对齐的 align-self
相反)。这个值适用于单个单元格内的网格项。
可选的值:
start
:使网格项与单元格的起始边缘齐平。end
:将网格项目与单元格的末端边缘对齐。center
:使网格项目在单元格的中心对齐。stretch
:填充整个单元格的宽度(这是默认的)。
.item { justify-self: start | end | center | stretch; }
下面来看例子:
.item-a { justify-self: start; }
.item-a { justify-self: end; }
.item-a { justify-self: center; }
.item-a { justify-self: stretch; }
要为网格中的所有项目设置对齐方式,也可以通过 justify-items
属性在网格容器上设置此行为。
4.5 align-self
将一个单元格内的网格项沿块(列)轴对齐(与 justify-self
相反,它沿内联(行)轴对齐)。这个值适用于单个网格项的内容。
可选的值:
start
:使网格项与单元格的起始边缘齐平。end
:将网格项与单元格的末端边缘齐平center
:使网格项目在单元格的中心对齐。stretch
:填充整个单元格的高度(这是默认的)。
.item { align-self: start | end | center | stretch; }
下面来看例子:
.item-a { align-self: start; }
.item-a { align-self: end; }
.item-a { align-self: center; }
.item-a { align-self: stretch; }
为了对齐网格中的所有项目,这个行为也可以通过 align-items
属性在网格容器上设置。
4.6 place-self
place-self
在一个声明中同时设置 align-self
和 justify-self
属性。
可选的值:
auto
:布局模式的 "默认 "对齐方式。<align-self>
/<justify-self>
:第一个值设置align-self,第二个值设置justify-self。如果省略了第二个值,则第一个值将被分配给这两个属性。
下面来看例子:
.item-a { place-self: center; }
.item-a { place-self: center stretch; }
除 Edge
外,所有主要的浏览器都支持 place-self
简写属性。
5、一些特殊的单位、关键字和函数
5.1 fr(fraction:片段)
我们有现有的长度维度、百分比以及这些新关键字。在CSS网格布局中,还有一种特殊的调整大小的方法,只适用于网格布局 —— 一个新的灵活单位:fr
(fr-unit:w3 规范)。fr
是一个分数单位,1fr
代表1部分的可用空间。下面是几个fr单位工作的例子。这些例子中的网格项目是用网格区域放置在网格上的。
fr
的工作方式类似于在 flexbox
中使用 flex: auto
。它在项目被布置好后分配空间。因此,如果有多列都希望设置为相同份额的可用空间,那么就可以使用fr
。
.container { display: grid; grid-template-columns: 1fr 1fr 1fr 1fr; grid-template-rows: 100px 200px 100px; grid-template-areas: "head head2 . side" "main main2 . side" "footer footer footer footer"; }
这4栏各占相同的空间:
为什么会出现 fr
?
首先,让我们看看我们通常是如何在CSS中建立网格的。在下面的例子中,我们要创建一个四列网格,每一列都有相同的宽度:
<div class="grid"> <div class="column"> </div> <div class="column"> </div> <div class="column"> </div> <div class="column"> </div> </div>
.grid { display: grid; grid-template-columns: repeat(4, 25%); grid-column-gap: 10px; }
如果你从未见过 grid-template-columns
属性后面的 repeat()
函数,那么让我向你介绍一下CSS Grid最整洁的功能之一它是一种简写,本质上允许我们更简洁地描述重复的值。我们可以写成 grid-template-columns。25% 25% 25% 25%;
,但使用 repeat()
更加简洁,特别是当你有更多的宽度时(比如 minmax()
表达式)。它的语法是这样的:
作者:_你当像鸟飞往你的山
链接:https://juejin.cn/post/7208484366955085883
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
repeat(number of columns/rows, the column width we want);
不过,到目前为止,我们所做的事情其实有几个问题。
首先,为了使用这个整洁的CSS功能,我们不得不做一点点数学运算。我们必须想一想,网格的总宽度(100%)除以我们想要的列数(4),就得出了25%
。在这个例子中,数学是非常简单的,所以我们不必担心,但在更复杂的例子中,我们可以完全避免做数学题,让浏览器为我们计算。我们确实有calc()
可用,所以我们可以做 repeat(4, calc(100% / 4)
, 但即使这样也有点奇怪,而且还有另一个问题...
第二个问题是溢出的问题。因为我们把每一列设置为25%
,而grid-column-gap
为10px
,这样就把grid元素
推得比100%
还宽。从上面的代码来看,这并不是你所期望的工作方式,但这就是百分比的工作方式。我们在上面的代码中真正说的是 "将每一列设置为视口宽度的25%
,并在它们之间有一个10px
的间隙。"这是一个微妙的区别,但它导致了布局上的一个大问题。
我们无意中在这里造成了水平滚动:
<div class="grid"> <div class="column"> </div> <div class="column"> </div> <div class="column"> </div> <div class="column"> </div> </div>
这就是fr
可以解决问题的地方。在定义网格时,fr
可以像其他CSS长度(如 %
、px
或em
)一样使用。让我们快速重构上面的代码以使用这个奇特的新值:
.grid { display: grid; grid-template-columns: repeat(4, 1fr); grid-column-gap: 10px; }
<div class="grid"> <div class="column"></div> <div class="column"></div> <div class="column"></div> <div class="column"></div> </div>
这看起来和上面的例子一样,因为在这个例子中,我们将四列中的每一列都设置为一个分数(刚好是1/4
或25%
)。但是!X轴上不再有溢出,因为将每一列设置为1fr
会自动考虑到这10px
,并从每一列的总宽度中减去它。
你想知道,如果我可以坚持使用百分比或像素等单位,我为什么要学习如何使用这种花哨的新CSS长度?好吧,让我们来看看一个更复杂的CSS网格例子,以解释为什么fr
是一个更好的选择。在一个新的例子中,假设我们希望我们的导航在左边,然后是一个12列的网格。
对于许多 UI
来说,这是一个非常典型的场景,因此使用 fr
可以避免我们制作单独的网格 div
或使用 calc
。因为如果我们在上面的例子中没有使用 fr
那么我们将不得不使用下面的计算逻辑:
每列的宽度 = ((视口宽度 - nav宽度) / 列数) * 1%
这当然是可行的,只是阅读起来非常痛苦,而且如果我们改变了导航的宽度,那么我们就必须重新进行这种计算。而 fr
将所有这些都整理成一行可读性很好的代码:
.grid { display: grid; grid-template-columns: 250px repeat(12, 1fr); grid-column-gap: 10px; }
仅仅通过少量的代码,我们就使我们的页面在未来更容易维护,我们也确保了我们的代码对我们后面的开发者来说更容易读懂。
5.1.1 fr 的使用
下面是上面的同一个例子,不同的fr值。注意布局的变化。
.container { /* ... */ grid-template-columns: 1fr 1fr 40px 20%; grid-template-rows: 100px 200px 100px; /* ... */ }
在下面的最后一个例子中,侧边栏项目覆盖了2fr
,所以它的宽度将与横跨第1和第2列的项目相同。
.container { /* ... */ grid-template-columns: 1fr 1fr 40px 2fr; grid-template-rows: 100px 200px 100px; /* ... */ }
你可能会在 CSS Grid
中使用很多 fractional units,比如 1fr
。它们本质上意味着 "剩余空间的一部分"。因此,一个声明如:
grid-template-columns: 1fr 3fr;
意味着,宽泛地说,25% 75%
。只是这些百分比值比分数单位要牢固得多。例如,如果你给这些基于百分比的列添加了填充物,现在你已经打破了 100%
的宽度(假设是一个内容框模型)。分数单位与其他单位的组合也更加友好,这一点你可以看下面这个例子:
grid-template-columns: 50px min-content 1fr;
5.1.2 fr 混合其他单位使用
正如你在前面的例子中所看到的,你可以将fr值与固定值和百分比值混合。fr值将被划分在其他值所占的空间中。
例如,如果你的网格有4列,如下面的片段,第1列将是300px
,第2列80px(800px的10%)
,第3和第4列将是210px(各占剩余空间的一半)
。
main { width: 800px; display: grid; grid-template-columns: 300px 10% 1fr 1fr; /* 300px 80px 210px 210px */ grid-template-rows: auto; }
5.2 sizing 关键字和函数
在确定行和列的大小时,你可以使用你习惯的所有长度,如 px、rem、%
等,还可以使用下面几个在 Box Sizing
规范中定义的关键词:
min-content
:内容的最小尺寸,min-content(最小内容)
这个关键词会让一个轨道尽可能小,而不会让轨道内容溢出来。如果将网格布局改为列轨道都是min-content
,意味着它们会变得与轨道中最长的单词一样窄。比如像"E pluribus unum"
这样的一行文字,最小内容可能是"pluribus"
这个词的宽度。max-content
:内容的最大尺寸,max-content关键字
则有相反的效果。轨道将变得足够宽,所有的内容都可以显示在一个长的不间断的字符串中。这可能会导致溢出,因为字符串不会被包裹。比如上面的句子,max-content
是整个句子的长度。auto
:这个关键词很像fr单位,只是在分配剩余空间时,它们在与fr单位的尺寸之争中 "输 "了。fr
:见上文fit-content()
:函数使用可用的空间,但绝不会小于min-content
,也不会超过max-content
。fit-content()
函数一开始的作用与max-content
类似。然而,一旦轨道达到你传入该函数的尺寸,内容就开始被包裹。因此,fit-content(10em)
将创建一个小于10em的轨道,如果最大内容尺寸小于10em
,但绝不会大于10em
。minmax()
:函数的作用和它看起来的一样:它为长度能够达到的程度设置一个最小和最大的值。这对于相对单位相结合是很有用的。比如你可能希望一列只能缩到这么远。这非常有用,可能是你想要的。
grid-template-columns: minmax(100px, 1fr) 3fr;
min()函数
:可看 min()、max() 和 clamp():今天要使用的三个逻辑 CSS 函数max()函数
:可看 min()、max() 和 clamp():今天要使用的三个逻辑 CSS 函数
<main> <div class="wrapper"> <article class="flow"> <figure class="callout"> </figure> <div class="controls"> <label> 选择列 size <select id="switcher"> <option value="auto">auto</option> <option value="min-content">min-content</option> <option value="max-content">max-content</option> <option value="fit-content(7em)">fit-content(7em)</option> </select> </label> </div> <div class="container" id="container"> <div class="box">Item one</div> <div class="box">Item two</div> <div class="box">Item three has more text </div> <div class="box">Item four</div> <div class="box">Item five</div> </div> </article> </div> </main>
在这个demo中,你可能会发现,当使用 auto
时,网格列会拉伸以填充容器。如果网格容器中有额外的空间,自动尺寸的轨道将默认拉伸。
5.3 repeat() 函数和关键字
如果你的定义包含重复的部分,你可以使用 repeat()
来简化事情。你可以将其与 grid-template-columns
和 grid-template-rows
属性一起使用,使您的规则在创建大量列或行时更加简洁和易于理解。
例如,我们有一个网格容器:
.container { display: grid; grid-gap: 10px 15px; grid-template-columns: 1fr 2fr 1fr 2fr 1fr 2fr; grid-template-rows: 100px auto 20% 100px auto 20px; }
我们可以使用像 repeat()
这样的符号来简化:
.container { display: grid; grid-gap: 10px 15px; grid-template-columns: repeat(3, 1fr 2fr); grid-template-rows: repeat(2, 100px auto 20%); }
传递给 repeat()
的第一个值是重复次数,第二个值是要重复的网格轨道。
5.3.1 repeat() 与 关键字
看下面这个例子:
grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr。 /* 简洁的写法 */ grid-template-columns: repeat(8, 1fr); /* 配合 minmaxx() */ grid-template-columns: repeat(8, minmax(10px, 1fr))
但是,repeat()
在与关键词结合时可以变得更加花哨。
auto-fill
:在一行中尽可能多地填入可能的列,即使它们是空的。auto-fit
:将所有的列装入空间。倾向于扩大列来填充空间,而不是空列。
这承担了所有CSS网格中最著名的片段,也是历史上最伟大的CSS技巧之一。
.container { display: grid; grid-auto-flow: column dense; grid-template-columns: repeat(4, [col] 1fr); grid-template-rows: repeat(5, [row] 150px); }
这等效于以下长格式定义:
.container { display: grid; grid-auto-flow: column dense; grid-template-columns: [col] 1fr [col] 1fr [col] 1fr [col] 1fr; grid-template-rows: [row] 150px [row] 150px [row] 150px [row] 150px [row] 150px; }
重复符号末尾的命名网格线最终与下一个起始名称行共享同一行。例如,有了这个:
.container { display: grid; grid-auto-flow: column dense; grid-template-columns: repeat(4, [col-start] 1fr [col-end]); grid-template-rows: repeat(5, [row-start] 150px [row-end]); }
我们得到这个等效的长格式定义:
.container { display: grid; grid-auto-flow: column dense; grid-template-columns: [col-start] 1fr [col-end col-start] 1fr [col-end col-start] 1fr [col-end col-start] 1fr [col-end]; grid-template-rows: [row-start] 150px [row-end row-start] 150px [row-end row-start] 150px [row-end row-start] 150px [row-end row-start] 150px [row-end]; }
5.4 minmax() 函数
这个功能意味着你可以为一个轨道设置一个最小和最大的尺寸。这可能是相当有用的。如果我们以上面那个分配剩余空间的fr单元为例,可以用minmax()
写成minmax(auto, 1fr)
。Grid看的是内容的内在尺寸,然后在给内容足够的空间后分配可用空间。这意味着你可能不会得到每个轨道在网格容器中都有相等份额的所有可用空间。
要强制轨道在网格容器中占有同等份额的空间,减去间隙,使用minmax
。用minmax(0, 1fr)
代替1fr作为轨道尺寸。这使得轨道的最小尺寸为0,而不是最小内容尺寸。然后,Grid将占用容器中所有可用的尺寸,扣除任何间隙所需的尺寸,并根据你的fr单位将其余部分分出去。
5.5 auto-fill
和 auto-fit
有时候你可能不想指定列轨道的数量,而是想创建尽可能多的适应容器的轨道。你可以用 repeat()
和 auto-fill
或 auto-fit
关键字来实现这一点。来看下面这个demo:
<main> <div class="wrapper"> <article class="flow"> <figure class="callout"> <p><code>grid-template-columns: repeat(auto-fill, 200px);</code></p> </figure> <div class="container" id="container"> <div class="box">Item one</div> <div class="box">Item two</div> <div class="box">Item three</div> <div class="box">Item four</div> <div class="box">Item five</div> <div class="box">Item six</div> <div class="box">Item seven</div> <div class="box">Item eight</div> </div> </article> </div> </main>
在demo
中,我们可以得到尽可能多的轨道。然而,这些轨道并不灵活。在有足够的空间容纳另一个200像素的轨道之前,你会在末端得到一个缺口。如果你添加了minmax()
函数,你就可以要求尽可能多的轨道,最小尺寸为200像素
,最大为1fr
。然后,Grid会将200像素的轨道排列出来,不管剩下多少空间都会平均分配给它们。
这创造了一个二维响应式布局,而且不需要任何媒体查询:
<main> <div class="wrapper"> <article class="flow"> <h1>Auto responsive grid</h1> <figure class="callout"> <p><code>grid-template-columns: repeat(auto-fill, minmax(200px,1fr));</code></p> <p><strong>Resize the editor panel to see the grid change.</strong></p> </figure> <div class="container" id="container"> <div class="box">Item one</div> <div class="box">Item two</div> <div class="box">Item three</div> <div class="box">Item four</div> <div class="box">Item five</div> <div class="box">Item six</div> <div class="box">Item seven</div> <div class="box">Item eight</div> </div> </article> </div> </main>
auto-fill
和 auto-fit
之间有一个微妙的区别。在下一面一个demo中,使用上面解释的语法来玩一个网格布局,但在网格容器中只有两个网格项。使用auto-fill
关键字,你可以看到空轨道已经被创建。将关键字改为auto-fit
,轨道就会折叠成0大小。这意味着,灵活的轨道现在会增长,以消耗空间。
<main> <div class="wrapper"> <article class="flow"> <h1><code>auto-fill</code> vs <code>auto-fit</code></h1> <figure class="callout"> <p><code>grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));</code></p> </figure> <div class="controls"> <label> 选择 size <select id="switcher"> <option value="auto-fill">auto-fill</option> <option value="auto-fit">auto-fit</option> </select> </label> </div> <div class="container" id="container"> <div class="box">Item one</div> <div class="box">Item two</div> </div> </article> </div> </main>
auto-fill
和 auto-fit
关键词的作用在很大程度上是相同的。一旦第一个轨道被填满,它们之间就没有任何区别。
5.6 Masonry
CSS网格的一个实验性功能是砌体布局。请注意,有很多关于 CSS砌体
的方法,但大部分都是些花式玩法,要么有很大的弊端,要么不是你想要的。
该规范现在有一个官方的实现,这是在 Firefox
的一个 flag
后面:
.container { display: grid; grid-template-columns: repeat(4, 1fr); grid-template-rows: masonry; }
5.7 Subgrid
Subgrid
是网格的一个非常有用的功能,它允许网格项拥有自己的网格,该网格从父网格继承网格线
.parent-grid { display: grid; grid-template-columns: repeat(9, 1fr); } .grid-item { grid-column: 2 / 7; display: grid; grid-template-columns: subgrid; } .child-of-grid-item { grid-column: 3 / 6; }
现在只有Firefox支持这个功能,但它真的需要得到普及。
了解 display: contents;
也很有用。这与 subgrid
不同,但它有时也是一个有用的工具,方式类似:
<div class="grid-parent"> <div class="grid-item"></div> <div class="grid-item"></div> <ul style="display: contents;"> <li class="grid-item"></li> <li class="grid-item"></li> </ul> </div>
6、其他的一些应用
6.1 Fluid columns
流动宽度的 column
,在有空间的情况下,可以分成更多或更少的栏目,而且无需媒体查询!
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); /* 这对小屏幕更好,前提是 min() 得到更好的浏览器支持。 */ /* grid-template-columns: repeat(auto-fill, minmax(min(200px, 100%), 1fr)); */ gap: 1rem; }
6.2 CSS Grid animation
根据 CSS Grid Layout Module Level 1
规范,有5个可实现动画的网格属性。
grid-gap
、grid-row-gap
、grid-column-gap
的长度、百分比或计算。grid-template-columns
,grid-template-rows
作为一个简单的长度、百分比或计算的列表,只要唯一的区别是列表中的长度、百分比或计算成分的值。
截至目前,只有(grid-)gap
, (grid-)row-gap
, (grid-)column-gap
的动画在所有测试的浏览器中实现。