Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
An interactive guide to Flexbox (joshwcomeau.com)
813 points by brandrick on Nov 23, 2022 | hide | past | favorite | 87 comments



As someone who only needs to use Flexbox/Grid every once in a while, this is precisely what I needed.

I've been struggling with static documentation like the one from Tailwind [1] or MDN [2]. Writing good and intuitive documentation is hard, surely this must have been quite an effort.

[1]: https://tailwindcss.com/docs/flex-direction

[2]: https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layou...


For Flexbox https://css-tricks.com/snippets/css/a-guide-to-flexbox/ is the resource I would recommend, along with https://flexboxfroggy.com/ for a more interactive tutorial.

For CSS Grid, the equivalent resources would be https://css-tricks.com/snippets/css/complete-guide-grid/ and https://cssgridgarden.com/

These are all tutorial-level documentation. Once you've gone through those you can complement them with the MDN documentation on the individual properties as a reference.



I can't recommend the css tricks guide enough. I don't write enough css to know the properties by heart but with this resource it is easy to find quickly the property you need.


Yeah, I have both of those bookmarked myself. I know they sell posters of the articles. I've always wanted to get them, though they're a tad pricey. But I guess I can write it off as a business expense…


I wonder how many hits that article has. It must be one of the most visited development-related articles on the web.


Ah I came here to recommend Flexbox Froggy and Grid Garden! I didn't come across them until long after I needed them, which is really a tragedy, but I try to rectify it by linking them to everyone I come across who is learning css (which is a lot of people due to some Discords I'm in). They're adorable and wonderful, and if you don't use css frequently enough to keep the properties memorized, but do use it enough that it would be convenient to be slightly more familiar than needing to re-google constantly I recommend re-playing them once a year or so; they're honestly pretty fun just because they're so cute.


For CSS layout related stuff, I think video tutorials are a really good resource. In particular I like Kevin Powell who has guides on both subjects.


For Tailwind I put together "Tailwind Toucan" on my side project https://codeamigo.dev/lessons/243. Warning: it touches on more than flexbox.


Maybe more introductory than you're looking for, but I went through this once a few years ago and its stuck ever since: https://flexboxfroggy.com/

Now I just need one for Grid.



As far as I'm concerned, Flexbox Froggy is mandatory reading for anyone completely baffled by flexbox. It's really brilliant.

CSS grid is heaps more complex than the flexbox spec, so I think the Grid Garden one is not quite as useful. But seriously – if anyone is just squinting when staring at flexbox stuff, go check out that game.


I thought it was just me struggling with the tailwind flex docs...


I love flex, it's made CSS so easy. One of the things that improved my flex usage was using Penpot to draw my designs before implementing them.

They have alignment properties for graphical elements that work like flex's justify-content and align-items properties so once you design a view in Penpot it becomes almost trivial to translate it into HTML/CSS using flex.

It really changed my mindset from working with relative or absolute positioning, blocks, margins, padding, etc... to simply working with flex everywhere. And it's responsive automatically!


Just wait until you try CSS Grid :) IMO it's even more intuitive than Flexbox, at least for any 2 dimensional layout.


Grid and Flex serve different purposes for layout. Also Grid has many of the same keywords as flex, but is more complex. I wouldn't call it more intuitive.


For anyone unsure whether to use flex or grid, the mental shorthand that I use is whether the container or the elements in a container should have more control over the layout.

Flex is better if the individual elements should have some control over the layout, whereas grid is better if the container should be fully controlling the layout.

Great 20min tutorial vid with examples and details on the above: https://www.youtube.com/watch?v=3elGSZSWTbM


That's good advice—I like it.

Another data point I use is that if I find myself adding a container for the sole purpose of layout, I realize that I should be using grid. That is one of the biggest wins of grid: you don't need to pollute your markup with nearly as many layout/presentation-only elements.


Grid is also 2D capable whereas flex is supposed to be a one-axis situation.

You can nest flex such that it acts in a 2D way but it’s a bit annoying


For anyone unsure whether to use flex or grid, the mental shorthand that I use is whether the container or the elements in a container should have more control over the layout.

I guess I’m wondering why it’s any more complicated than:

