I am just learning how flexbox works and want to build a very rough prototype to see if flexbox can handle this layout.
I basically want to see if flexbox can support a 4-column table with varying width and height, but with consistent row height.
I'm not sure I am explaining the layout so well, so here is a quick sketch of what I am after:
So what I am concerned with is this: If I was making this using HTML tables, regardless of how much height a particular column has, each row will be consistent.
It can be changed by using the flex-direction property. To use flexbox, we have to set display: flex or inline-flex to flex-container. By default, the height and width of a flex-container are set to auto. But we can define a fixed amount to them.
CSS grids are for 2D layouts. It works with both rows and columns. Flexbox works better in one dimension only (either rows OR columns). It will be more time saving and helpful if you use both at the same time.
Flexbox is a layout model that allows elements to align and distribute space within a container. Using flexible widths and heights, elements can be aligned to fill a space or distribute space between elements, which makes it a great tool to use for responsive design systems.
The basic difference between CSS Grid Layout and CSS Flexbox Layout is that flexbox was designed for layout in one dimension - either a row or a column. Grid was designed for two-dimensional layout - rows, and columns at the same time.
I basically want to see if flexbox can support a 4-column table with varying width and height, but with consistent row height.
Simply put, one good feature Flexbox share with HTML Table, is that flex item's on the same row can have the same height, which is controlled by the align-items
property. Its default value is stretch
, and will by that make items on a row equal high.
.flex-container {
display: flex;
flex-wrap: wrap; /* allow items to wrap */
justify-content: space-between; /* vertical */
align-items: stretch; /* horizontal, is default
and can be omitted */
}
.flex-item {
flex-basis: 23%; /* give each item a width */
background-color: #ccc;
padding: 10px;
box-sizing: border-box;
}
.flex-item:nth-child(n+5) {
margin-top: 10px; /* from 5th item, add top margin */
}
<div class="flex-container">
<div class="flex-item">Left<br>high</div>
<div class="flex-item">Middle/Left</div>
<div class="flex-item">Middle/Right</div>
<div class="flex-item">Right</div>
<div class="flex-item">Left</div>
<div class="flex-item">Middle/Left</div>
<div class="flex-item">Middle/Right</div>
<div class="flex-item">Right</div>
<div class="flex-item">Left</div>
<div class="flex-item">Middle/Left</div>
<div class="flex-item">Middle/Right<br>higher<br>higher</div>
<div class="flex-item">Right</div>
</div>
One thing that might be worth mentioned, is what Flexbox doesn't share with HTML Table.
If an item's content will be wider than the rest of the items in the same column, the other items won't adjust their width to equal the widest.
.flex-container {
display: flex;
flex-wrap: wrap; /* allow items to wrap */
justify-content: space-between; /* vertical */
align-items: stretch; /* horizontal, is default
and can be omitted */
}
.flex-item {
flex-basis: 23%; /* give each item a width */
background-color: #ccc;
padding: 10px;
box-sizing: border-box;
}
.flex-item:nth-child(n+5) {
margin-top: 10px; /* from 5th item, add top margin */
}
<div class="flex-container">
<div class="flex-item">Left<br>high</div>
<div class="flex-item">Middle/Left - is wider</div>
<div class="flex-item">Middle/Right</div>
<div class="flex-item">Right</div>
<div class="flex-item">Left</div>
<div class="flex-item">Middle/Left</div>
<div class="flex-item">Middle/Right</div>
<div class="flex-item">Right</div>
<div class="flex-item">Left</div>
<div class="flex-item">Middle/Left</div>
<div class="flex-item">Middle/Right<br>higher<br>higher</div>
<div class="flex-item">Right</div>
</div>
By prevent flex item's to shrink, and enable them to be smaller than their content, it is possible to force equal width.
Note, overflow: hidden
(or any value other than visible
) has the same effect as min-width: 0
has, so in below sample min-width
can be omitted.
.flex-container {
display: flex;
flex-wrap: wrap; /* allow items to wrap */
justify-content: space-between; /* vertical */
align-items: stretch; /* horizontal, is default
and can be omitted */
}
.flex-item {
flex-basis: 23%; /* give each item a width */
background-color: #ccc;
padding: 10px;
box-sizing: border-box;
flex-shrink: 0; /* prevent from "shrink to fit" */
min-width: 0; /* allow to shrink past content width */
overflow: hidden; /* hide overflowed content */
}
.flex-item:nth-child(n+5) {
margin-top: 10px; /* from 5th item, add top margin */
}
<div class="flex-container">
<div class="flex-item">Left<br>high</div>
<div class="flex-item">Middle/Left - is wider</div>
<div class="flex-item">Middle/Right</div>
<div class="flex-item">Right</div>
<div class="flex-item">Left</div>
<div class="flex-item">Middle/Left</div>
<div class="flex-item">Middle/Right</div>
<div class="flex-item">Right</div>
<div class="flex-item">Left</div>
<div class="flex-item">Middle/Left</div>
<div class="flex-item">Middle/Right<br>higher<br>higher</div>
<div class="flex-item">Right</div>
</div>
A more appropriate comparison would be with CSS Grid, which can do pretty much everything HTML Table can, and then some :)
Here is two great guides to Flexbox and CSS Grid:
Consistent row heights are actually a default setting in flexbox.
You cannot get equal height rows in a flex container, meaning all rows share the same height. For that you could use CSS Grid layout.
But with flexbox each row by itself can be the same height across all columns.
body {
display: flex;
justify-content: center;
}
.container {
display: flex;
flex-wrap: wrap;
width: 75%;
}
.box {
flex: 1 0 20%; /* see note below */
margin: 0 5px 5px 0;
background-color: lightgreen;
display: flex;
justify-content: center;
align-items: center;
font-size: 1.2em;
}
<div class="container">
<div class="box">GROUP 1</div>
<div class="box">text text text text text text text text text text text text text text text text</div>
<div class="box"></div>
<div class="box"></div>
<div class="box">GROUP 2</div>
<div class="box"></div>
<div class="box">text text text text text text text text</div>
<div class="box"></div>
<div class="box">GROUP 3</div>
<div class="box"></div>
<div class="box"></div>
<div class="box">text text text text text text text texttext text text text text text text text</div>
<div class="box">GROUP 4</div>
<div class="box">text text text text text text text text</div>
<div class="box"></div>
<div class="box"></div>
</div>
With regard to flex: 1 0 20%
, here's the underlying concept:
The flex container is set to wrap
.
On the flex items, with flex-grow: 1
defined in the flex
shorthand, there's no need for flex-basis
to be 25%, which would actually result in three items per row due to the margins.
Since flex-grow
will consume free space on the row, flex-basis
only needs to be large enough to enforce a wrap. In this case, with flex-basis: 20%
, there's plenty of space for the margins, but not enough space for a fifth item.
More information:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With