flex children of <button> are always vertically centered, despite align-items or justify-content

UNCONFIRMED
Unassigned

Status

()

Core
Layout
P3
normal
UNCONFIRMED
3 months ago
6 days ago

People

(Reporter: Florens Verschelde, Unassigned)

Tracking

Trunk
Points:
---

Firefox Tracking Flags

(firefox57 wontfix)

Details

Attachments

(5 attachments)

(Reporter)

Description

3 months ago
Created attachment 8905515 [details]
button-flex-justify-content.html

Bug 984869 enabled display:flex (and inline-flex) for BUTTON elements.

When using flex layout to arrange the children of the BUTTON element, properties that distribute items on the vertical axis do not behave as expected:

- For flex-direction:row, flex items do not take the full height when using align-items:stretch
- For flex-direction:column, flex items are not distributed over the full height when using justify-content:space-between (or space-around or space-evenly).

This can create issues for authors who expect to lay out the contents of <button> elements the same way they would lay out the contents of a <a> or <span> element.

I’m attaching a test case, expanded from https://bugzilla.mozilla.org/show_bug.cgi?id=984869#c39
(Reporter)

Comment 1

3 months ago
Created attachment 8905516 [details]
Screenshot of test case in Firefox 57
(Reporter)

Comment 2

3 months ago
Created attachment 8905517 [details]
Screenshot of test case in Chrome 60
(Reporter)

Comment 3

3 months ago
Created attachment 8905518 [details]
Screenshot of test case in Safari 10.1
(Reporter)

Comment 4

3 months ago
I’ve added screenshots of results in Firefox, Safari and Chrome.
Chrome seems to be the most flexible, Safari has the most issues, and Firefox is somewhere in between.
Yeah, I think what happens here is that we wrap the <button> contents in a helper box (which does *not* inherit width/height), and we manually center that box within the button.  Chrome clearly does something similar, on the first line of your testcase (the top two pinkish examples).

In Firefox, that button-internal layout happens here:
https://dxr.mozilla.org/mozilla-central/rev/93dd2e456c0ecca00fb4d28744e88078a77deaf7/layout/forms/nsHTMLButtonControlFrame.cpp#258-292

(I guess we do the centering differently for inline (horizontal) vs. block (vertical) axis, based on your oboservations -- though I don't remember precisely how/where.)

Unfortunately, the internal rendering/positioning of button contents is pretty underspecified, which is why this is so unpredictable & different between browsers.

If you want this to work reliably & work cross-browser, your best bet is to use an *explicit* wrapper div for the button's contents, with "height: 100%; width: 100%", and give that wrapper-div 100% height and width so that it explicitly fills the whole button.  I'll attach a testcase demonstrating that tweak.
Created attachment 8905599 [details]
testcase variant, using explicit wrapper div (which produces expected results)
(In reply to Daniel Holbert [:dholbert] from comment #5)
> (I guess we do the centering differently for inline (horizontal) vs. block
> (vertical) axis, based on your oboservations -- though I don't remember
> precisely how/where.)

Ah -- following up on this: we center the text horizontally in buttons via "text-align: center", here:
 https://dxr.mozilla.org/mozilla-central/rev/93dd2e456c0ecca00fb4d28744e88078a77deaf7/layout/style/res/forms.css#645,653

So the implicit wrapper box is, by default:
 - the full width of the button's content box (though it has text-align:center so its text contents still look centered)
 - only as tall as its contents (and vertically centered manually, via some C++ code rather than via CSS)
...because traditionally CSS had no way to reliably do vertical centering of arbitrary content.

Comment 8

3 months ago
When CSS Align is implemented, I think buttons should be styled with "align-content: safe center", and get rid of the magic wrapper.
(In reply to Oriol Brufau [:Oriol] from comment #8)
> When CSS Align is implemented...

...for blocks (this is bug 1105571).

> ...I think buttons should be styled with
> "align-content: safe center", and get rid of the magic wrapper.

I think something like that could work, yes.  We'd still have the magic wrapper under the hood, but we could style it with "display:block; height:100%; align-content:center", which I think would center its contents vertically within it.  Or maybe we'd really want to give the *button* "align-content:center" and give the wrapper "align-content:inherit", so that authors could override the centering... That would be web-observable change, though (since authors can inspect the default style of buttons and could conceivably depend on it somehow), so this would involve some risk of breakage.

Updated

3 months ago
Priority: -- → P3

Updated

2 months ago
status-firefox57: --- → wontfix
You need to log in before you can comment on or make changes to this bug.