Hacker News new | past | comments | ask | show | jobs | submit login
Flexbox Cheatsheet (yoksel.github.io)
202 points by AllThingsSmitty on Mar 15, 2017 | hide | past | web | favorite | 37 comments

I always viewed https://css-tricks.com/snippets/css/a-guide-to-flexbox/ as the definitive flexbox resource, and https://github.com/philipwalton/flexbugs for browser specific issues

While CSS Tricks certainly is a lot more thorough, I've always found the "throw stuff at the wall" ordering of content (a la Pinterest) to be confusing for things where I probably need to find something specific, or want to read things in order. I think that's where this resource can come in handy.

FYI: I get an invalid certificate warning. Looks like it's presenting the github wildcard certificate, rather than a certificate with your domain in.

Thanks but not my site.

There's also this slightly more visual approach to learning flexbox: https://www.flexboxgame.com/

Whoa, that was much more effective than I thought it was going to be. The first impression from the tool sidebar is overwhelming, but patterns quickly emerge and you can pick up speed fast.

It's very satisfying to see layouts "just work" through the application of one or two simple but descriptive commands.

Same. Separating the container from the items makes it easier to grok. A lot of the browser bugs arise in deeply nested containers, so judicious use has saved a lot of legacy design headache and still allowed me to roll it out with very good support on desktop and mobile.

Thanks for this. I haven't kept up to date on my CSS. Great to know flexbox is fully supported across the board now.

Just for the history...

