likes
comments
collection
share

关于auto-fill与auto-fit那些事

作者站长头像
站长
· 阅读数 22

repeat与minmax

grid 为我们提供了强大的布局能力,基本使用可以参考阮一峰老师的教程. 我们在本篇文章主要讨论如何使用 auto-fillauto-fit 来实现自适应布局,以及二者的区别有哪些。

auto-fillauto-fit 通常是用于配合 gridrepeat 属性来使用的,通过 repeat 属性我们可以让每一行展示固定数量的元素:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        body {
            margin: 0;
            padding: 0;
        }
        
        .grid {
            display: grid;
            grid-template-columns: repeat(6, 1fr); 
        }

        .grid div {
            width: 100%;
            height: 100px;
            box-sizing: border-box;
            border: 1px solid red;
            background-color: aquamarine;
            display: grid;
            place-items: center center;
        }
    </style>
</head>

<body>
    <div class="grid">
        <div>box</div>
        <div>box</div>
        <div>box</div>
        <div>box</div>
        <div>box</div>
        <div>box</div>
        <div>box</div>
    </div>
</body>

</html>

关于auto-fill与auto-fit那些事

但如果要兼容不同设备上的样式,这种布局显然对小屏设备十分不友好,为了使一行可以放下6个元素,需要尽可能压缩每个元素的宽度:

关于auto-fill与auto-fit那些事

为了在小屏设备上的展示,我们需要为栅格系统的每个元素定义一个最小宽度,minmax(最小宽度,最大宽度) 可以帮我们实现这个功能:

.grid {
	display: grid;
	grid-template-columns: repeat(6, minmax(250px , 1fr) ); 
}

让我们看看效果:

关于auto-fill与auto-fit那些事

不好,grid 布局不像 flex 布局,可以通过 flex-wrap 来控制是否换行,超出宽度的元素被隐藏了,但 auto-fitauto-fill 可以帮我们完成相似的功能:

.grid {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(250px , 1fr) );
}
.grid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(250px , 1fr) );
}

关于auto-fill与auto-fit那些事

关于auto-fill与auto-fit那些事

auto-fitauto-fill 直译为 自适应自填充 ,在上面这个例子中他们表现一致(他们的区别我们稍后再讨论)。但问题是,这种自适应是如何与 minmax 函数、repeat函数相互作用的呢?

这是一个复杂的问题,它涉及多个函数的处理,我们慢慢来讨论。

不同尺寸页面下的grid讨论

设页面宽度为 x

0 < x < 250 时

1fr 等于 x ,此时对于 minmax 函数来说,最大值 < 最小值。根据 MDN-minmax

如果 最大值 < 最小值,则最大值被忽略并且 minmax(最小值, 最大值) 被看成最小值。

因此 repeat(auto-fill, minmax(250px , 1fr) ) == repeat(auto-fill , 250px) ,根据 MDN-repeat中的 auto-fill 词条:

If any number of repetitions would overflow, then the repetition is 1.

因为 250px 溢出(overflow) 了页面,因此重复次数为1. 即 repeat(auto-fill , 250px) 表示将 250px 重复1次。

示例:

关于auto-fill与auto-fit那些事

250 <= x < 500时

1fr 等于 x ,则 minmax(250px , 1fr) 表示元素的最小值为 250px , 最大值为 x 。根据 MDN-repeat 中的 auto-fill 词条:

If the grid container has a definite or maximal size in the relevant axis, then the number of repetitions is the largest possible positive integer that does not cause the grid to overflow its grid container. 如果网格容器在相关轴上具有确定的大小或最大大小,则重复次数是最大可能的正整数,不会导致网格溢出其网格容器。

我们根据 minmax 函数得到了一个最大值 x ,可【重复次数是最大可能的正整数】是多少?

因为一个元素至少 250px ,如果有两个元素,则超出了页面宽度 x (x < 500) ,因此重复次数为1。而这个元素应该多宽呢?

Treating each track as its maximal track sizing function . 将每个轨道视为其最大轨道尺寸大小函数.

抓住关键词【最大】,那么假设 x 等于 300,则宽度为300 .

关于auto-fill与auto-fit那些事

x <= 500 < 750

因为一个元素至少 250px ,如果有三个元素(250 * 3 = 750),则超出了页面宽度 x (x < 750) ,因此重复次数为2。

假设 x = 700 ,要使每个元素最大,则每个元素应该为 700 / 2 = 350px :

关于auto-fill与auto-fit那些事

...

auto-fill与auto-fit的区别在哪里?

根据 MDN上 auto-fit 的描述 :

Behaves the same as auto-fill, except that after placing the grid items any empty repeated tracks are collapsed. 行为与 auto-fill 相同,除了放置网格项目后,所有空的重复轨道都将消失。

直接看有点难理解,简单来说,如果元素数量不够放满一行,则 auto-fit 会将元素平铺,铺满一行

比如我只有一个元素,页面宽度为700. 还是刚才的例子,如果我们写下:

.grid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(250px , 1fr) );
}

html :

<body>
    <div class="grid">
        <div>box</div>
    </div>
</body>

因为一个元素至少 250px ,如果有三个元素,则超出了页面宽度 x == 700 ,因此重复次数为2。grid 系统会为这两个元素预留网格,即使第二个元素并不存在:

关于auto-fill与auto-fit那些事

但相同的情况下,auto-fit 则会让这个元素直接铺满该行,不留下任何空的网格:

.grid {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(250px , 1fr) );
}

关于auto-fill与auto-fit那些事

总结

与常识相反:

  • 当栅格系统设置了 auto-fill ,其内元素不会 fill 铺满整个容器,而是会预留空的网格。
  • 当栅格系统设置了 auto-fit,其内元素会铺满整个容器,不会留下任何空的网格。

参考: