https://twitter.com/ned/status/1051798190951940096
button { display: inline; } should work.
Yes, I want to make buttons that wrap lines like a normal inline elements, but retain the semantics and accessibility of a button.
that's the point: it should be able to just flow its contents, it's crucial for action items inserted in text as pseudolinks. For now we have to hack around with
<span role=button tabindex=0 onkeydown=handleEnterOrSpace(event) onclick=handleClick(event)>
or just use<a href=#>
https://twitter.com/micahgodbolt/status/1047218367432544257
So, what if you have some long text in a paragraph where on click, it performs an action (not an href)
You'd use a
<button>
right?Okay, then how would you make that button LOOK like text in a paragraph.
https://www.scottohara.me/blog/2018/10/03/unbutton-buttons.html
This post discusses the problem, and explores styling buttons with display: contents
but notes that it loses the ability to receive keyboard focus and there's no accessibility node so it's not exposed as a button to screen readers.
In https://github.com/whatwg/html/issues/4081 I'm working on specifying the layout model that buttons use. Currently my working draft for this is part of https://docs.google.com/document/d/1FE5YIoirPKxYbbnMd8kS6w39M8bzLTl5tf4wwOxR1wc/edit?usp=sharing
In particular, buttons have an inner anonymous box that is a block formatting context, and I think this is the cause of the inability to make buttons be inline.
One way to solve this could be to add a pseudo-element to target the anonymous box, so that web developers can set it to 'display: inilne'. The button would still be focusable and be exposed the same in the accessibility tree.
Thoughts?
cc @tkent-google @MatsPalmgren @hober @FremyCompany
I don't think you can explain all the <button>
magic just by adding an inner box.
For example, height
doesn't apply to non-replaced inlines, but a <button>
obeys height
even with display: inline
. Also, the ::part(button-contents) { display: flow-root }
which you include in the default UA stylesheet would split a non-replaced inline <button>
.
So it seems <button>
always needs to be replaced, not just "if the element is absolutely positioned" or "For the purpose of the ‘normal’ keyword of the ‘align-self’ property".
It indeed needs to act as a replaced element for some purposes by default. But we could disable the replaced element-ness if the inner box is not block-level, or some such.
Basically like this, as author CSS to unstyle a button:
button { appearance: none; display: inline; font: inherit; background: initial; border: initial; padding: initial }
button::part(button-contents) { display: inline }
I don't like that the kind of box that is generated depends on the display
value of the children, because the computed display
value of the children depends on the formatting context in which they participate.
IMO a better way to approach this would be adding a new CSS property which can force an element to establish an independent formatting context (or behave like an inline-block if it's a non-replaced inline). Enable this on buttons via UA stylesheet, but let authors revert it to normal behavior.
Good point, and good idea. If that property is used to turn off the independent formatting context, it would also turn off the element acting like a replaced element? And the inner box would inherit that property?
I don't think I understand the reasoning for not just specifying appearance: none
on <button>
as simply removing the layout "magic" and turning off the replaced element behavior? Affording a computed inline
value on display
? Or is it just too late to do this? https://github.com/w3c/csswg-drafts/issues/3024
I doubt that would be web compatible.
What if the appearance: none
alone would preserve the default display: inline-block
behavior of the button (making it behave _similarly_ to how replaced elements behave, but _without any magic_), and changing its display
to inline
would convert it to the regular non-atomic inline box? Maybe _this_ could be web compatible? Are there many web pages that use _both_ appearance: none
_and_ display: inline
for buttons while relying on their "replaced-element-like" behavior?
However, having the pseudo element that wraps all the content of the button could be useful for solving #2632 — it could get the default focus outline (similarly to that of the inline a
element) even when the button
element doesn't generate its own box.
Good point, and good idea. If that property is used to turn off the independent formatting context, it would also turn off the element acting like a replaced element?
Well, I didn't think much about the differences between a normal inline-block and a replaced one, I'm not an expert in this. I don't think the property should allow to convert arbitrary elements to replaced, just create an independent formatting context, but maybe handle this case specially for buttons. Then yes, setting it to the initial value in buttons could make them normal inlines.
And the inner box would inherit that property?
I don't really see how the inner box helps explaining the behavior of buttons. It can be useful for some unrelated purposes, but then I prefer my ::contents
proposal (#2406).
Are there many web pages that use both
appearance: none
anddisplay: inline
for buttons while relying on their "replaced-element-like" behavior?
I don't know but I have seen "CSS reset" stylesheets which use something like
* { display: inline }
section, main, div /*...*/ { display: block }
It's possible that they forgot button { display: inline-block }
and relied on this behavior anyways.
Using both appearance: none
and display: inline
might work from an implementation POV, assuming that we define all buttons to have display: inline-block
in the UA sheet. (Currently, Gecko only has that on <button>
but not on <input type=button>
etc. Chrome has it on all buttons AFAICT, so it should be OK to change it in Gecko.) I'm a bit worried about changing the meaning of that combination of values though. We probably need to add a counter to see how common that is first.
Here are rules and their counts in httparchive that set *-appearance: none and display: inline
https://gist.github.com/zcorpan/4fea68aad8265cfa45d83f80586c9cf8
The sum of the nums is 2361. The data set is 1.3M pages. There could be multiple matches for a single page. Not all of these are buttons, and maybe some of these want to really unstyle their buttons.
There could possibly be some buttons with display: inline
implicitly set via all: initial
/unset
, but I suppose that it would be safe now to imply that authors who use this do want to remove _all_ the rendering "magic" from the buttons, including "magic inline-block-ness".
To clarify, an explicit appearance: none would be needed, not just implicit by setting a border or a background color, right?
I believe so. Honestly, in my opinion, what happens to the button when its default background is changed is "simplifying" its appearance rather than "undoing" it: the button loses the default OS-themed style, but (at least in Windows Chrome) it still has "pseudo 3d"-style border and it appears "pressed down" when activated.
Yeah but appearance: none does the same (setting border or background implicitly sets appearance: none).
See https://github.com/whatwg/html/commit/c1e1f6f9e7d83af5affca071775a98f4b6abc29d for a proposal for this.
appearance: none does the same
Thanks, I didn't realize this before! Then, it seems that the real meaning of display: none
is "remove OS/browser-specific _theming_" rather than "remove the element's _specific behavior_". If so, it seems that my idea to use display
as an extra switch was not very good. Maybe it would be better to leave appearance: none
as is and introduce a new value (e.g. appearance: plain
) with the latter meaning, with no extra dependency on other properties?
Discussion on twitter here
https://twitter.com/benoitrouleau/status/1088883974296997890?s=20
Made me think that maybe display: inline isn't a good hook for this. It's good if you want an inline, but what about if you want a without-magic block/grid/other?
Maybe a new property is better, that is set by the UA stylesheet so that all: unset removes the magic.
I’d much rather have display: inline;
act like a normal inline element and the current behaviour use display: inline-block;
@zcorpan Might I suggest changing the title of this issue to "Allow making
@benface, the display:inline
case for buttons is a bit special: it's a "final frontier" that is yet not achievable by CSS in any implementation. Implementers seem to have agreed that the ability to style buttons as flex or grid container is necessary, and at least Firefox has already implemented it somehow. But making a button display as a regular non-replaced non-atomic inline element is currently not achievable anywhere. That's why it was initially stressed in the title.
@zcorpan, when I proposed display:inline
as a hook for removing "magic" replaced-like behavior, I didn't realize that explicit and implicit change of appearance
are equivalent, I assumed that explicit change has deeper effect. Sorry, it was my error. Now I believe that there probably should be two different values of appearance
– the good old none
to remove the platform-specific _default theming_ (borders, background, focus/hover highlighting etc.) while still preserving the "magic replaced-like" rendering behavior, and a new one to remove that "magic" altogether.
@SelenIT Ah, I understand. I was more referring to the outer display though, e.g. make a <button style="display: block;">
expand to its container's width like a <div style="display: block;">
would.
I have another use case, but I'm not sure if it fits under the umbrella of this issue or whether it should be filed elsewhere?
By default, the contents of a button
are vertically centred. I want to disable this, so that their behaviour matches all other (non-button
) elements.
(If we want developers to use button
s for the best semantics/a11y, we must have ways to fully reset their styles.)
@OliverJAsh, interestingly, different browsers seem to have different bits of control over this "magic". Chrome/Mac changes the vertical position of the button contents if I add flex-direction: column
to the button styles (even without display: flex
!), Firefox/Mac seems more logical and changes the position if I apply display: flex
/grid
to the button (but not block
/flow-root
, unfortunately).
@SelenIT In Firefox, if you use display: flex
on a button, it will obey align-content
and align-items
. I think the idea is that buttons with display: block
should also obey them, but alignment properties are not supported on blocks yet (https://bugzil.la/1105571)
That button
is implemented in terms of Flexbox by default in Chromium is considered a bug per https://github.com/whatwg/html/issues/4081#issuecomment-429989272
The magic defined in https://github.com/whatwg/html/pull/4143 is more likely to match what we end up doing I think, but it's this issue is still an open issue, i.e. how to disable the magic.
Maybe it would make sense to define the default vertical centering of the _anonymous button content box_ in terms of align-content
for the "main" button box (it would be safe center
, I guess?), so once browsers implement content distribution properties for block containers, this becomes part of the general rule rather than a "magical" exception?
Most helpful comment
Discussion on twitter here
https://twitter.com/benoitrouleau/status/1088883974296997890?s=20
Made me think that maybe display: inline isn't a good hook for this. It's good if you want an inline, but what about if you want a without-magic block/grid/other?
Maybe a new property is better, that is set by the UA stylesheet so that all: unset removes the magic.