At early stages of flexbox idea discussion I proposed (at W3C's www-style WG) it to be implemented in form of two entities:

The flow property describing children layout manager:

and flex length units, describing "spring power" used by the property.

    width:1*; margin-left:2* 
for example.


That schema has very simple physical model that does not require any need for cheatsheets - very simple. Just to walk over illustrations in the document above to get the idea.

Current (accepted) flexbox variant is too controversial IMO. Yet breaks existing CSS box model somehow, what would be the used box width in this case:

    div {
       flex: 1;
two properties compete for the same entity (width of the box) - basic architectural error IMHO.

My flexbox story:

I decided to use flexbox. Everything was wonderful - responsive sizing was perfect. So easy to use. I then tried it on Safari.

First port of call: older versions of Safari don't calculate widths based on min / max width property but rather a flex specific property (can't remember which).

Didn't work. Tried a polyfill - the polyfill landscape for flexbox is shockingly bad.

At this point, I'd give up hope. I turn to Modernizr so I can fall back to display table. Got this set up (modernizr only really does custom builds apparently, no CDN now).

Surprise. Safari was flagging up with modern flexbox support. The autoprefixer I used set the WebKit vendor prefix to use legacy flexbox. Chrome uses the non prefixed property fine. Other browsers were fine. Safari was still using the vendor prefix. Fin.

tl;dr flexbox embarrassed me.

If you're looking for modernizr CDN, see https://cdnjs.com/libraries/modernizr

I believe this is an old version. For new versions, i think you have create a custom build.

I still wonder why we have

    display: flex

    display: inline-flex
It seems to me that the committee who designed this has been confusing what is happening inside the box (flex or not) with what is happening outside the box (inline or block). Those two behaviors should be orthogonal, IMHO.

> It seems to me that the committee who designed this has been confusing what is happening inside the box (flex or not) with what is happening outside the box (inline or block).

That has nothing do do with "the committee who designed this", the issue has been inherited all the way from CSS 2's inline-block, which defines `display` as a single-value property altering both inner and outer display types.

> Those two behaviors should be orthogonal, IMHO.

Which is why Display Module Level 3 exists https://www.w3.org/TR/css-display-3/#the-display-properties.

However Display 3 is a Working Draft, and thus not available to flexbox (or grid), so until then they need an inline- prefixed "legacy" value.

Problem is in another architectural error that authors of the spec have made. In fact flexbox is the worst CSS spec ever produced - too many problems yet bloated.

display is a wrong CSS property for that. The display defines requirement of the element to its container.

For example

    div { display:inline-block; }
demands that div itself to be placed inside line-box container in a row with other inline elements.

But the flex is about quite different entity: specification of how children of the container shall be replaced.

That's why there is a need for the whole zoo:

   display: table | inline-table | flex | inline-flex | grid | inline-grid | etc.
Yet even this does not solve principal problem. What if I want to have display:list-item that uses flexes inside. No way...

It is really should be

    display:list-item; // list item 
    flow:horizontal;   // children replaced horizontally
                       // with flexes if needed 
or some as such.


Truly there should be no use case for the "inline-" prefixed properties anymore. Your HTML+CSS systems should denote layout strictly from parents ("cascading!") and any exceptions to your rules would exhibit either an unsatisfactory rule or an inconsistent design.

It's interesting (and reasonable) that cascade has become synonymous with inheritance, while the standard defines it as the process that looks at importance and origin, followed (if necessary) by specificity, followed by order: https://www.w3.org/TR/CSS22/cascade.html#cascade

In my usage I meant to express that a modern system should be constructed similarly to how flexbox and grid determine the "display" property of the selected element's children.

If your code constantly requires manual display:inline-block; on elements (and it's not just to override the browser's default stylesheet), then you probably aren't adhering to a consistent pattern and your CSS's maintainability will eventually drop off at an exponential rate.

Flexbox enables you to even avoid patterns like .inline-list>li{float:left;}, so sibling-level specificity isn't going to align with best practices anymore in the near future.

Oh, I agree with your comment. I guess I should have quoted the part that led to my rather off-the-topic remark:

parents ("cascading!")

I wonder whether the people who coined the term CSS also had in mind cascading as related to inheritance, or maybe even only this meaning, and later the standards "lawyers" tied the term cascade to the definition I cited. Thanks for replying.

What is the correct way to achieve, say, the example that article uses for inline-flex?

In anything implementing the current draft of CSS Display Module Level 3, the `display` values we commonly use today become a shorthand for two orthogonal properties.

For example, `display: block` becomes shorthand for `display: block flow`, where `block` is the <display-outside> and `flow` is the <display-inside>.



> The `display` property defines box’s display type, which consists of the two basic qualities of how an element generates boxes:

> * the inner display type, which defines [...] the kind of formatting context it generates, dictating how its descendant boxes are laid out.

> * the outer display type, which dictates how the box participates in its parent formatting context.


> <display-outside> = block | inline | ...

> <display-inside> = flow | flow-root | table | flex ...


   Short `display` | Full `display`     | Generated box
   'block'         | 'block flow'       | block-level block container
   'flow-root'     | 'block flow-root'  | block-level block container that establishes a new block formatting context
   'inline'        | 'inline flow'      | inline box
   'inline-block'  | 'inline flow-root' | inline-level block container
   'flex'          | 'block flex'       | block-level flex container
   'inline-flex'   | 'inline flex'      | inline-level flex container


It looks like there were, in the first draft of the spec, independent `display-inside/outside` properties, with `display` being a "one property that sets multiple properties" shorthand:


But that has since been changed to `display` being a "one property that takes multiple values" shorthand, in the current version of the spec:


> Changes since the 11 September 2014 Working Draft include:

> Removed `display-inside`, `display-outside`, and `display-extras` longhands, in favor of just making `display` multi-value. (This was done to impose constraints on what can be combined. Future levels of this specification may relax some or all of those restrictions if they become unnecessary or unwanted.)

Even that display-inside is a fuzzy one. What does it mean

   display-inside: block;
for example? I would expect flex-direction to go there

   display-inside: default | row | column | ... ; 
So display-inside: row; will replace children horizontally.

In this formulation, `block` is a <display-outside> value, and would not be valid as a <display-inside> value.


<display-inside>, which can be `flow`, `flex`, `grid`, etc, but not `block`:

> defines [...] the kind of formatting context it generates, dictating how its descendant boxes are laid out"


Which, as I interpret it, is "just" another level of indirection on top of your proposal, providing a mechanism for more messy and incompatible, legacy and future, layout systems to coexist.

So if I have this:

   img-row {
     display: block flow;
and markup

     <img src=1.png>
     <img src=2.png>
     <img src=3.png>
I will still have a problem with white space appearance between image of these [inline-]blocks ?

While with this:

   img-row {
     display: block;
child images will be treated as blocks and so white spaces will not go into rendering/layout tree of the img-row.

So again partial solution, sigh.

As far as I can tell, the only way the source-whitespace will appear is when both of the following are true:

1. The parent has `display-inside: flow` or `display-inside: flow-root` (ie, the "original", pre-flexbox, formatting contexts)

  eg `display: block`, `display: inline`, `display: inside-block`
2. The children have `display-outside: inline`

  eg, `display: inline`, `display: inline-block`, `display: inline-flex`
In any other combination, the source-whitespace disappears, in some way or other.


What I think you want, a horizontal row disregarding source-whitespace, could be achieved with `display-inside: flex` (eg, `display: flex`, `display: inline-flex`) on the parent (with `flex-direction: row` being the default). So:

    img-row {
        display: flex;

    img-row {
        display: block flex;
aka (though this syntax has been temporarily removed)

    img-row {
        display-outside: block;
        display-inside: flex;

    img-row {
        display-outside: block;
        display-inside: flex;
        flex-direction: row; /* the default */

Note that this longhand syntax doesn't seem to be implemented in Chrome, at least, yet. So if you want to check it out, you'll have to work in the shorthand (still translatable from the longhand as specified in the draft spec https://drafts.csswg.org/css-display/#propdef-display).

As far as I understand

    display-inside: flow;
is the current (default) layout method. So all runs having characters (including spaces) and children that have display:inline | inline-block will be replaced in line boxes preserving spaces between them (consecutive spaces are collapsed into one but still they will be there).

But suddenly all children that have display:block will be a) replaced on new row each and b) with spaces between them ignored.

Such a dichotomy is the source of weird hacks, like advices to remove spaces between blocks at all, etc.

Yes, it is my understanding that one of the major, inviolable design goals in this is not to break any old behaviour, or any such (yes, totally distasteful) "hacks" dependent on it. Now that particular old behaviour is "isolated" under the `display-inside: flow` formatting context, which has to remain the default.

Lets go back to the spec draft:



> The display property defines box’s display type, which consists of the two basic qualities of how an element generates boxes:

> * the inner display type, which defines [...] the kind of formatting context it generates, dictating how its descendant boxes are laid out.

> * the outer display type, which dictates how the box participates in its parent formatting context.


> <display-inside> = flow | flow-root | table | flex ...

> <display-outside> = block | inline | ...


It's not just the reframing into `display-inside` (how to lay out children) and `display-outside` (how to participate in parent) which addresses your problem -- that just provides a new way to specify the same behaviour as before. Split into 2 orthogonal axes, cleanly leaving room for new behaviour to exist in combination with old behaviour.

But, rather, it's that plus the specific provision of `display-inside: flex`, within this new framing, which addresses your problem.

If you stick with `display-inside: flow` in your examples of things that are problems, of course nothing is going to change, because that specifically specifies "behave like you always used to".

I'm honestly not sure I understand your complaint. I'm definitely open to the possibility that this is an internally-inconsistent or short-sighted solution, but I'm not seeing it here.

> But that has since been changed to `display` being a "one property that takes multiple values" shorthand, in the current version of the spec

FWIW, there is a WG resolution to have display-inside/outside properties in Level 4.

bring back tables with some responsive behaviour and we can call it a day

I bookmarked this and thank you for posting it! As a Webflow user it is really nice to have a clear visual guide to the underlying CSS so I understand exactly what is happening especially when I break something.

Could someone please recommend a javascript library that allow one to use flexbox without requiring a deep knowledge of idiosyncrasies of different implementations of Flexbox ?

Well JavaScript isn't really relevant here, but bootstrap v4 is using flexbox now

The one annoying thing is that there is a bug in safari. You can't do a flex-basis of a % if you want it to work.

This bug exists in IE11 as well. This is especially annoying when using Boostrap 4 with flex grid system (although it's still alpha).

This got my hopes up that flex-basis: content was working in more places.

Great resource I'll be sure to use it :) Are you using a theme or is it custom made? It's really nice!

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