whatwg / html

HTML Standard
https://html.spec.whatwg.org/multipage/
Other
8.18k stars 2.71k forks source link

"being rendered" interaction with display:contents #1837

Open zcorpan opened 8 years ago

zcorpan commented 8 years ago

display:contents

The element itself does not generate any boxes, but its children and pseudo-elements still generate boxes as normal. For the purposes of box generation and layout, the element must be treated as if it had been replaced with its children and pseudo-elements in the document tree.

https://drafts.csswg.org/css-display/#valdef-display-contents

"being rendered"

An element is being rendered if it has any associated CSS layout boxes, SVG layout boxes, or some equivalent in other styling languages.

https://html.spec.whatwg.org/multipage/rendering.html#being-rendered

So an element that is display:contents is not "being rendered". Check the uses of "being rendered" if that makes sense.

Related: https://github.com/w3c/csswg-drafts/issues/540

zcorpan commented 7 years ago

https://github.com/w3c/csswg-drafts/issues/540 is now resolved as follows: https://drafts.csswg.org/css-display/#unbox

lilles commented 6 years ago

Stumbled into this one for innerText. There's a wpt relying on "being rendered" being true for display:contents. innerText is spec'ed to return textContent for elements not being rendered.

Gecko considers display:contents to be rendered for textContent. Another reference to "being rendered" in the HTML spec where this matters is https://html.spec.whatwg.org/multipage/browsing-the-web.html#scroll-to-fragid:being-rendered

For that case, Gecko does not scroll to a display:contents fragment.

@emilio do you know how consciously this is done in Gecko?

emilio commented 6 years ago

Oh, I somehow missed that mention... But the answer is "Gecko's innerText impl was a bit bogus", see https://github.com/web-platform-tests/wpt/issues/12580.

SelenIT commented 5 years ago

In the CSSWG issue linked above (2362), it turned out that treating elements with display:contents as "not being rendered" conflicts with the general rule and intent that CSS display other than none shouldn't affect the semantics and interactivity of the element. Specifically, it turns off the focusability of the otherwise focusable element (at least, removes it from the tab focus sequence).

I believe that treating an interactive element that has visible subtree and can be activated through it as "not being rendered" is confusing and counter-intuitive. Wouldn't it be better to revisit this definition (or change the focusability criteria from "element has associated CSS boxes" to something like "element or its subtree has any visible/interactive parts")?

domenic commented 5 years ago

Revising the focusability criteria seems reasonable to me, but I'd like to to be as well-defined as possible. Moving from "has CSS boxes" to "has any visible/interactible parts" seems like a step down in rigor.

domenic commented 5 years ago

It's also possible that this problem occurs more than just for focus, in which case the better revision may be to change the definition of "being rendered".

SelenIT commented 5 years ago

I found the usage of the "box tree" term in the spec (in the section about Focusable areas). Maybe it can be reused for "being rendered", like the following?

An element is being rendered if any of the element itself, its descendant nodes, or pseudo-elements associated with the element itself or its descendant nodes, generate a box or text run in the box tree.

emilio commented 5 years ago

Revising the focusability criteria seems reasonable to me, but I'd like to to be as well-defined as possible. Moving from "has CSS boxes" to "has any visible/interactible parts" seems like a step down in rigor.

Yeah, that is true. Also, it seems a bit weird to define that an element with display: contents is focusable, fwiw. While I get the sentiment, per definition elements with display: contents generate no boxes, which means that they generate no overflow, no background, no outlines...

I wouldn't know how to implement a "focusable display: contents element", except hacking up the whole layout engine to display some kind of outline on descendants that contributed to some overflow area? Which overflow area should that contribute to, I don't know... Descendants of display: contents elements can be all over the layout tree.

domenic commented 5 years ago

Although at first glance I am sympathetic, it seems that debate has already been had at https://github.com/w3c/csswg-drafts/issues/2632, and the conclusion is that they should be focusable, even if you don't draw any outline around them.

In other words, break it down into observable consequences:

annevk commented 5 years ago

Does https://github.com/w3c/csswg-drafts/issues/2632#issuecomment-495360508 match implementations though? If browsers use the box tree and there's no box tree, many of these things will be affected unless they are somehow specifically catered for (likely by creating some special box), so I'm not sure the conclusion there is fully accurate.

SelenIT commented 5 years ago

The exact problem is that there is a box tree in case of display:contents (totally unlike the display:none case!). It only misses just one box (the box for element itself), but all other boxes in it remain fully visible and interactive (they can be clicked and this activates the element through event bubbling). However, the definition of "being rendered" and related concept of focusability are currently tied to this one box, not the presense/visibility of the box tree, and this discrepancy currently leads to behavior which is counterintuitive for both authors and users. So maybe there are better options for this case than to tie focusability etc. to that one box?

SelenIT commented 5 years ago

CSSWG now has a resolution that, for accessibility reasons, display:contents elements need an outline rendered around their displayed contents when focused:

RESOLVED: Outline of 'display: contents' is propagated to children for painting (for a11y on focus);

IMO, this clearly implies that display:contents elements must be focusable, and thus should be considered rendered.

