web布局:Flex和Grid的注意点

《现代Web布局》小册的学习笔记。
这篇不是系统的记录知识点,对于我已经掌握的或者我认为基础的知识不会记录。

Flex布局

Flex布局中有两条轴,主轴和侧轴,轴的方向会受 CSS 的derectionwriting-mode和 HTML 的dir属性值的影响。

空间分配属性和对齐属性

  1. 空间分配属性:justify-contentalign-contentplace-content(前两者简写align在justify在后)
  2. 对齐属性:align-selfalign-items

align-contentalign-items区别

  1. align-content可以让所有 Flex 行,在侧轴上分配剩余空间。
  2. align-items让 Flex 项目在自己行内的侧轴上对齐,Flex 容器中的每一行都有自己的主轴方向和侧轴方向,也就是说,当 Flex 容器有多行出现时,使用align-items: center无法让它们在 Flex 容器中垂直居中(只能在所在 Flex 行中垂直居中)。
  3. align-content属性必须要在flex-wrap属性值为 wrap 或 wrap-reverse 条件下才能正常工作,但align-items属性则不需要,因为单行使用align-items足矣。
  4. 如果同时设置了align-contentalign-items,优先使用align-content

align-selfmargin

  1. align-self用于某一个 Flex 项目在侧轴上对齐。在容器设置了align-contentalign-items时,该属性行为会有差异:
    1. 只有align-content 属性值为 stretch 时,align-self属性的值才有效。
    2. 而碰上align-items时不会有类似限制,只不过 Flex 项目的align-self属性取值为 auto 时,不会覆盖 Flex 容器上align-items的效果。
  2. Flex 容器不存在 justify-items 和 justify-self ,因为 Flex 项目在 Flex 容器的主轴上被当作一个组。因此没有将单个 Flex 项目从该组中分离出来的概念,Grid 布局有这个概念。但可以使用margin来实现类似效果。

flex属性

flex-grow flex-shrink flex-basic简写,常见简写含义:

  • 默认值:0 1 auto;
  • flex: 1:1 1 0%;
  • flex: none:0 0 auto;
  • flex: auto:1 1 auto;

flex-basic

  1. 优先级公式:content => width => flex-basic

意思是,如果 Flex 项目未显式指定flex-basic属性,那么flex-basic将使用width值;如果 width也没有,那么flex-basic基于 Flex 项目的内容计算宽度 。当然,最终都会被min-widthmax-width限制(或者height)。

  1. 如果 Flex 项目的flex-basicwidth取初始值 auto 时,Flex 项目的初始化尺寸是fit-content;但当flex-shrink显式重置为0,Flex 项目不可收缩时,Flex 项目的初始化尺寸就是max-content
  2. ⚠️当 Flex 容器产生不足空间,即使 Flex 项目的flex-shrink是非0值,Flex 项目宽度也不会小于min-content或者内部固定元素宽度。所以通过flex: 1想让每一个项目都等宽是不可靠的,可以设置min-width: 0来解决这个问题

flex-growflex-shrink

  1. flex-grow默认值为0。当所有 Flex 项目的flex-grow总和小于 1 时,Flex 容器剩余空间分不完。
  2. flex-shrink默认值为1。同理flex-shrink总和小于 1 时,Flex 容器不足空间分不完。

Grid布局

Grid布局中有两条轴,块轴和内联轴,轴的方向会受 CSS 的derectionwriting-mode和 HTML 的dir属性值的影响。

  • 块轴(列轴):定义网站文档(元素块)流,CSS 的书写模式writing-mode会影响块轴的方向。
  • 内联轴(行轴):定义网站的文本流方向,也就是文本的阅读方式,CSS 的derection或 HTML 的dir会影响内联轴的方向。

但需要注意的是,列轴和行轴方向是始终不变的,这两个轴只是现实中网格的概念,拿来方便理解。

fr单位

  1. fr单位只用于定位网格轨道的四个属性:grid-template-columngrid-template-rowgrid-auto-columngrid-auto-row
  2. fr是网格轨道弹性系数,是一个类似于Flex弹性特性的单位,计算公式是:网格轨道尺寸 = 网格轨道弹性系数 ✖️ 网格容器可用空间 ➗ 所有网格轨道弹性系数总和。其中网格容器可用空间不一定等于网格容器宽度,会减去已确定的网格轨道宽度,比如某些轨道宽度单位是百分比、px等,就算是已确定的宽度。
  3. 当所有网格轨道fr相加不大于1,代表网格容器空间还会有剩余。