* Flexbox is for formatting in one dimension (or axis)—a row or a column.

* Grid is for layout in 2-dimensions—columns and rows; a.k.a. a grid.

In fact, you can use flexbox and grid in the same layout, each doing its thing.


What I'd add your summary: Flex wrapping is a different kind of 2-dimension behavior than a grid, but they're both useful 2 dimensional layout behaviors.

In fact, you can use flexbox and grid in the same layout, each doing its thing.

100% At 17:30 near the end of that video I linked is an example of mixing them.


Are there any layout behaviors that are possible to achieve with flexbox but impossible with grid? Basically, setting aside inversion of control at the moment, does grid subsume flexbox?

Even the deconstructed pancake example in the posted article doesn't seem to be impossible with CSS grid but I haven't given it too much thought.


Grid and Flex serve different purposes for layout. Also Grid has many of the same keywords as flex, but is more complex.

I find CSS Grid easier to understand than Flex. I also think it's easier (arguably more logical) to start with Grid and then understand Flexbox and how fits in your Grid.

The problem is that popular frameworks like Bootstrap and Bulma still don't support CSS Grid (they use flexbox only for layout, although Bootstrap 5 has opt-in CSS Grid). You could argue that CSS Grid makes frameworks redundant for layouts only.

Developers have rightly complained how cumbersome CSS layout has been in the past. It's ironic CSS Grid is available in all modern browsers but developers still aren't using it.


Not sure, but grid seems to be not very framework-able. Bootstrap frees you from choosing geometry by traditional grid system where you just class-mark columns and that's it. CSS grid is a whole new ~sublanguage that you have to master.


Grid surely is more complex. For example: Units that appear nowhere else in CSS besides Grid, functions that are only used in Grid. It feels like a language inside a language.


"I like to think of CSS as a collection of layout modes. Each layout mode is an algorithm that can implement or redefine each CSS property. We provide an algorithm with our CSS declarations (key/value pairs), and the algorithm decides how to use them."

Brilliant. The way basic CSS properties are taught often ignores the layout mode. Even MDN does not mention that "width" is a CSS property that is not always respected when "display: flex". Making this distinction more prominent would reduce the amount of confusion/frustration when certain CSS properties appear to "not work".

[1] https://developer.mozilla.org/en-US/docs/Web/CSS/width


As someone who does more back-end work in my job, I love learning about this kind of front-end stuff that I don't get to use as often.

Flexbox has been great to work with because it's much easier to control your responsive design. You can choose what lengths stay fixed, which expand and shrink, etc.

When I learned how to use flexbox I went searching for how to add tools to my responsive-design toolbox. I learned about how to use media queries so that different CSS rules are applied based on the width of the page.

Flexbox, grid, and media queries are some of the heavy hitters in responsive design these days, but wanted to know more about effective use of things like CSS functions like calc, min, max, clamp, minmax (grid only) and when to use them. I can find reference material, but I haven't found any good resources that explain when you'd use them instead of something else.

Does anyone have a good resource for responsive design that covers use of CSS functions too? It's no good to have a tool in your toolbox if you don't know you should be using it.


Check out “Designing Intrinsic Layouts” by Jen Simmons—https://aneventapart.com/news/post/designing-intrinsic-layou...

Thanks to Flexbox and CSS Grid, you may not need media queries for most layouts.


I don’t have a good resource, but min, max, minmax are good if you have a responsive layout where elements change (under a parent container in vh, vw, %) but you also want to have a threshold that is not exceeded. Like min-width or max-width, but as a value instead of the explicit css property, which means you can set properties to equal that value.

MDN has some good explainers: https://developer.mozilla.org/en-US/docs/Web/CSS/clamp


Thanks. After reading your explanation it became clearer that the reason you use clamp is because you're using different units (e.g. rem vs %, px vs vw) and varying page dimensions may affect those units differently (e.g. 10% may be larger or smaller than 100px depending on the parent's width).

Here I read the entire MDN article on clamp and it didn't click in my mind until you explained it.


I use CSS basically every day but flex-basis, flex-grow and flex-shrink now clear. I had a gut feeling but no motivation to investigate further. If something doesn't work with flexbox I just use grid. Now Flexbox gets maybe some more use cases where grid is bit of an overkill.