Maybe the it would be sufficient to update the definition of "being rendered" like the following?

An element is being rendered if it or its content has any associated CSS layout boxes, SVG layout boxes, or some equivalent in other styling languages.

domenic commented 5 years ago

What is "content"?

SelenIT commented 5 years ago

I tried to find something short for something like "any of the element's inclusive descendants or their CSS generated content pseudo-elements". I agree that it was too vague for the definition.

ExE-Boss commented 5 years ago

"being rendered"

An element is being rendered if it has any associated CSS layout boxes, SVG layout boxes, or some equivalent in other styling languages.

To me, that seems to imply that display: contents shouldn’t affect it as descendant items still generate layout boxes as normal.

SelenIT commented 5 years ago

It seems that the term "a box associated with the element" is quite ambiguous and still needs some clarification. On the one hand, it can be read as a broader synonym for "a box generated by the element" (that sounds more natural for CSS devs), but applicable to SVG and (largely hypothetical) "other styling languages".

On the other hand, the CSS Display Level 3 actually does use the term associated, but it's not defined normatively, and seems to mean different things in different contexts. E.g. in the phrase

An anonymous box is a box that is not associated with any element

it seems to mean more-or-less the same as "generated by" (otherwise, we would say that an anonymous box is "associated" with the parent element which would generate more than one box in this case). However, later in the Glossary section we have the following definition (emphasis mine):

containing block A rectangle that forms the basis of sizing and positioning for the boxes associated with it (usually the children of the box that generated it)

which seems to imply that many boxes can be associated with one particular aspect of the element, and the box subtree of the element can be considered somehow associated with the parent element (at least, in some circumstances).

tabatkins commented 5 years ago

"associated" isn't a term of art in that spec, it has its regular English meaning.

(Sorry for the drive-by correction; I'm happy to help provide wording guidance here, but I'm not sure exactly which definition y'all wanna fix.)

SelenIT commented 5 years ago

My idea was to update the "being rendered" definition to treat any element with the non-empty box tree as rendered. This way only elements with display:none (in the CSS terms) would be considered non-rendered, and there will be no "non-rendered elements that the user still can see and interact with" that confuse authors.

rniwa commented 5 years ago

Sounds like we need a more precise definition of associating a CSS box with an element in CSS?

any element with the non-empty box

That still sounds ambiguous. What does it mean for an element to be with a non-empty box tree?

SelenIT commented 5 years ago

It seems that the HTML spec definition tries to be more general, considering SVG boxes and "some equivalent in other styling languages" along with CSS boxes, so updating the CSS definition would probably be not enough. Changing the HTML definition seems more reliable to me.

My suggestion was to replace the word "element" in the current definition of "being rendered" with a new term/phrase that would include

i.e. anything that is somehow displayed to the user and for what the element in question is an ancestor. With this change, the definition should become unambiguous regardless the exact interpretation of the "box/element association".

annevk commented 5 years ago

I don't think HTML's definition needs to be more general and CSS already needs to deal with SVG one way or another. We should strive to simplify that setup, not make it appear more grand than it really is.

SelenIT commented 5 years ago

If it's possible to use CSS as direct reference in the "being rendered" definition, maybe it can be defined like "An element is being rendered if its CSS display is other than none"?

emilio commented 5 years ago

That doesn't work for descendants of display: none elements.

SelenIT commented 5 years ago

Valid point. Then maybe something like

An element is being rendered if any of its shadow-including inclusive descendants or their CSS pseudo-elements has associated CSS layout boxes, SVG layout boxes, or some equivalent in other styling languages

would work?

SelenIT commented 3 years ago

Are there any objections to redefining "being rendered" as following?

An element is being rendered if any of its shadow-including inclusive descendants or their CSS pseudo-elements has associated CSS layout boxes, SVG layout boxes, or some equivalent in other styling languages

dbaron commented 2 years ago

I made a quick attempt to fix Chromium bug 1366037 which relates to focusability of display:contents elements..

It turned out that display:contents elements not being focusable was being tested in 3 places in Chromium's test suite. The one that was in WPT was specifically testing display: contents, but the other two (not in WPT) were testing that the <slot> element is not focusable.

I'm curious if folks here think that a <slot> element becoming focusable is an expected consequence of display: contents elements being focusable, or if <slot> should be unfocusable through some other mechanism.

lilles commented 2 years ago

As a consequence of being display:contents. That is, I would expect tab to focus the slot for:

<!doctype html>
<div id="host"></div>
<script>
  let root = host.attachShadow({mode:"open"});
  root.innerHTML = `
    <style>
      slot {
        display: block;
        width: 100px;
        height: 100px;
        background: red;
      }
      slot:focus {
        background: green;
      }
    </style>
    <slot tabindex="1"></slot>
  `;
</script>

That works in both Safari and Firefox, but not in Chrome. Without checking any specs, I'd say that's a Chrome bug.

dbaron commented 1 year ago

It's worth noting that w3c/csswg-drafts#2632 concluded that elements with display: contents should be focusable, which contradicts the above. (Note that in Chrome, the bug is specifically about being tabbable, and not more generally about being focusable.)