I've created a layout below using display: grid
, I've used the old padding-top
trick to have fluid square divs, but I'm wondering if there is a better way of doing this, either with CSS Grid or Flexbox. The layout should look as is, and not use JS.
https://codepen.io/anon/pen/GWzavX
.o-container {
margin: 0 auto;
max-width: 1280px;
}
.o-grid {
box-sizing: border-box;
display: grid;
grid-gap: 1rem;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(2, 1fr);
max-width: 100%;
padding: 0 1rem;
width: 100%;
}
.o-grid__content {
box-sizing: border-box;
height: 100%;
padding: 1rem;
position: absolute;
top: 0;
width: 100%;
}
.o-grid__item {
box-shadow: inset 0 0 0 1px red;
position: relative;
}
.o-grid__item--tall {
grid-row: span 2;
}
.o-grid__item--wide {
grid-column: span 2;
padding-top: 50%;
}
<div class="o-container">
<div class="o-grid">
<div class="o-grid__item o-grid__item--wide">
<div class="o-grid__content">
1. 2x1
</div>
</div>
<div class="o-grid__item">
<div class="o-grid__content">
2. 1x1
</div>
</div>
<div class="o-grid__item o-grid__item--tall">
<div class="o-grid__content">
3. 1x2
</div>
</div>
<div class="o-grid__item">
<div class="o-grid__content">
4. 1x1
</div>
</div>
<div class="o-grid__item">
<div class="o-grid__content">
5. 1x1
</div>
</div>
<div class="o-grid__item">
<div class="o-grid__content">
6. 1x1
</div>
</div>
</div>
</div>
I've created a layout below using
display: grid
, I've used the oldpadding-top
trick to have fluid square divs, but I'm wondering if there is a better way of doing this, either with CSS Grid or Flexbox.
The truth of the matter is that you're going to have to find another way to make this work, unless you're coding for Chrome only.
In CSS Grid, the padding-top
trick fails in Firefox. The spec provides the reason:
6.4. Grid Item Margins and Paddings
Authors should avoid using percentages in paddings or margins on grid items entirely, as they will get different behavior in different browsers.
Percentage margins and paddings on grid items can be resolved against either:
- their own axis (left/right percentages resolve against width, top/bottom resolve against height), or,
- the inline axis (left/right/top/bottom percentages all resolve against width).
A User Agent must choose one of these two behaviors.
Note: This variance sucks, but it accurately captures the current state of the world (no consensus among implementations, and no consensus within the CSSWG). It is the CSSWG’s intention that browsers will converge on one of the behaviors, at which time the spec will be amended to require that.
This issue exists in Flexbox, as well: Why doesn't percentage padding work on flex items in Firefox?
So your best bet at this point may be viewport percentage units.
From the spec:
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
.
Here's a rough sketch: revised codepen
Try replacing the padding with
height: calc(25vw - 1.5rem);
Or better yet, apply it to all the grid elements instead of just the first one:
.o-grid__item {
box-shadow: inset 0 0 0 1px red;
position: relative;
height: calc(25vw - 1.5rem); /* allow for the spacing between squares */
}
.o-grid__item--tall {
grid-row: span 2;
height: calc(50vw - 1rem);
}
.o-grid__item--wide {
grid-column: span 2;
}
There’s no “clean” way to achieve set aspect ratios for an element, grid or not. The zero height and percent-based padding trick is probably the most common solution to this.
The downside to this is it locks in the height of the element, so if the element is too small, its content will overflow.
I like a slightly different approach that uses a floated pseudo-element to achieve the same result, but also allows the element to grow to contain overflow if necessary:
.o-grid__item--wide::before {
content: "";
float: left;
padding-bottom: 50%;
}
.o-grid__item--wide::after {
clear: left;
content: " ";
display: table;
}
Using this inside a grid, you might want to get rid of your grid-template-rows
declaration. Otherwise, if one element grows to contain the overflow, it will change the height of all the other grid rows as well.
来源:https://stackoverflow.com/questions/43189390/fluidly-scaling-items-in-css-grid-layout