带有响应正方形的网格布局
A grid layout with responsive squares
我想创建一个带有响应式方块的网格布局。
我觉得我应该可以使用 CSS 网格布局来做到这一点,但无法将每个正方形的高度设置为等于宽度。
在每个正方形之间设置间距也有问题。
使用 flexbox 会更好吗?
目前我的 HTML 看起来像这样,但会是动态的,因此可以添加更多方块。当然,它需要响应,因此最好使用媒体查询将其折叠成一列。
<div class="square-container">
<div class="square">
<div class="content">
</div>
</div>
<div class="square">
<div class="content spread">
</div>
</div>
<div class="square">
<div class="content column">
</div>
</div>
</div>
使用css网格,这是我得到的
.square-container{
display: grid;
grid-template-columns: 30% 30% 30%;
.square {
}
}
我能够更进一步地使用 flexbox 并能够使用 space-between 将正方形与漂亮的排水沟对齐,但仍在努力使高度与每个正方形的宽度相匹配。
我找不到任何使用 flexbox 或 grid 完成此操作的示例,但也将不胜感激。
谢谢
尝试使用视口百分比单位。
jsFiddle
.square-container {
display: grid;
grid-template-columns: repeat(3, 30vw);
grid-template-rows: 30vw;
grid-gap: 2.5vw;
padding: 2.5vw;
background-color: gray;
}
.square {
background-color: lightgreen;
}
body {
margin: 0; /* remove default margins */
}
<div class="square-container">
<div class="square">
<div class="content"></div>
</div>
<div class="square">
<div class="content spread"></div>
</div>
<div class="square">
<div class="content column"></div>
</div>
</div>
来自规范:
5.1.2. Viewport-percentage lengths: the vw
, vh
, vmin
, vmax
units
The viewport-percentage lengths are relative to the size of the
initial containing block. When the height or width of the initial
containing block is changed, they are scaled accordingly.
- vw unit - Equal to 1% of the width of the initial containing block.
- vh unit - Equal to 1% of the height of the initial containing
block.
- vmin unit - Equal to the smaller of
vw
or vh
.
- vmax unit - Equal to the larger of
vw
or vh
.
可以利用padding是根据width计算出来的,直接padding-top: 100%
设置square
网格项(网格项现在是方形的)。
2019年更新
请注意,对于 flex items 以及 grid items 之前,这并不适用 - 请参阅 post 在评论中链接到这个答案:
Now that there is a consensus between browsers (newer versions) to have the same behaviour for padding
for flex items and grid items, you can use this solution.
参见下面的演示:
.square-container {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(30%, 1fr));
grid-gap: 10px;
}
.square {
background: cadetblue;
padding-top: 100%; /* padding trick directly on the grid item */
box-sizing: border-box;
position: relative;
}
.square .content { /* absolutely positioned */
position: absolute;
top: 0;
right:0;
left: 0;
bottom: 0;
}
<div class="square-container">
<div class="square">
<div class="content"> some content here</div>
</div>
<div class="square">
<div class="content"> some content here</div>
</div>
<div class="square">
<div class="content"> some content here</div>
</div>
<div class="square">
<div class="content"> some content here</div>
</div>
<div class="square">
<div class="content column">some content here and there is a lot of text here</div>
</div>
<div class="square">
<div class="content spread">text</div>
</div>
<div class="square">
<div class="content column">some text here</div>
</div>
</div>
padding-bottom
技巧是最常用的方法。
您可以将它与 Flexbox 和 CSS Grid 结合使用,并且由于对 margin/padding 使用百分比会导致 flex/grid 项的结果不一致( 在较旧的浏览器版本上, 见下面的编辑注释), 可以添加一个额外的包装器,或者像这里一样,使用伪元素,所以带有百分比的元素不是 flex/grid项目。
编辑: 注意,有一个 ,现在在 flex/grid 项目上使用时应该给出一致的结果。但请注意,旧版本仍然会出现此问题。
请注意,如果您要向 content
元素添加内容,则需要绝对位置以保持正方形的纵横比。
编辑 2: 在评论中有人问我如何使文本居中,所以我在下面的代码片段中添加了它。
.square-container {
display: flex;
flex-wrap: wrap;
}
.square {
position: relative;
flex-basis: calc(33.333% - 10px);
margin: 5px;
border: 1px solid;
box-sizing: border-box;
}
.square::before {
content: '';
display: block;
padding-top: 100%;
}
.square .content {
position: absolute;
top: 0; left: 0;
height: 100%;
width: 100%;
display: flex; /* added for centered text */
justify-content: center; /* added for centered text */
align-items: center; /* added for centered text */
}
<div class="square-container">
<div class="square">
<div class="content">
<span>Some centered text</span>
</div>
</div>
<div class="square">
<div class="content spread">
</div>
</div>
<div class="square">
<div class="content column">
</div>
</div>
<div class="square">
<div class="content spread">
</div>
</div>
<div class="square">
<div class="content column">
</div>
</div>
</div>
CSS网格版
.square-container {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(30%, 1fr));
grid-gap: 10px;
}
.square {
position: relative;
border: 1px solid;
box-sizing: border-box;
}
.square::before {
content: '';
display: block;
padding-top: 100%;
}
.square .content {
position: absolute;
top: 0; left: 0;
height: 100%;
width: 100%;
}
<div class="square-container">
<div class="square">
<div class="content">
</div>
</div>
<div class="square">
<div class="content spread">
</div>
</div>
<div class="square">
<div class="content column">
</div>
</div>
<div class="square">
<div class="content spread">
</div>
</div>
<div class="square">
<div class="content column">
</div>
</div>
</div>
几天来,我很惊讶在 2020 年没有简单的解决方案。我确信使用 CSS 网格这将是小菜一碟...... Ason 提供的 Flexbox 解决方案是唯一可以跨浏览器工作的解决方案。在 Stack 上,我发现了另一种使用 CSS 网格的解决方案,它使用 padding-bottom: 100% 但它在 Firefox 中不起作用(页脚下方有很多白色 space)。
这是我对这个问题的看法,我认为这是我这些天遇到的所有问题中最简单的解决方案。
CSS Codepen 上的网格解决方案:
https://codepen.io/abudimir/pen/ExKqyGp
<div class="square-container">
您可以使用 CSS aspect-ratio
属性.
在所有现代浏览器中实现此目的
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-gap: 5px;
}
.container div {
aspect-ratio: 1 / 1;
/* Styles below just for demo */
background-color: orange;
color: white;
font-family: Arial;
display: flex;
justify-content: center;
align-items: center;
}
<div class="container">
<div>A</div>
<div>B</div>
<div>C</div>
<div>D</div>
<div>E</div>
<div>F</div>
<div>G</div>
</div>
我想创建一个带有响应式方块的网格布局。
我觉得我应该可以使用 CSS 网格布局来做到这一点,但无法将每个正方形的高度设置为等于宽度。
在每个正方形之间设置间距也有问题。
使用 flexbox 会更好吗?
目前我的 HTML 看起来像这样,但会是动态的,因此可以添加更多方块。当然,它需要响应,因此最好使用媒体查询将其折叠成一列。
<div class="square-container">
<div class="square">
<div class="content">
</div>
</div>
<div class="square">
<div class="content spread">
</div>
</div>
<div class="square">
<div class="content column">
</div>
</div>
</div>
使用css网格,这是我得到的
.square-container{
display: grid;
grid-template-columns: 30% 30% 30%;
.square {
}
}
我能够更进一步地使用 flexbox 并能够使用 space-between 将正方形与漂亮的排水沟对齐,但仍在努力使高度与每个正方形的宽度相匹配。
我找不到任何使用 flexbox 或 grid 完成此操作的示例,但也将不胜感激。
谢谢
尝试使用视口百分比单位。
jsFiddle
.square-container {
display: grid;
grid-template-columns: repeat(3, 30vw);
grid-template-rows: 30vw;
grid-gap: 2.5vw;
padding: 2.5vw;
background-color: gray;
}
.square {
background-color: lightgreen;
}
body {
margin: 0; /* remove default margins */
}
<div class="square-container">
<div class="square">
<div class="content"></div>
</div>
<div class="square">
<div class="content spread"></div>
</div>
<div class="square">
<div class="content column"></div>
</div>
</div>
来自规范:
5.1.2. Viewport-percentage lengths: the
vw
,vh
,vmin
,vmax
unitsThe viewport-percentage lengths are relative to the size of the initial containing block. When the height or width of the initial containing block is changed, they are scaled accordingly.
- vw unit - Equal to 1% of the width of the initial containing block.
- vh unit - Equal to 1% of the height of the initial containing block.
- vmin unit - Equal to the smaller of
vw
orvh
.- vmax unit - Equal to the larger of
vw
orvh
.
可以利用padding是根据width计算出来的,直接padding-top: 100%
设置square
网格项(网格项现在是方形的)。
2019年更新
请注意,对于 flex items 以及 grid items 之前,这并不适用 - 请参阅 post 在评论中链接到这个答案:
Now that there is a consensus between browsers (newer versions) to have the same behaviour for
padding
for flex items and grid items, you can use this solution.
参见下面的演示:
.square-container {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(30%, 1fr));
grid-gap: 10px;
}
.square {
background: cadetblue;
padding-top: 100%; /* padding trick directly on the grid item */
box-sizing: border-box;
position: relative;
}
.square .content { /* absolutely positioned */
position: absolute;
top: 0;
right:0;
left: 0;
bottom: 0;
}
<div class="square-container">
<div class="square">
<div class="content"> some content here</div>
</div>
<div class="square">
<div class="content"> some content here</div>
</div>
<div class="square">
<div class="content"> some content here</div>
</div>
<div class="square">
<div class="content"> some content here</div>
</div>
<div class="square">
<div class="content column">some content here and there is a lot of text here</div>
</div>
<div class="square">
<div class="content spread">text</div>
</div>
<div class="square">
<div class="content column">some text here</div>
</div>
</div>
padding-bottom
技巧是最常用的方法。
您可以将它与 Flexbox 和 CSS Grid 结合使用,并且由于对 margin/padding 使用百分比会导致 flex/grid 项的结果不一致( 在较旧的浏览器版本上, 见下面的编辑注释), 可以添加一个额外的包装器,或者像这里一样,使用伪元素,所以带有百分比的元素不是 flex/grid项目。
编辑: 注意,有一个
请注意,如果您要向 content
元素添加内容,则需要绝对位置以保持正方形的纵横比。
编辑 2: 在评论中有人问我如何使文本居中,所以我在下面的代码片段中添加了它。
.square-container {
display: flex;
flex-wrap: wrap;
}
.square {
position: relative;
flex-basis: calc(33.333% - 10px);
margin: 5px;
border: 1px solid;
box-sizing: border-box;
}
.square::before {
content: '';
display: block;
padding-top: 100%;
}
.square .content {
position: absolute;
top: 0; left: 0;
height: 100%;
width: 100%;
display: flex; /* added for centered text */
justify-content: center; /* added for centered text */
align-items: center; /* added for centered text */
}
<div class="square-container">
<div class="square">
<div class="content">
<span>Some centered text</span>
</div>
</div>
<div class="square">
<div class="content spread">
</div>
</div>
<div class="square">
<div class="content column">
</div>
</div>
<div class="square">
<div class="content spread">
</div>
</div>
<div class="square">
<div class="content column">
</div>
</div>
</div>
CSS网格版
.square-container {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(30%, 1fr));
grid-gap: 10px;
}
.square {
position: relative;
border: 1px solid;
box-sizing: border-box;
}
.square::before {
content: '';
display: block;
padding-top: 100%;
}
.square .content {
position: absolute;
top: 0; left: 0;
height: 100%;
width: 100%;
}
<div class="square-container">
<div class="square">
<div class="content">
</div>
</div>
<div class="square">
<div class="content spread">
</div>
</div>
<div class="square">
<div class="content column">
</div>
</div>
<div class="square">
<div class="content spread">
</div>
</div>
<div class="square">
<div class="content column">
</div>
</div>
</div>
几天来,我很惊讶在 2020 年没有简单的解决方案。我确信使用 CSS 网格这将是小菜一碟...... Ason 提供的 Flexbox 解决方案是唯一可以跨浏览器工作的解决方案。在 Stack 上,我发现了另一种使用 CSS 网格的解决方案,它使用 padding-bottom: 100% 但它在 Firefox 中不起作用(页脚下方有很多白色 space)。
这是我对这个问题的看法,我认为这是我这些天遇到的所有问题中最简单的解决方案。
CSS Codepen 上的网格解决方案: https://codepen.io/abudimir/pen/ExKqyGp
<div class="square-container">
您可以使用 CSS aspect-ratio
属性.
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-gap: 5px;
}
.container div {
aspect-ratio: 1 / 1;
/* Styles below just for demo */
background-color: orange;
color: white;
font-family: Arial;
display: flex;
justify-content: center;
align-items: center;
}
<div class="container">
<div>A</div>
<div>B</div>
<div>C</div>
<div>D</div>
<div>E</div>
<div>F</div>
<div>G</div>
</div>