Flex suggestions


#1

So after the great and useful Flex workshop that @fantasai ran, several crazy suggestions were asked. Here is a list of things that I mentioned that would be useful.

@tabatkins Fantasai already mentioned how hard some of these are to implement, however I still think they are worth considering.

Collapse of outer margins

Flex containers don’t currently have the ability to collapse the outer margins of its elements which get taken from the items within.

Having the outer regions of the flex container to collapse margin to 0 would be my only curreny use case.

<h1>Big ol heading</h1>
<ul>
  <li>Wow
  <li>So
  <li>Much
  <li>Fun!
</ul>

With CSS:

ul {
  display: flex;
}
li {
  flex: auto;
  min-width: 5rem;
  margin: 2rem;
}
h1 {
  color: blue;
}

Having the control to set how the li aligns it’s margin to the h1 without having to know document structure would be useful here.

So setting minus margin works here: http://codepen.io/anon/pen/pJLJeo

However it then makes an assumption of what the contents of the flex container is.

So perhaps finding a better name for this:

ul {
  display: flex;
  outer-item-margin: 0;
}

Min and Max margins

Flex uses auto margins for laying out spacing between elements, however it doesn’t give fine grain controls for collapsing of margins.

.thing {
  margin: auto;
  min-margin: 2rem;
  max-margin: 20rem;
}

The element will use auto margins unless they are calculated smaller than 2rem or larger than 20rem.

The use case here is something like:

<my-row>
  <my-product>
    <h1>Product name</h1>
    <p>Product desc</p>
    <button>Buy me</button>
  </my-product>
  ...

The style could be something like:

my-product {
  display: flex;
  flex-flow: column;
}
my-product button {
  margin-top: auto;
  margin-top-max: 5rem;
}

So the products would be within a row which lined up vertically, however when a certain products description isn’t even close to matching the others then the button would clamp to 5rem and no further down the product element.

Selectors for a lines flex items

Having fine grained selectors for row and items within them isn’t currently possible.

Layouts where the outer edge elements of flex need a certain layout needs the ability to be selected.

.thing {
  display: flex;
}
.thing .item {
  flex: auto;
  margin-bottom: 20rem;
}
.thing:line-start {
  border-left: 1px solid #333;
}
.thing:line-end {
  border-right: 1px solid #333;
}
.thing:first-line {
  border-top: 1px solid #333;
}
.thing:last-line {
  border-bottom: 1px solid #333;
}

@Shane mentioned the desire to select each line to give an odd and even row style.

line-start selector

Gives the author the ability to style items which are at the first item of every line on the main axis.

Alternative-name: main-start

last-line selector

Gives the author the ability to style items which are at the far most edge of the cross axis.

Alternative-name: cross-end

Snap fit

The last line of a flex sometimes looks messy with it not matching any other column.

.thing:last-line {
  max-width: 300rem;
  snap-fit: 1;
}

Setting a max-width usually makes the layout look worse, however in this case we give it a bounding to match from towards 1 flexible unit. This would try to snap to the items in the previous line, where min and max width would be used to aid the snapping.

If there are two or more items in the last-line the behaviour is the same. Positive space would fill the remaining space.


#2

Collapse of outer margins

Sounds like you want a particular separation between elements, but no gap between the first/last in the line and the flex container? If so, this is already listed in the Flexbox 2 ideas (explicit control over packing space), so you could set it to space-between and then say the space must be at least 2rem.

Min and max margins

Same thing, probably. Using margins and using packing space are basically identical, if you have control over the packing space.

Selectors for a lines flex items

This one runs straight into tricky circularity issues, unfortunately, which sucks, because I’d really like it too. In particular, you can using :line-end to style an element so that it no longer fits on the line at all. Also, this requires layout information, and we don’t let layout loop back into selectors.

Snap fit

Yup, one of the biggest things to address imo, and already in the Flexbox 2 ideas doc as well. I’ve got several possible ideas to address it.


#3

@tabatkins great, I wasn’t aware of that page thank you! As I said to Fantasi, I owe you so many drinks.

Yep, exactly that.

Yep, as you mention method doesn’t matter as long as it is controllable.

Yup, so either:

  • Pack the items in a set order based upon flex-direction and what line-start makes the item grow by, then account for line-end and then another line-start etc (obviously making the packing algo slower and more complex and requiring lots more repaints if dynamic styles are applied - animations just shouldn’t happen)
  • Box size changing properties couldn’t be used with the pseudo selectors, obviously making them not as useful but still easier to style

Very interested. The only solution I could come up with is having the selectors as above and being able to select the last row etc however I have not given it half as much thought as you likely have.

Thanks again


#4

This is a much broader prohibition than you probably realize. In particular, it makes your use-case example impossible, as ‘border’ changes the size of the box.

Also, a simple “can’t use circular properties” prohibition doesn’t work; if you have two such selector/property sets, and the properties differ, you can cause a circularity indirectly (use one selector to set a property that’s legal, but affects the other selector; key off that in another rule to set a property that’s legal for the second selector but would invalidate the first rule). You have to exclude all selector-affecting properties from being used in a rule with any property-affected selectors, which quickly means basically all of CSS is disallowed and the whole thing is worthless. :slight_smile:

snap fit

My current idea is that, after initial sizing but before flexing, you generate “phantom flex items” of the same size as the last item, enough to fill the line, with the same flex parameters as the last item. Do flexing with the phantom items included, then throw them away. You should get a reasonable appearance from that, similar to if you had “just enough” items on the last line to exactly fill it up.


#5

Thank you for writing these out.

As for min/max-margin, I think it’s best to use a different name—like packing-space @tabatkins mentioned—as to not confuse authors. To me it looks like something that is flexbox—and maybe grid layout—specific, because I can’t think of an example for ‘regular’ css layout that could use it; it would just collapse to the min-margin I guess. Only place you could use it is something aligned with margin: auto, but I don’t see any real use cases for that. Please correct me if I’m wrong :slight_smile:

I agree with the other suggestions.


#6

For the collapsing behavior rule thing (last item on the wiki), perhaps something like “height-stops” / “width-stops”, where not having enough space for an item makes it “collapse” to one of the specified heights/widths? So like I could have a “height-stops: 30px 600px”, and if there’s only 595px of space the item ends up with 30px of space (which I then adjust with some kind of JavaScript-toggled class that overrides that rule to expand/collapse the item).


#7

Whoops fell asleep writing this last night:

margin:auto; was the main use-case I was looking at as I was expecting packing space to be harder but a main goal of others.

As mentioned above in column form aligning buttons with margin:auto; some products could have lots of description and others have small descriptions. Aligning the buttons is the ideal situation however products with small descriptions would not benefit from having closer gaps between the description and button.


#8

If you want alignment across rows, that’s what Grid + auto-placement is for.


#9

@tabatkins Please start Flex2 as soon as possible.