Perfect timing. I'm working with tailwindcss, not by choice. And all good tailwind templates, buttons, styles are for purchase. I guess that is why I gravitate towards boostrap when I can.

But this site is helping a lot. Thank you.


This is actually something I love about tailwind. It doesn't create a layout abstraction. I solve 99% of my layout problems with 2/3 flexbox properties so I strongly recommend learning that.

CSS tricks has a very nice reference/guide: https://css-tricks.com/snippets/css/a-guide-to-flexbox/


Yes indeed. Layout abstraction is excellent until you need to do something it doesn’t expect, and then it turns into an absolute nightmare.


This used to be my go-to Flexbox reference, but Josh' guide supplanted it.


Try out Tailwind Toucan and let me know what you think! https://codeamigo.dev/lessons/243


We make plenty of Tailwind CSS templates for free at https://tailtemplate.com/


I created https://www.flexulator.com for a deeper look into how the spacing algorithm works, you can see how the values are calculated.


I played with this a bit, and found that it seems to give the wrong results. Check out:

https://imgur.com/a/0lGWShy

The numbers displayed (855, 144, 144) don't match the widths actually shown, the calculations look the same across all three panels even though they have different parameters, and the displayed calculations (e.g. -619 + 1000 = 855) don't add up.


Nice work on the interactive elements in this guide, they're delightful!


> "One of the biggest Flexbox quality-of-life improvements in recent years has been the gap property. Gap allows us to create space in-between each Flex child, along the primary axis."

He is not wrong. It's an underrated improvement.

I couldn't believe it when gap arrived last year (2021) out of nowhere to solve the biggest issue I had with flexbox. No more assigning margins to flex items and dealing with the annoying side effect of that margin applying between item and container edge, rather than just between each item. CSS gap is applied on the flex container, and items can have zero margin, and everything just works now in flexbox.


I just learned about gap from this article. Amazing. Yes dealing with margins between things but not on the edges was super annoying.

I guess it’s time I drop IE11 support.

https://caniuse.com/?search=gap


This is great.

Unrelated but I was just wondering

“Content warning I make a food-related metaphor later in this tutorial.”

Why did the author have to include a content warning for food?


I also saw this and was at a loss. I'm guessing for those with eating disorders/people who have food as some sort of trigger. I understand we should respect others, but a warning about food seems... excessive.


I've started seeing things like this recently too. For example I was browsing through a gallery of artwork by an artist and one was blurred because it contained "sensitive material". The warning stated "food" and when I clicked to reveal the image I found that it was simply a photograph of some freshly baked bread.


Interesting! I actually assumed it was simply a self-ironic joke by the author about his metaphor choice. I indeed laughed about this 'joke', but it might not even have been one in the end.


That's the kind of thing I'd include as a joke.


A challenge for anyone who wants one, and because I’ve been pulling my hair out over this:

Make a taller-than-wide rectangle that always fills the maximum available space of the viewport without breaking aspect ratio. Inside have two elements: a square that always fills the max space while maintaining aspect ratio, and a rectangle that takes up all of whatever is left. Inside the inner square lay out 64 (or any n^2) elements as the tiles (like a chess board). No JS.

I’ve been fighting with flex and grid and aspect-ratio and getting into one of those rare moments where I feel viscerally angry. I think the main issue is aspect-ratio is a very very weak property.


