现在我们做的响应式布局的一般都会用到媒体查询工具,那么能不能不用呢?那我告诉您,可以的,不妨来一试吧。
带有网格的响应式布局
首先可能是我最喜欢的所有解决方案,因为它的多功能性和易用性。使用 Grid,我们可以创建一组响应式列,这些列可以根据需要自行创建。我们将提供一个单一的约束------列的最小宽度------它在列项目进入新行之前作为一种"断点"发挥双重作用。
这是完成此响应式网格布局所需的全部,其中我们的最小列大小是30ch
通过辅助自定义属性设置的。此规则指示浏览器创建尽可能多的列,这些列至少要30ch
宽:
.grid {
--min: 30ch;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--min)), 1fr));
}
由于1fr
是 的"最大"值minmax()
,因此还允许列拉伸以公平地填充行内的任何剩余空间。因此,如果可用空间为80ch
并且有两个网格子项,它们将各自占用40ch
. 如果有三个孩子,第三个将在第二行,因为80
没有平均分配到允许的最小大小30
。
以下提供了响应式网格布局的实时示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>带有网格的响应式布局 | Web前端之家www.jiangweishan.com</title>
<style>
html {
height: 100%;
}
body {
font-family: system-ui;
min-height: 100%;
background-color: var(--bg, mediumvioletred);
padding: var(--padding, 0);
max-width: var(--max-width, 120ch);
margin-inline: auto;
--padding: 5vw;
--max-width: 180ch;
}
ul,li {
display: list-item;
text-align: -webkit-match-parent;
}
* {
box-sizing: border-box;
margin: 0;
}
.grid {
--min: 30ch;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--min)), 1fr));
gap: 1rem;
}
:where([role="list"]) {
margin: 0;
padding: 0;
list-style: none;
}
.card {
padding: clamp(0.75rem, 5%, 3rem);
background-color: #fff;
border-radius: 1rem;
}
</style>
</head>
<body>
<ul role="list" class="grid">
<li class="card">
<h3>Lorem, ipsum.</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>
</li>
<li class="card">
<h3>Minus, pariatur?</h3>
<p>Veritatis optio illum possimus eveniet exercitationem perferendis ad?</p>
</li>
<li class="card">
<h3>Iste, assumenda!</h3>
<p>Esse minima in maiores similique unde eaque nostrum!</p>
</li>
<li class="card">
<h3>Voluptatem, veritatis!</h3>
<p>Provident deserunt veniam, debitis alias atque deleniti laboriosam!</p>
</li>
<li class="card">
<h3>Accusamus, magnam.</h3>
<p>Ipsum accusantium laboriosam, architecto cum dolor odit animi?</p>
</li>
<li class="card">
<h3>Recusandae, placeat.</h3>
<p>Incidunt, aliquid odit! Eaque nihil mollitia repellat beatae.</p>
</li>
</ul>
</body>
</html>
使用 Flexbox 的响应式布局
我们可以用 Flexbox 完成类似的体验。Flexbox 和 Grid 解决方案之间的区别在于,流向新行的网格项不能扩展到多个网格列。使用 Flexbox,我们可以引导 flex 项目增长以填充所有剩余的额外空间,从而防止在 Grid 解决方案中出现"孤儿"。
在此代码中,与在 Grid 代码中一样,浏览器将创建尽可能多的列,以适应行内空间,大小至少--min
为30ch
. 如果我们有三个项目,第三个需要移动到一个新行,由于简写,它会占用剩余的空间flex
,重要的是设置flex-grow
为1
. 因此,它在大多数情况下具有类似的行为1fr
:
.flexbox-grid {
--min: 30ch;
display: flex;
flex-wrap: wrap;
}
.flexbox-grid > * {
flex: 1 1 var(--min);
}
由于该属性,下图显示了跨越两列的最终奇数列表项flex-grow
。
注意:在 Grid 和 Flexbox 解决方案中,如果我们添加一个gap
,那么在添加新行之前可以创建多少列的计算中会减去该空间。
敏锐的读者可能已经注意到这些解决方案之间的另一个关键区别:使用 Grid 时,父级定义子级行为。对于 Flexbox,我们在子项上设置子布局行为。简写flex
顺序依次为flex-grow
、flex-shrink
和flex-basis
。
作为实验,我们可以将flex-grow
值更改为0
,看看项目如何只扩展到该flex-basis
值。flex-shrink
(用下面的 CodePen 演示进行实验。)保持很重要1
,这样,最终------当可用内联空间比 窄时flex-basis
------仍然允许项目"收缩",因为这有助于防止溢出。
下面的展示了我们的 Flexbox 布局。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>带有网格的响应式布局 | Web前端之家www.jiangweishan.com</title>
<style>
* {
box-sizing: border-box;
margin: 0;
}
html {
height: 100%;
}
body {
font-family: system-ui;
min-height: 100%;
background-color: var(--bg, mediumvioletred);
padding: var(--padding, 0);
max-width: var(--max-width, 120ch);
margin-inline: auto;
}
:where([role="list"]) {
margin: 0;
padding: 0;
list-style: none;
}
.card {
padding: clamp(0.75rem, 5%, 3rem);
background-color: #fff;
border-radius: 1rem;
}
.flexbox-grid {
--min: 30ch;
display: flex;
flex-wrap: wrap;
gap: 1rem;
}
.flexbox-grid > * {
flex: 1 1 var(--min);
}
body {
--padding: 5vw;
--max-width: 180ch;
}
</style>
</head>
<body>
<ul role="list" class="flexbox-grid">
<li class="card">
<h3>Lorem, ipsum.</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>
</li>
<li class="card">
<h3>Minus, pariatur?</h3>
<p>Veritatis optio illum possimus eveniet exercitationem perferendis ad?</p>
</li>
<li class="card">
<h3>Iste, assumenda!</h3>
<p>Esse minima in maiores similique unde eaque nostrum!</p>
</li>
</ul>
</body>
</html>
flex-basis
可以针对此解决方案进一步调整该属性,以便为不同的项目分配唯一的"断点"。由于我们通过--min
自定义属性设置该值,并且 Flexbox 子元素控制自己的大小,因此我们可以使用内联样式对其进行调整:
<li style="--min: 40ch">...</li>
此示例中的其他列表子项仍将围绕它流动并使用30ch
来自基本规则,但更宽的列有效地改变了行为。
这是此代码的演示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>带有网格的响应式布局 | Web前端之家www.jiangweishan.com</title>
<style>
* {
box-sizing: border-box;
margin: 0;
}
html {
height: 100%;
}
body {
font-family: system-ui;
min-height: 100%;
background-color: var(--bg, mediumvioletred);
padding: var(--padding, 0);
max-width: var(--max-width, 120ch);
margin-inline: auto;
}
:where([role="list"]) {
margin: 0;
padding: 0;
list-style: none;
}
.card {
padding: clamp(0.75rem, 5%, 3rem);
background-color: #fff;
border-radius: 1rem;
}
.flexbox-grid {
--min: 25ch;
display: flex;
flex-wrap: wrap;
gap: 1rem;
}
.flexbox-grid > * {
flex: 1 1 var(--min);
}
body {
--padding: 3vw;
--max-width: 180ch;
}
</style>
</head>
<body>
<ul role="list" class="flexbox-grid">
<li class="card">
<h3>Lorem, ipsum.</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>
</li>
<li class="card" style="--min: 40ch">
<h3>Custom "Breakpoint" --min</h3>
<p>Veritatis optio illum possimus eveniet exercitationem perferendis ad?</p>
</li>
<li class="card">
<h3>Iste, assumenda!</h3>
<p>Esse minima in maiores similique unde eaque nostrum!</p>
</li>
<li class="card">
<h3>Molestiae, quo.</h3>
<p>Quos ullam, iure inventore delectus sequi aliquam omnis!</p>
</li>
<li class="card">
<h3>Illo, facere!</h3>
<p>Vel pariatur quod alias, quaerat porro sint quas.</p>
</li>
</ul>
</body>
</html>
以下是另外两种以有趣的方式使用flex-grow
和 的Flexbox 技术flex-basis
:
-
Heydon Pickering 的Flexbox Holy Albatross,它根据父容器的总宽度从列分解为一行。
-
Heydon Pickering 和 Andy Bell 的侧边栏布局,它展示了如何强制使用不同的基于 Flexbox 的断点以更好地控制项目何时换行。