w3c / csswg-drafts

CSS Working Group Editor Drafts
https://drafts.csswg.org/
Other
4.45k stars 657 forks source link

[css-contain-2] Proposal: content-visibility: hidden-matchable #5595

Closed josepharhar closed 3 years ago

josepharhar commented 3 years ago

I would like to propose a new value for the content-visibility CSS property: hidden-matchable.

content-visibility: hidden-matchable would function the same as content-visibility: hidden but also allow the browser to search for text inside the hidden content during find-in-page and ScrollToTextFragment. When used in conjunction with the proposed beforematch event, this would enable pages to reveal text in response to find-in-page before the browser scrolls and therefore make hidden sections which are searchable.

An example usage of this feature would be to search the content of hidden, collapsed sections of mobile wikipedia, which are not currently searchable.

Non-hidden content is already searchable and so no event or CSS property is needed to expose it to user agent algorithms.

This is related to #3460, but is concerned with making hidden text searchable, rather than making visible text non-searchable.

Why content-visibility and not other “hidden content” mechanisms like display: none or visibility: hidden?

Hidden content is usually put in display:none subtrees on sites today (for example, this is what mobile wikipedia does), to avoid rendering costs associated with the hidden content. However, display: none content cannot actually be searched properly, because searching depends on certain features of styling to determine critical features such as word breaks, and display: none elements do not have CSS boxes. visibility: hidden has several performance problems, such as being overridable in subtrees and not allowing the browser to avoid rendering work when hidden.

The current values of content-visibility are in the css-contain-2 spec.

Sketch of edits to spec

'hidden-matchable': This value behaves very similarly to 'hidden'. That is, the element skips its contents. The skipped contents must not be accessible to user-agent features such as tab-order navigation, nor be selectable or focusable. However, unlike 'hidden', the skipped contents must be accessible to the find-in-page algorithm in order to allow the beforematch event to fire.

hftf commented 3 years ago

Disclaimer: I have read this issue, TAG review #511, the explainer, and various linked documents, at least twice. I am in favor of the idea and thank those who have worked on it so far. I am an author, not an expert, and I hope my contribution will be useful. Please correct me if I’m wrong about anything!


The question below does not seem to have been directly discussed much yet:

Is it the correct decision to integrate this feature with content-visibility?

I am concerned that extending the content-visibility property with the value hidden-matchable conflates two concepts at once: visibility and searchability.

Searchability is the desired primitive

The new primitive most relevant to this proposal is the concept of searchability (or findability, matchability, etc.). Searchability could be thought of as a new general property of any element. Even some non-elements with visible text could theoretically be made searchable, such as CSS generated content or tooltips using the HTML title attribute.

In #3460, I make a case for essentially the inverse of this proposal. As the OP summarized, this issue (#5595) is about making hidden text searchable, while #3460 is about making visible text non-searchable. Note that visibility is not relevant to #3460.

An isolated design for #5595 that does not take into account #3460 could undesirably result in two very different, confusing solutions for handling the same single primitive: searchability.

Searchability belongs in CSS

It seems hard to determine whether user interaction abilities belong exclusively in the semantic/markup layer or in the style/presentational/visual layer. But for the purposes of this proposal, it is mostly thanks to CSS that the visibility of content (semantic markup elements) is controlled at all.

Imagine a Wikipedia article with a section containing a paragraph. By default (HTML only, no CSS), the paragraph would be visible and searchable. To better fit the experience on mobile devices, the authors then chose to add CSS and Javascript to change the particular “presentation” of the page, letting sections collapse. It does not seem consistent for the visibility of the paragraph to be disabled via the style layer, but the searchability of the paragraph to be re-enabled via the markup layer.

That being said, the key idea behind searchability is whether or not certain content is conceptually thought of as being part of the same document. (Hidden content may or may not be conceptually part of the document, just as visible content may or may not be conceptually part of the document.) This important point is acknowledged in the OP (emphasis mine):

hidden-matchable: Content is not technically shown to the user visually (and as a result the UA need not spend time rendering it by default), but is conceptually part of the current view and is only not shown because it's inside of a UX pattern such as an accordion or their off-screen portions of a userland infinite list.