Here you go. Wrapping the element with an aspect-ratio in a flex container was key to getting it to apply the ratio. You also have to be aware that the default flexbox alignment is "stretch" which will override the size you specify, so you need to opt out of that by using `justify-content: center` (main axis) or `align-items: center` (cross axis) (start or end alignment will also work if that's where you want it. The inner rectangle doesn't require this because it has the bottom green rectangle to flex and take up the extra space.

  <!DOCTYPE html>
  <html>
    <head>
      <style type="text/css">
        * {
          box-sizing: border-box;
        }

        html, body {
          height: 100%;
        }

        body {
          background: #999;
          display: flex;
          flex-direction: column;
          align-items: center;
        }

        .tall-rectangle {
          height: 100%;
          aspect-ratio: 0.66;
          display: flex;
          flex-direction: column;
          background: red;
        }

        .square {
          background: black;
          width: 100%;
          aspect-ratio: 1;
          display: flex;
          flex-wrap: wrap;
        }

        .inner-rectangle {
          background: green;
          flex: 1;
        }

        .tile { 
          width: 12.5%;
          height: 12.5%;
        }

        .tile.odd-row { background: black; }
        .tile.odd-row.tile:nth-of-type(2n) { background: white; }

        .tile.even-row { background: white; }
        .tile.even-row.tile:nth-of-type(2n) { background: black; }

      </style>
    </head>
    <body>
      <div class="tall-rectangle">
        <div class="square">
          <div class="tile odd-row"></div><div class="tile odd-row"></div><div class="tile odd-row"></div><div class="tile odd-row"></div>
          <div class="tile odd-row"></div><div class="tile odd-row"></div><div class="tile odd-row"></div><div class="tile odd-row"></div>
          <div class="tile even-row"></div><div class="tile even-row"></div><div class="tile even-row"></div><div class="tile even-row"></div>
          <div class="tile even-row"></div><div class="tile even-row"></div><div class="tile even-row"></div><div class="tile even-row"></div>
          <div class="tile odd-row"></div><div class="tile odd-row"></div><div class="tile odd-row"></div><div class="tile odd-row"></div>
          <div class="tile odd-row"></div><div class="tile odd-row"></div><div class="tile odd-row"></div><div class="tile odd-row"></div>
          <div class="tile even-row"></div><div class="tile even-row"></div><div class="tile even-row"></div><div class="tile even-row"></div>
          <div class="tile even-row"></div><div class="tile even-row"></div><div class="tile even-row"></div><div class="tile even-row"></div>
          <div class="tile odd-row"></div><div class="tile odd-row"></div><div class="tile odd-row"></div><div class="tile odd-row"></div>
          <div class="tile odd-row"></div><div class="tile odd-row"></div><div class="tile odd-row"></div><div class="tile odd-row"></div>
          <div class="tile even-row"></div><div class="tile even-row"></div><div class="tile even-row"></div><div class="tile even-row"></div>
          <div class="tile even-row"></div><div class="tile even-row"></div><div class="tile even-row"></div><div class="tile even-row"></div>
          <div class="tile odd-row"></div><div class="tile odd-row"></div><div class="tile odd-row"></div><div class="tile odd-row"></div>
          <div class="tile odd-row"></div><div class="tile odd-row"></div><div class="tile odd-row"></div><div class="tile odd-row"></div>
          <div class="tile even-row"></div><div class="tile even-row"></div><div class="tile even-row"></div><div class="tile even-row"></div>
          <div class="tile even-row"></div><div class="tile even-row"></div><div class="tile even-row"></div><div class="tile even-row"></div>
        </div>
        <div class="inner-rectangle"></div>
      </div>
    </body>
  </html>
For CSS grid, you can use the same HTML with the following styles:

    <style type="text/css">
      * {
        box-sizing: border-box;
      }

      html, body {
        height: 100%;
      }

      body {
        background: #999;
        display: grid;
        grid-template-rows: 100%;
        justify-content: center;
      }

      .tall-rectangle {
        background: red;
        height: 100%;
        aspect-ratio: 0.66;
        display: grid;
        grid-auto-rows: auto 1fr;
      }

      .square {
        background: black;
        width: 100%;
        aspect-ratio: 1;
        display: grid;
        grid-template-rows: repeat(8, 1fr);
        grid-template-columns: repeat(8, 1fr);
      }

      .inner-rectangle {
        background: green;
        flex: 1;
      }

      .tile.odd-row { background: black; }
      .tile.odd-row.tile:nth-of-type(2n) { background: white; }

      .tile.even-row { background: white; }
      .tile.even-row.tile:nth-of-type(2n) { background: black; }

    </style>


Thanks for the tip about flexbox defaulting to stretch! That goes a long way.

I think your solution is very close but breaks when I scale down the width of my viewport. If I set Chrome dev to iPhone 12 Pro or iPhone SE, for example, the chess board starts getting cut off.


> I think your solution is very close but breaks when I scale down the width of my viewport. If I set Chrome dev to iPhone 12 Pro or iPhone SE, for example, the chess board starts getting cut off.

Hmm... what would you like it to do in that case? Start shrinking the height? You can try adding `max-width: 100%` to the tall rectangle.


I’ll try tomorrow at a PC.

Yeah I think so. The idea is to fill as much of the viewport as possible but always maintain aspect ratio. Oh did I describe the challenge/problem poorly maybe? Sorry!

Still, you’ve gotten closer than I.


Old guy here. I can remember fighting with and complaining about horizontal scroll bars on wide html pages. I didn't realize how good I had it. Now I fight with browser based UI's that rearrange themselves to fit in whatever width the browser is set to. Sounds good. Oh, that nav-bar on the left side doesn't fit? No problem. Now it appears as a set of sub-tabs arranged horizontally. The app knows where things are, but I don't. No thanks.

Don't get me started on links that aren't underlined blue font and only reveal themselves on mouse-over.


Fellow old guy here. I abhorred the blue text and forced outlines. It was like engineers came up with a UI without talking to people experienced with graphic design. In fact, it looks exactly like every single UI I had ever created until CSS became functionally useful. Now, everyone of my UIs looks like an engineer that took a design boot camp made it instead my code looking like a designer taking a coding boot camp made it.

I know my UIs look bad. I've been in/around graphics/design/desktop publishing/etc for a long enough time to recognize it. I just don't know how to fix it. Now, I just make it functional enough to work, but never to a place that someone would ever think "this is good enough we don't need a designer involved".


This is a beautiful, immensely valuable resource - straight into my bookmarked notes. Thank you!


This is really good, the language, the examples, just everything. It's right up my alley.


It seems like in the example widgets baseline and flex-start appear the same. But according to https://stackoverflow.com/questions/34606879/whats-the-diffe... they do different things. Josh's examples have text in them, so why is it not aligning to the baseline of that text?

Windows 11/Latest Chrome FWIW :-)


