Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flex-wrap with rows of different heights

Tags:

html

css

flexbox

I am implementing css-only tabs with hash-tag linking. I'm very very close but can't quite get the flex wrapping to work properly. In order for everything to work they way I want it to with :target (I've done this before with radio buttons and that gives a bit more flexibility), I need all tabs and all sections at the same level so I have:

body
  section
  anchor
  section
  anchor
  ...

I can then use flexbox ordering to make all anchors appear first and style the appropriately, set all sections to width 100% and use flex-wrap to allow them to wrap to the next line. The problem is that I seem to be unable to control the height of the first row. What's going on here?

body {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  margin: 0;
  padding: 0;
  height: 100vh;
  outline: 1px solid green;
}
body > a {
  padding: 10px;
  margin: 0 5px;
  order: -1;
  flex-grow: 0;
  border: solid gray;
  border-width: 1px 1px 0 1px;
}
body > a:last-of-type {
  order: -2;
}
section {
  flex-grow: 1;
  width: 100%;
  background-color: cornsilk;
  display: none;
  border-top: 1px solid grey;
}
section:last-of-type {
  display: flex;
}
a {
  font-weight: normal;
}
a:last-of-type {
  font-weight: bold;
}
:target {
  display: flex;
}
:target ~ section {
  display: none;
}
:target ~ a {
  font-weight: normal;
}
:target + a {
  font-weight: bold;
}
<section id="advanced">
	Advanced Stuff
</section>
<a href="#advanced">Advanced</a>

<section id="home">
	Home Things
</section>
<a href="#home">Home</a>

Slightly easier to play with jsbin

The issue is that the tabs in the first row stretch to the height of the visible section rather than collapsing to the height of their contents. Even a specific height and max-height seems to be ignored.

Please note, the question is specifically about line heights when wrapping with flexbox. I know a million different ways to build tabs both in css and js. I'm specifically looking for a deeper understanding of flex-wrap.

like image 542
George Mauer Avatar asked May 31 '16 19:05

George Mauer


People also ask

How do you show 3 items per row in flexbox?

For 3 items per row, add on the flex items: flex-basis: 33.333333% You can also use the flex 's shorthand like the following: flex: 0 0 33.333333% => which also means flex-basis: 33.333333% .

What can I use instead of flex-wrap?

An alternative to using flex-wrap: wrap would be to switch from flex-direction: row to column using a media query. Show activity on this post. An other alternative to flex is to remove display: flex on the container and use display: inline-block on all item images.


1 Answers

Two initial settings of a flex container are align-items: stretch and align-content: stretch. You can override this by changing the value to flex-start.

But that seems to solve only part of the problem. You also want selected wrapping items to stretch the full height of the container.

This isn't happening because when flex items wrap they take only the minimum size necessary to contain their content.

From the flexbox spec:

6. Flex Lines

In a multi-line flex container (even one with only a single line), the cross size of each line is the minimum size necessary to contain the flex items on the line (after alignment due to align-self), and the lines are aligned within the flex container with the align-content property.

In other words, when there are multiple lines in a row-based flex container, the vertical height of each line (the "cross size") is the "minimum size necessary to contain the flex items on the line".

To make your layout work you would need a combination of row- and column-direction flex containers, along with an adjustment to the HTML.

like image 63
Michael Benjamin Avatar answered Oct 12 '22 14:10

Michael Benjamin