⚠️需要注意的是:所有轨道设置为1fr并不代表它们的列宽(或行高)都是相等的,1fr最小不会小于网格项目的min-content,当某个轨道宽度计算完之后小于其min-content,会把少的这部分按各fr所占比例减在其他轨道上。
在底层1fr === minmax(auto, 1fr),意味着min=auto(即min-width=min-content),max=1fr
这个问题可以通过两种方式解决:

  1. 定义网格轨道时,用maxmin(0, 1fr)代替1fr
  2. 给网格项目设置min-width: 0

可用于Grid布局的函数

repeat(重复次数, 宽度列表)

用来设置网格轨道的重复片段,接收了两个参数:

  • 第一个参数:重复次数,支持auto-fillauto-fit两个关键词,用于在保证网格项目不溢出网格容器之下,创建最多数量的网格列(或行)轨道。
    1. auto-fill:如果网格容器在内连轴上具有确定的大小或最大大小,则重复次数是最大可能的正整数。
    2. auto-fit:作用同auto-fill,区别是会折叠所有空轨道,也就是将空轨道宽度折叠为0px,这会影响fr单位的计算,因为一旦出现折叠现象,网格容器就会出现剩余可用空间,从而就会影响到fr的计算。所以使用auto-fit可能会扩展网格项目去填补剩余空间。需要注意的是,并不是比auto-fill创建的少,只是空轨道被折叠为0px。

看个例子

<!DOCTYPE html>
<html lang="zh">
<head>
  <style>
    .grid-container {
      display: grid;
      width: 800px;
      grid-auto-rows: 100px;
      gap: 10px;
    }
    .grid-container1 {
      grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
    }
    .grid-container2 {
      grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
    }
    .grid-container .item {
      border: 2px solid #0909;
    }
  </style>
</head>
<body>
  <div class="grid-container grid-container1">
    <div class="item"> 1 </div>
    <div class="item"> 2 </div>
    <div class="item"> 3 </div>
    <div class="item"> 4 </div>
  </div>
  

  <div class="grid-container grid-container2">
    <div class="item"> 1 </div>
    <div class="item"> 2 </div>
    <div class="item"> 3 </div>
    <div class="item"> 4 </div>
  </div>
</body>
</html>

image.png
image.png

  1. 两者相同点:当网格容器无法容纳网格轨道时(有网格项目的),会自动创建新的一行。所以通过repeat可以轻松实现如下布局效果(RAM布局):
.container { 
  display: grid; 
  grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); 
  gap: 10px; 
}