Yeah, I was worried people would wonder about this!

It doesn't appear to have an effect in this example because all of the text is the same size (and therefore, they do all share the same baseline). In the devtools, try bumping one of the items up to font-size: 2rem, and you'll see the effect it has.

My initial version of this post didn't have “baseline” as an option, since yeah it doesn't demonstrate it well, but I figured people would wonder why a single value was excluded.

Incidentally, baseline alignment is so handy, but I couldn't fit everything into this post. We cover it in more detail in my course (https://css-for-js.dev/)


Pushing an update now that sets different font sizes for the 4 children, so that this can be observed!


That is great, thanks. And thanks for this resource. If there is one thing I hate it is re-reading about flexbox. But playing with a widget is much more fun and tells me in 10 seconds what I need to know.


Easily one of the best guides of flexbox, and this is coming from a mostly backend guy that can never remember flexbox for long term, and always needs a refresh about it.


That reminds me again that flexbox is so needlessly complex that you need quite non-trivial guides each time you use it.

It could be significantly simpler and, well, flexible:

https://terrainformatica.com/2018/12/11/10-years-of-flexboxi...


core algo is simple, the complexity goes from everything else, which still needs to work with flexbox (min/max, relative/absolute/fixed, relative units everywhere, calcs, and the concept of min-content or whatever that is, for which you need to recursively call algos down even when in theory the size should be known already - text-specific)

the only stupid thing is the "loop until there is no deviation", but I think it's not mandatory for most of the real-world layouts and one pass is enough.

the naming of those alignments is hard to remember, but that's it, it's not complex, it's just very unfortunate.


I think in almost every real world scenario, the loop only runs once. I don't think it adds a huge amount of complexity to the layout algo - you still need to code in the loop body, even if you don't actually loop. That said - React Native only does two passes, and nobody seems to have noticed/complained.

You can do some neat things with the looping behaviour - like have a toolbar with some icons on the left and the right hand sides and a title centred in the toolbar - but then have the title move off centre as soon as the icons from either side touch it.


"core algo is simple"

It is not that simple. In common case that's an LP task. It can be reduced to O(N) in some cases but in worst case it has polynomial time-complexity.


What's your take on grid? I still can't quite grok the algorithm - but from your article, your proposal seems really similar to what's available with grid.