If for over 20 years, authors had not already been mainly using CSS to declare whether markup is visible or not – and, as a result, to usually make a verdict on its meaningness (its conceptual relevance) – then it might make more sense to use the markup layer to notate whether an element is “conceptually part of the document.” (Remember that CSS visibility notably affects the accessibility tree too.)

Is there an argument for this being in content-visibility?

I am trying to understand the reason why this feature belongs in the scope of content-visibility. Is it because optimization is most important? (i.e. the feature will only be applied to the few elements specifically marked as relevant to it via content-visibility: hidden-matchable, and tying it to visibility means that authors necessarily cannot misuse it, such as by applying a broad rule like * { user-search: searchable; } that defeats the purpose of the optimization)

Scanning an element for two style conditions – the hypothetical user-search: searchable and display: none – should not involve much more computation than the method implied by the current proposal, which scans for one condition.

Some use cases

As noted, the <details> element only makes sense for some use cases. Semantically, “the <details> element represents a disclosure widget from which the user can obtain additional information or controls.” In other words, hiddenness is a property that can apply to any element (thanks to CSS and Javascript) and is not in 1-to-1 correspondence with <details>’ semantics.

Below are some scenarios in which hidden content can be considered to be conceptually part of the same document.

chrishtr commented 3 years ago

How is the new value for hidden content attribute supposed to work with hidden idl attribute which is defined to be boolean https://html.spec.whatwg.org/#htmlelement?

My understanding is that due to technicalities of how boolean attributes are implemented in the platform, it is possible to extend to a non-boolean syntax without a lot of web compat problems. If that turns out not to be the case then a new attribute can be chosen...

I think the idea may have come up after the meeting concluded and so is not in the notes. @tantek @fantasai do you remember the details of the argument why it could be possible to extend hidden?

chrishtr commented 3 years ago

Searchability belongs in CSS

Responding to this particular point: I do now thing that searchability belongs in HTML. Until yesterday I couldn't see a good reason to put it in HTML, but now I do see a reason. It's that searchability is about informing UA-implemented semantic features, and by the design of CSS the UA cannot "override" CSS in some way to indicate its desire to search - there is no place in the cascade to define that. So if the feature was in CSS, then there would have to be an event sent to script to ask it to reveal the content.

Stated in a more practical way: if it's an attribute, the UA can then modify that attribute to signal to the page it wants to display the searched-for element to the user, and the page can respond by changing visual display via a CSS attribute selector. (And the page will also fire an event for situations that are beyond the abilities of CSS to express.)

astearns commented 3 years ago

I think the idea may have come up after the meeting concluded and so is not in the notes. @tantek @fantasai do you remember the details of the argument why it could be possible to extend hidden?

Was it this? https://www.w3.org/2021/02/09-css-irc#T21-44-14

chrishtr commented 3 years ago

Was it this? https://www.w3.org/2021/02/09-css-irc#T21-44-14

Yes! thanks. Inlined quote:

21:24:33 [tantek]
fantasai brought up the 'hidden' attribute and how it was created maybe too late compared to display:none to be properly designed together, and this made me wonder if there was more we could have done there, or can do there now
21:26:18 [tantek]
since 'hidden' is a boolean attribute, adding new values that work like the existing default but with some additional functionality is potentially backcompat
21:26:40 [tantek]
e.g. (just off the top of my head) hidden='findable' would have the right backcompat fallback behavior
smaug---- commented 3 years ago

Sure, backwards compat is fine with hidden attribute approach, but doesn't it make the API a bit awkward to use when after search has been done, the page must use setAttribute and not .hidden = true; to hide the element again to keep the text searchable? Perhaps there could be some additional idl attribute or method to deal with this?

FremyCompany commented 3 years ago

I guess that's something to be discussed in the whatwg given we're now discussing dom and attribute names but another name is also an option, we came up with a new value for hidden during a 40 minutes call and it's obviously possible to refine given constraints.

Nothing says that the whatwg folks cannot change the idl of hidden so that you can do element.hidden="until-found" in JS. But if not hidden-until-found can be it's own attribute or maybe there's another alternative.

josepharhar commented 3 years ago

I am now proposing this feature to be an attribute instead of a CSS property in whatwg/html: https://github.com/whatwg/html/issues/6040#issuecomment-785991421