![Kapture 2023-03-20 at 21.18.25.gif](https://img-blog.csdnimg.cn/img_convert/7b2a7d48f923ea8fa0a4081e7e3a41a8.gif#averageHue=#2a3237&clientId=u54c77816-c98b-4&from=paste&height=401&id=u026499d9&name=Kapture 2023-03-20 at 21.18.25.gif&originHeight=801&originWidth=1562&originalType=binary&ratio=2&rotation=0&showTitle=false&size=4340597&status=done&style=none&taskId=uffaceaf1-5872-46db-90b9-ba45e533831&title=&width=781)

  • 第二个参数:轨道宽度列表值,一般有如下几个写法(注意repeat不能嵌套repeat)
.grid-container {
  grid-template-columns: repeat(2, 1fr);
  /*1fr 1fr*/
  grid-template-columns: repeat(2, 1fr, 200px);
  /*1fr 200px 1fr 200px*/
  grid-template-columns: repeat(2, minmax(min(300px, 100%), 1fr));
  /*minmax(min(30px, 20%), 1fr) minmax(min(30px, 20%), 1fr)*/
  grid-template-columns: repeat(2, min-content);
  /*min-content min-content*/
  grid-template-columns: repeat(2, 1fr [col]);
  /*1fr [col] 1fr [col]*/
  grid-template-columns: repeat(2, [col-start] 1fr [col-end]);
  /*[col-start] 1fr [col-end col-start] 1fr [col-end]*/
}

minmax(MIN, MAX)

表示一段长度范围的闭区间,用于定义轨道宽度。

  • 当MAX小于MIN时,不算无效,会忽略MAX,返回MIN的值。
  • 如果MIN和MAX都是百分比,则没有不得小于min-content的限制,网格容器缩小时会无限跟着缩小。
  • 只有MAX能用fr单位。
  • 使用auto时:
    1. auto作为MAX时,auto相当于max-content,即minmax(100px,auto)===minmax(100px,max-content)
    2. auto作为MIN时,当min-width等和最小有关的属性小于min-content时,auto相当于这个属性指定的值,否则相当于min-content

min()、max()、clamp()

不专用于Grid布局,是CSS比较函数,支持使用加减乘除表达式作为值。

  • clamp:接收三个参数:最小值、首选值、最大值。作用是把一个值限制在一个上限和下限之间,当这个值超过最小值和最大值的范围时,在最小值和最大值之间选择一个值使用,小于最小值返回最小值,大于最大值返回最大值。clamp(MIN, VAL, MAX) 相当于max(MIN, min(VAL, MAX))

在实际使用中,更建议将CSS比较函数与minmax函数以及关键词min-contentmax-content结合起来使用。

fit-content()

将给定大小夹紧为可用大小
公式:fit-content(<length-percentage>) = max(minimum, min(limit, max-content))

  • minimum:代表最小值,一般等于min-content,除非指定了最小相关属性,比如min-width
  • limit:传给fit-content的值,类型为<length-percentage>,也就是只支持

也就是说,如果给fit-content()传入的值大于max-content,返回值介于min-contentmax-content之间,反之,返回值介于min-content和参数之间,总之,fit-content()返回的值不会小于min-content。比如fit-content(200px),代表不会超过200px,并且可以在内容很短的情况下缩小到200px以下,但不会小于min-content
fit-content关键字,就是介于min-contentmax-content之间。两个概念合在一起更好理解。

grid-auto-flow

  • grid-auto-flow默认为row,也就是当出现没有指定网格区域的网格项目时,优先从左到右从上到下放置,当显式网格不够用时,优先创建行轨道。
  • 可以设置为colomn,效果和row相反,优先从上到下从左到右放置,当显式网格不够用时,优先创建列轨道。
  • 网格布局默认采取稀疏算法,放置网格项目时不会考虑网格空洞(没有放置项目的网格区域),这是由于某个网格项目偏大或偏小产生的。当grid-auto-flow加上dense时,就会使用紧凑算法,放置时就会优先考虑可以放得下的网格空洞。属性值需要定义为row dense或者column dense,只定义一个dense相当于row dense

image.png
image.png

网格项目重叠

网格项目可以使用grid-row(或对应的start\end)、grid-column(或对应的start\end)、grid-area来指定所放置的网格区域,如此一来就可能会出现网格项目重叠的现象,和定位一样,可以使用z-index来说明重叠的网格项目在 Z轴 上的层级,没有z-index则会由网格项目在文档中出现的先后顺序来决定,越往后层级越高。
可以利用网格项目重叠实现如下的布局:
image.png

<!DOCTYPE html>
<html lang="zh">
<head>
  <style>

    .grid-container {
      display: grid;
      width: 600px;
      margin: auto;
      gap: 5px;
    }

    .grid-container1 {
      grid-template-columns: repeat(4, 150px);
      grid-template-rows: repeat(4, 150px);
    }

    .grid-container1 div {
      line-height: 300px;
      text-align: center;
      font-size: 25px;
      font-weight: bold;
    }

    .grid-container div:nth-child(1) {
      grid-area: 1 / 1 / 3 / 3;
    }

    .grid-container div:nth-child(2) {
      grid-area: 1 / 3 / 3 / 5;
    }

    .grid-container div:nth-child(3) {
      grid-area: 3 / 1 / 5 / 3;
    }

    .grid-container div:nth-child(4) {
      grid-area: 3 / 3 / 5 / 5;
    }

    .grid-container div:last-child {
      grid-area: 2 / 2 / 4 / 4;
      background-color: rgb(164, 159, 159);
      border-radius: 50%;
    }

    .grid-container .item {
      background-color: #0909;
    }
  </style>
</head>

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

</html>

网格布局中的对齐方式

分为网格项目和网格轨道的对齐

  • 网格项目对齐:justify-itemsjustify-self沿内连轴方向对齐网格项目,align-itemsalign-self沿块轴方向对齐网格项目,其中*-items被用于网格容器,相当于给每个项目设置*-self*-self用于网格项目)。
  • 网格轨道对齐:align-content沿着块联轴方向对齐网格轨道,justify-content沿着内联轴方向对齐网格轨道,都被用于网格容器。
  • 以上所有属性可以通过place-*来简写,place-itemsplace-selfplace-content,align在justify在后。

网格轨道布局:
对于网格轨道的对齐,通常只有网格容器有剩余空间时才会使用,当没有时,*-content各值的效果都相同,等于start(默认值)。如果轨道溢出网格容器,*-content会影响溢出方向,比如两侧溢出,start溢出等。
margin:
因为Flex布局不存在jestify-itemsjustify-self,通常会用margin来实现某些对齐样式,margin对于网格布局同样有效(用于网格项目上),需要注意的是,网格项目上设置margin值时,网格项目会向里收缩。

常用属性

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值