Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can flexbox handle varying sizes of columns but consistent row height?

Tags:

html

css

flexbox

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:

enter image description here

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.

like image 220
Blankman Avatar asked Jan 29 '18 02:01

Blankman


People also ask

Can you set height of flexbox?

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.

In what situations is it better to use flexbox than grid?

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.

What are the benefits of using the flexbox layout?

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.

What are the main differences between flexbox and grid layout?

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.


2 Answers

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.

  • Dynamic equal column width.

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&nbsp;-&nbsp;&nbsp;is&nbsp;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&nbsp;-&nbsp;&nbsp;is&nbsp;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:

  • https://css-tricks.com/snippets/css/a-guide-to-flexbox/
  • https://css-tricks.com/snippets/css/complete-guide-grid/
like image 178
Asons Avatar answered Oct 10 '22 21:10

Asons


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>

jsFiddle demo

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:

  • Equal height rows in a flex container
  • Equal height rows in CSS Grid Layout
like image 24
Michael Benjamin Avatar answered Oct 10 '22 20:10

Michael Benjamin