【重学CSS】图文并茂!一次性搞懂 Grid 布局,实现“布局自由”~(下)

简介: 【重学CSS】图文并茂!一次性搞懂 Grid 布局,实现“布局自由”~(下)

4.4 justify-self

沿着内联(行)轴对齐一个单元格内的网格项(与沿着块(列)轴对齐的 align-self 相反)。这个值适用于单个单元格内的网格项。

可选的值:

  • start:使网格项与单元格的起始边缘齐平。
  • end:将网格项目与单元格的末端边缘对齐。
  • center:使网格项目在单元格的中心对齐。
  • stretch:填充整个单元格的宽度(这是默认的)。


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

下面来看例子:

.item-a {
  justify-self: start;
}

微信图片_20230613131551.png

.item-a {
  justify-self: end;
}

微信图片_20230613131619.png

.item-a {
  justify-self: center;
}

微信图片_20230613131646.png

.item-a {
  justify-self: stretch;
}

微信图片_20230613131710.png要为网格中的所有项目设置对齐方式,也可以通过 justify-items 属性在网格容器上设置此行为。

4.5 align-self

将一个单元格内的网格项沿块(列)轴对齐(与 justify-self 相反,它沿内联(行)轴对齐)。这个值适用于单个网格项的内容。

可选的值:

  • start:使网格项与单元格的起始边缘齐平。
  • end:将网格项与单元格的末端边缘齐平
  • center:使网格项目在单元格的中心对齐。
  • stretch:填充整个单元格的高度(这是默认的)。
.item {
  align-self: start | end | center | stretch;
}

下面来看例子:

.item-a {
  align-self: start;
}

微信图片_20230613131754.png

.item-a {
  align-self: end;
}

微信图片_20230613131822.png

.item-a {
  align-self: center;
}

微信图片_20230613131848.png

.item-a {
  align-self: stretch;
}

微信图片_20230613131915.png为了对齐网格中的所有项目,这个行为也可以通过 align-items 属性在网格容器上设置。

4.6 place-self

place-self 在一个声明中同时设置 align-selfjustify-self 属性。

可选的值:

  • auto:布局模式的 "默认 "对齐方式。
  • <align-self> / <justify-self>:第一个值设置align-self,第二个值设置justify-self。如果省略了第二个值,则第一个值将被分配给这两个属性。

下面来看例子:

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

微信图片_20230613131948.png

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

微信图片_20230613132016.pngEdge 外,所有主要的浏览器都支持 place-self 简写属性。

5、一些特殊的单位、关键字和函数

5.1 fr(fraction:片段)

我们有现有的长度维度、百分比以及这些新关键字。在CSS网格布局中,还有一种特殊的调整大小的方法,只适用于网格布局 —— 一个新的灵活单位:frfr-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栏各占相同的空间:
微信图片_20230613132110.png
为什么会出现 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-gap10px,这样就把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长度(如 %pxem)一样使用。让我们快速重构上面的代码以使用这个奇特的新值:

.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/425%)。但是!X轴上不再有溢出,因为将每一列设置为1fr会自动考虑到这10px,并从每一列的总宽度中减去它。

你想知道,如果我可以坚持使用百分比或像素等单位,我为什么要学习如何使用这种花哨的新CSS长度?好吧,让我们来看看一个更复杂的CSS网格例子,以解释为什么fr是一个更好的选择。在一个新的例子中,假设我们希望我们的导航在左边,然后是一个12列的网格。


微信图片_20230613132317.png

微信图片_20230613132317.png对于许多 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;
  /* ... */
}

微信图片_20230613132434.png在下面的最后一个例子中,侧边栏项目覆盖了2fr,所以它的宽度将与横跨第1和第2列的项目相同。

.container {
  /* ... */
  grid-template-columns: 1fr 1fr 40px 2fr;
  grid-template-rows: 100px 200px 100px;
  /* ... */
}

微信图片_20230613132514.png你可能会在 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-contentfit-content() 函数一开始的作用与 max-content 类似。然而,一旦轨道达到你传入该函数的尺寸,内容就开始被包裹。因此,fit-content(10em)将创建一个小于10em的轨道,如果最大内容尺寸小于10em,但绝不会大于10em
  • minmax():函数的作用和它看起来的一样:它为长度能够达到的程度设置一个最小和最大的值。这对于相对单位相结合是很有用的。比如你可能希望一列只能缩到这么远。这非常有用,可能是你想要的
grid-template-columns: minmax(100px, 1fr) 3fr;
<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-columnsgrid-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-fillauto-fit

有时候你可能不想指定列轨道的数量,而是想创建尽可能多的适应容器的轨道。你可以用 repeat()auto-fillauto-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-fillauto-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-fillauto-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-gapgrid-row-gapgrid-column-gap 的长度、百分比或计算。
  • grid-template-columns, grid-template-rows 作为一个简单的长度、百分比或计算的列表,只要唯一的区别是列表中的长度、百分比或计算成分的值。

截至目前,只有(grid-)gap, (grid-)row-gap, (grid-)column-gap 的动画在所有测试的浏览器中实现。

微信图片_20230613133232.png

相关文章
|
24天前
|
前端开发 UED 容器
在 CSS 中使用 Flex 布局实现页面自适应时需要注意什么?
【10月更文挑战第22天】在使用 Flex 布局实现页面自适应时,需要对其基本原理和特性有深入的理解,同时结合具体的布局需求和场景,进行细致的调整和优化。通过合理的设置和注意事项的把握,才能实现理想的自适应效果,提升用户体验。还可以根据实际情况进行更深入的探索和实践,以不断提升 Flex 布局的应用能力。
|
17天前
|
前端开发 容器
实现CSS品字布局
【10月更文挑战第27天】
|
1月前
|
前端开发 容器
使用 CSS Grid 布局实现响应式设计
【10月更文挑战第1天】使用 CSS Grid 布局实现响应式设计
52 4
|
1月前
|
前端开发 容器
前端技术分享:利用CSS Grid布局实现响应式设计
【10月更文挑战第1天】前端技术分享:利用CSS Grid布局实现响应式设计
|
1月前
|
前端开发 UED 容器
前端技术分享:利用 CSS Grid 实现响应式布局
【10月更文挑战第1天】前端技术分享:利用 CSS Grid 实现响应式布局
54 2
|
3月前
|
前端开发
2s 利用 HTML+css动画实现企业官网效果
2s 利用 HTML+css动画实现企业官网效果
HTML+CSS 实现通用的企业官网页面(记得收藏)
HTML+CSS 实现通用的企业官网页面(记得收藏)
|
1月前
|
前端开发 JavaScript 搜索推荐
打造个人博客网站:从零开始的HTML和CSS之旅
【9月更文挑战第32天】在这个数字化的时代,拥有一个个人博客不仅是展示自我的平台,也是技术交流的桥梁。本文将引导初学者理解并实现一个简单的个人博客网站的搭建,涵盖HTML的基础结构、CSS样式的美化技巧以及如何将两者结合来制作一个完整的网页。通过这篇文章,你将学会如何从零开始构建自己的网络空间,并在互联网世界留下你的足迹。
|
22天前
|
JSON 移动开发 数据格式
html5+css3+js移动端带歌词音乐播放器代码
音乐播放器特效是一款html5+css3+js制作的手机移动端音乐播放器代码,带歌词显示。包括支持单曲循环,歌词显示,歌曲搜索,音量控制,列表循环等功能。利用json获取音乐歌单和歌词,基于html5 audio属性手机音乐播放器代码。
75 6