flexbugs icon indicating copy to clipboard operation
flexbugs copied to clipboard

Multi-line flex containers do not respect align-content when there is only a single line of items

Open BobVul opened this issue 8 years ago • 4 comments

The issue

First, the spec defines the single/multi-linedness of a flex container based purely on the value of flex-wrap, not on whether wrapping is currently occurring: https://www.w3.org/TR/css-flexbox-1/#single-line

align-content has no effect on a single-line container: https://www.w3.org/TR/css-flexbox-1/#propdef-align-content

Browsers

Currently, Firefox 46, Chrome 50 and IE 11 follow an older definition based on the actual number of rendered lines. This is both incorrect according to the current spec, and not intuitive as described in the change request: https://lists.w3.org/Archives/Public/www-style/2014Oct/0489.html

Edge (12, 13) and Safari 9.1 appear to work correctly, but the workaround does no harm there.

Bug reports

Firefox bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1090031 Chromium bug: https://bugs.chromium.org/p/chromium/issues/detail?id=599828

Test case and workaround

Here's a test case, with a workaround: http://codepen.io/Bob_Vul/pen/RaXKeq

You'll see that if you add enough children to cause an overflow, the align-content property is respected and the items no longer stretch to fill the container, only their current row (i.e. stretch to the biggest in the row).

The workaround just adds an otherwise-invisible full-width item to the first row, so the first visible row is actually the second wrapped row. Since wrapping is always occurring in this case, the flex container is always treated as multi-line even under the old spec.

This is for a row-orientation flexbox:

.flex-wrap-fix {
  width: 100%;
  height: 0px;
  padding: 0;
  margin: 0;
  border: none;
}

Those with accessibility concerns should set aria-hidden="true" and role="presentation" as appropriate.

I don't know of any side-effects of this workaround.

BobVul avatar May 23 '16 02:05 BobVul

Interesting, I wasn't aware of this change.

I think it makes sense to document this workaround. I've used similar "invisible children" techniques in the past* and haven't noticed any negative side effect, so I don't see a problem with it.

  • (e.g. this flex-grid component that prevents children on the last line from expanding all the way)

philipwalton avatar May 28 '16 00:05 philipwalton

Fixed in Firefox (shipped in FF 52) but Safari Technology Preview v34 now follows Chrome's incorrect rendering.

Example: Blink and Webkit apply the default align-content: stretch instead of align-content: start.

Safari 10.1: safari-10-1

Firefox 54: firefox 54

Safari Technology Preview 34: safari-tp-34

cristianl avatar Jul 01 '17 15:07 cristianl

The bug still exist in both Chrome (tested in v.65/Windows) and Safari (tested in iOS 11.2). The Chrome bug referenced above is reopened since Oct. 2016. Unfortunately, I couldn’t find the bug reported for WebKit.

Adding an extra zero-height flex item with 100% width is also only workaround for this issue I could come up with. It can be the ::after pseudo-element of the flex container instead of extra element (as suggested above): example of the bug and workaround.

Issue #187 is another example of the same difference in behavior: Chrome just ignores align-content for a single flex line despite flex-wrap: wrap, and stretches this line to the whole container height.

I believe this issue is worth listing as a Flexbug!

SelenIT avatar Mar 19 '18 23:03 SelenIT

In My Test Case,Chrome And FireFox work correctly, Safari work incorrectly,My solution is set align-content and align-item with same value。This method works in my example。 Chrome: 78 Safari: 12.1

MrErHu avatar Dec 09 '19 13:12 MrErHu