Grid does suffer from not being able to set min/max track sizes - like have a sidebar be say 20% of the width, but clamped between 200px and 300px


   sidebar {
     width:0.2*; //20% of the width
     min-width: 200px;
     max-width: 300px;
   }


I noticed a lot of developers rave about flexbox, but not so much about grid.

It is my understanding that flexbox was intended for 1D layouts and grid was intended for 2D layouts. We've been using grid for the overall page layout and flex inside certain regions.

Is there something I am missing here, or are we finding that the hammer is pretty good at screws too?


I would say the 1D/2D thing is a summary/rule of thumb. But grid can be useful for "1D" (linear) layouts too -- I feel like I've used it for something that was harder to do with flex even though it was linear, although I can't recall specifically. And flex can certainly be useful for some "2D" things depending on what you mean by that.

Grid is newer, and somewhat more complicated. Newer is probably the main reason it seems less popular than flex.


> Grid is newer

That's probably it. grid-template is a hell of a property too... Took me quite some time to figure it out.


CSS is grid is newer than Flexbox and has lower browser support, caniuse says 99.74% vs 96.95%. Overtime I imagine we'll see more utilization though

• Grid usage: https://caniuse.com/?search=css%20grid

• Flexbox usage: https://caniuse.com/?search=flexbox


I think its a reality that by and large most developers are coupled to some CSS / Component framework that they aren't writing all the CSS from scratch, and most of these frameworks only (currently, when I last surveyed, say ~3 months ago) provide Flex based CSS utilities. Until recently this was particularly true of Bootstrap and Zurb Foundation which were arguably the most popular of the CSS frameworks.

I also think its general knowledge. Took a really long time for everyone to use Flexbox too. Even as late as 2016/2017 I saw engineers still reach for things like unsemantic[0] (the 960 Grid successor) and other utilities like it if they were doing custom layouts.

[0]: https://unsemantic.com/


The hammer is pretty good at screws.

And CSS grid is only working on pentalobe screws, until subgrid is usable.

https://caniuse.com/?search=subgrid


I’d love an interactive guide that reflects real life experience with css, where every property mysteriously doesn’t work.


To make complete layouts, you still need to creatively combine (nested) Flexbox with other CSS features. Flexbox was a huge improvement, but I continue to see the need for "tricks" articles that give you well thought-out solutions to practical layout cases.


I wonder if the most use cases today could justify flex as a default where `display:block` is a default and s/inline-block/inline-flex/ .. I often have an anxiety of using too many flex elements. How many cases where there's a need to un-flex?


This is the one I use to get me some layout needs quickly:

https://codepen.io/justd/full/yydezN/


Is there a way to remember what justify/align-content/items do on a column or row? I write css semi-rarely and go through all options in dev tools until it’s the one I want..


Try grid too - unless you need flexing, it's simpler than flexbox, even for single columns or rows.


this depends on what you know ... grid is way more mighty and you have to take know what to do if you want to behave like flexbox.


> grid is way more mighty

I don't know what you mean by `mighty'

> you have to take know what to do if you want to behave like flexbox.

yes, as mentioned, that is if you want flexing. Most people don't want flexing - most layouts are static, grid-based and only change based upon media queries, where CSS grid is very similar.


Who forgets their middle initial?


Amazing guide, thanks!


Why is it that any 2 year old can come up with a more concise, precise, and easy to understand layout system than any that has ever been invented?


I think this is a great tutorial but I also think it's absolutely not needed because of how many other similar guides have already been done.

Now, I'm not trying to be arrogant about it either.

This tutorial could have been 10 times better if Josh didn't pretend like what he wrote hasn't already been done (it has been, a million times, and I don't know why you'd keep beating this dead horse over and over again) - and instead made this same exact tutorial but actually built functional layouts in the process. You know, web pages that use Flexbox.

People don't learn by clicking on fancy buttons that rearrange some boxes in a specific order. People learn by example and by visually seeing the consequence of an action (in this case, the value of a property).

No offense meant at all to the author, of course.


Well, it made flexbox finally click for this old hand, so thanks Josh.


Of course it did.




Consider applying for YC's Fall 2025 batch! Applications are open till Aug 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: