One of the most notoriously difficult parts of the CSS flexbox spec to understand is the eponymous flex
property, which uses cryptic values like 1 1 auto
. Confusion only deepens when the designer discovers that flex
is merely a shortcut for properties with even stranger names like flex-grow
and flex-basis
.
Most explanations of the flexbox spec are fairly technical and dense, with few concessions to visual thinkers. After struggling with the properties and values, I realized that these aspects of flexbox are actually talking about visual weight.
A Not-So-Egalitarian Algorithm
It would be reasonable to assume that the flexbox model might start by distributing all flexbox items equally. That is, given a series of <article>
elements inside a <section>
:
<h1>The Fortean World Times</h1>
<section>
<article>
<img src="earth-vs-the-flying-saucers.jpg" alt>
<h1>Washington D.C. Attacked By Flying Saucers</h1>
<h2>Dateline Washington D.C.</h2>
<h3>Frank Bragg reporting</h3>
<p>The country was brought to a standstill today when flying saucers appeared over the nation’s capital.
</article>
<article>
…
</section>
With the <section>
provided with display: flex
, you might expect each article to have equal width by default, but that’s not the case:
As you can see, the flex items have different widths, depending on their content.
Providing Flex Items With Equal Width
If we have three articles in the <section>
you might go to the instinctive solution of giving each <article>
a width of 33% to make them equal. While that will work, it’s a suboptimal solution that removes many of the advantages of flexbox layout. Instead, I would recommend the following:
article { flex: 1 0 0px; }
Which translates to:
flex-grow: 1;
- “make sure this element grows in width equally to all other flex items with a value of flex-grow: 1”
flex-shrink: 0;
- “don’t shrink this element more than any others to fit in the available space”)
flex-basis: 0px;
- “start this element at 0 pixels wide, and adjust from there”
In turn, this can be shortcut to:
article { flex: 1; }
I would recommend using this shortcut in your CSS: not only is it quicker to write, but it has better support cross-browser right now.
Written as part of the following CSS:
section {
display: flex;
}
article {
margin: 1rem;
flex: 1;
}
article img {
width: 100%;
height: auto;
}
… the CSS creates equal width and distribution of the flex “columns”:
The advantage of this system is that it’s adaptive: add another <article>
element, and the space is distributed automatically between them, with all articles keeping the same width, and no need to adjust any of your CSS.
Providing A Flex Item With More Visual Weight
The example we’ve been working on displays articles for an online newspaper. For such a layout, it would make sense that you would occasionally need a larger space for a breaking story, which we’ll apply as a class
:
<article class="breaking">
It’s reasonable to assume that breaking stories should always take twice as much space as any other articles on the page. I’ll use another flex
shortcut to define a new flex-grow
value for this particular class:
article.breaking { flex: 2; }
However it is applied, flex-grow
remains true no matter how big or small the space for the articles becomes: the breaking news article remains always twice as wide as the others: i.e. it always has twice as much visual weight. (The article’s height is determined by it’s content, by default, following standard web layout principles: the one special consideration is that all flex items in a row are the height of the item with the most content).
Adding A Solution For Small Screens
Obviously at a certain point cramming articles side-by-side will create unreadable content. At a reasonable breakpoint, we’ll distribute the articles in a column, rather than a row:
@media screen and (max-width: 750px) {
section {
-webkit-box-orient: vertical;
flex-direction: column;
}
}
Note that flex-grow
doesn’t make any difference now: all the articles are the same width when they are arranged vertically, with each article’s height determined by its content.
Conclusion
grow
is only one part of the visual weight controls in flexbox: the next articles in this series will deal with the two other aspects, flex-shrink
and flex-basis
.
Enjoy this piece? I invite you to follow me at twitter.com/dudleystorey to learn more.
Check out the CodePen demo for this article at https://codepen.io/dudleystorey/pen/umrnE