Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
josepharhar opened this issue Oct 8, 2020 · 58 comments
Closed

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

josepharhar opened this issue Oct 8, 2020 · 58 comments
Labels
css-contain-2 Current Work HTML Requires coordination with HTML people

Comments

@josepharhar
Copy link
Contributor

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.

@vmpstr
Copy link
Member

vmpstr commented Oct 19, 2020

The only concern I have with this is that content-visibility: hidden puts in things like containment which on the surface doesn't seem like it's needed for hidden-matchable type of behavior.

Also, the proposal says that visibility: hidden has performance problems such as not skipping layout work, but again that doesn't seem like it is a requirement for having hidden searchable content.

To be clear, I think this should absolutely work with content-visibility: hidden, but I'd just like to point out that making it also work with visibility: hidden might be nice.

@vmpstr
Copy link
Member

vmpstr commented Oct 20, 2020

Accidentally didn't log the discussion, so here it is for posterity:

irc log
 fantasai> jarhar: Hi I'm Joey. I'm working on content-visibility: hiddne-matchable
 fantasai> jarhar: in parallel with HTML feature called ??
 fantasai> jarhar: A lot of websites have sections, like wikipedia
 heycam> s/??/beforematch/
 fantasai> jarhar: and find-in-page doesn't work because it's 'display: none'
 fantasai> jarhar: When searching for these things, want these things to be findable
 fantasai> jarhar: so you would send 'content-visiblity: hidden-matchable' which is same as 'content-visibility: hidden'
 * fantasai q+
 * Zakim sees myles, fantasai on the speaker queue
 fantasai> jarhar: that'll find the element and fire ??
 fantasai> jarhar: and page has ability to change the style to reveal the content
 cbiesinger> s/??/the beforematch event/
 fantasai> jarhar: and after one RequestAnimationFrame
 fantasai> jarhar: browser will scroll to it
 florian> s/??/before match/
 fantasai> jarhar: and that's pretty much thie ideal
 emilio> q+
 * Zakim sees myles, fantasai, emilio on the speaker queue
 fremy> this is a wonderful proposal
  q-
 * Zakim sees fantasai, emilio on the speaker queue
 fantasai> s/thie ideal/the idea/
 astearns> ack fantasai
 * Zakim sees emilio on the speaker queue
 florian> fantasai: I'm curious, in a lot of cases, it seems it should just work
 florian> fantasai: in the case of a details element, it should just pop open
 florian> fantasai: I'm a little confused as to why we wouldn't want this to happen as well
 fantasai> jarhar: Agree supporting content in details element
 fantasai> jarhar: but separate from CSS property
 fantasai> jarhar: for DETAILS could just say browser can change the state of DETAILS automatically
 fantasai> jarhar: but other case don't use DETAILS element, those use display: none
 fantasai> jarhar: so providing a different way
 smfr> q+
 * Zakim sees emilio, smfr on the speaker queue
 fantasai> jarhar: also CSS state is maintained by page, page has opportunity to change itself
  jarhar: 2nd question?
 TabAtkins> q+
 * Zakim sees emilio, smfr, TabAtkins on the speaker queue
 bkardell_> q+
 * Zakim sees emilio, smfr, TabAtkins, bkardell_ on the speaker queue
 fantasai> fantasai: why wouldn't this be the default behavior for 'content-visbility: hidden'
 fantasai> jarhar: could maybe, but some concern around privacy mitigations
 fantasai> jarhar: if we fired on hidden content
 fantasai> jarhar: page, after it gets an event, the page is required to reveal the content or else we lock the page out of using beforematch
 fantasai> jarhar: we want to prevent the page from trying to figure out what the user is searching for
 fantasai> jarhar: and hidden-beforematch is what we're using to determine state
 bkardell_> actually I will just say most of the time that is probably not actually what you want and if you need me to clarify why I can readd to the queue
 fantasai> jarhar: a lot of pages using 'content-visilibity: hidden' already, and would create lockout, so not great
 bkardell_> q--
 * Zakim sees emilio, smfr, TabAtkins, bkardell_ on the speaker queue
 fantasai> jarhar: so that's why
 astearns> ack emilio
 * Zakim sees smfr, TabAtkins, bkardell_ on the speaker queue
 bkardell_> q-
 * Zakim sees smfr, TabAtkins on the speaker queue
 fantasai> emilio: Find-in-page already changes the selection of the document, and that's observable now
 fantasai> emilio: so how useful is this mitigation
 fantasai> jarhar: There are other ways to observe find-in-page
 TabAtkins> So the answer to "why not give 'hidden' this behavior, and then add another value that has the current unmatchable behavior" is "there's already some legacy content that we'd prefer not to break if not necessary"
 fantasai> jarhar: e.g. by listening to scroll events
 * dholbert has quit (Ping timeout: 180 seconds)
 fantasai> jarhar: in Firefox as you type it fires selection events
 fantasai> jarhar: makes it easy to detec
 fantasai> jarhar: in Chromium not the same
 fantasai> jarhar: the selection is only fired when user dismisses find-in-page dialog
 * dauwhe has quit (Client closed connection)
 vmpstr> q+
 * Zakim sees smfr, TabAtkins, vmpstr on the speaker queue
 fantasai> jarhar: so from Firefox point of view, makes sense not to have extra mitigation, but from our side it's needed
 * dauwhe (~dauwhe@ef89345d.public.cloak) has joined #css
 fantasai> emilio: Other question is, this makes find-in-page effectively asynchronous, which is not something that happens
 fantasai> emilio: how does window.find() work and similar things?
 fantasai> emilio: and why does this have to be a CSS property at all?
 fantasai> emilio: I think if you find text in a 'display: none' subtree, and if page reacts to it
 fantasai> emilio: find again or something
 fantasai> emilio: idk
 fantasai> jarhar: for async part, it's true, the whole flow is async
 fantasai> jarhar: first we find the match, then wait for next animation frame, then ?, then wait for next frame, then see if it was revealed
 fantasai> jarhar: that was seen to be necessary ...j
 fantasai> jarhar: based on page, which wasn't handling the style change synchronously
 fantasai> jarhar: but for normal find-in-page use case, whene not 'hidden-matchable'
 fantasai> jarhar: still keeping it synchronous
 fantasai> jarhar: not really sure if we'll fire beforematch or window.find
 fantasai> jarhar: at this point
 fantasai> jarhar: only motivation for me is to make easier to test across platform, but not aware of any use cases for window.find where you need to search hidden content
 astearns> ack smfr
 * Zakim sees TabAtkins, vmpstr on the speaker queue
 fantasai> smfr: ...
 fantasai> smfr: you select into it
 fantasai> smfr: and then you have to realize all the content
 * dholbert (~dholbert@ef89345d.public.cloak) has joined #css
 fantasai> smfr: seems like what you're proposing would bring in content during find, incremental improvement
 astearns> s/.../from what I remember about content-visibility/
 fantasai> smfr: but wouldn't select content
 fantasai> smfr: previously if user did select-all on the document
 melanierichards> present+
 fantasai> smfr: because of selection, would realize content for invisible stuff, woudl be slow (?)
 fantasai> smfr: but find would work in a reasonable way
 * Rossen_ (~Rossen@ef89345d.public.cloak) has joined #css
 fantasai> smfr: with this new thing
 fantasai> smfr: but why is find special?
 fantasai> smfr: what about scroll to text?
 fantasai> smfr: what about seach for addresses, metadata
 fantasai> smfr: #target
 fantasai> smfr: ...
 fantasai> smfr: Why only find?
 fantasai> jarhar: started with find, could expand to other use cases
 fantasai> levin: I think auto already supports all these things
 fantasai> levin: this is adjustment to 'hidden', which is not available to find-in-page
 astearns> ack TabAtkins
 * Zakim sees vmpstr on the speaker queue
 fantasai> TabAtkins: You mentioned how a page doesn't respond to the format event by revealing something, we'll remove their ability to do it
 fantasai> TabAtkins: does that mean we automatically turn the thing visible, or what?
 fantasai> jarhar: We stop firing the beforematch event
 fantasai> jarhar: it's invisible
 fantasai> TabAtkins: so the whole page is broken, not just one aspect of the use
 fantasai> jarhar: Usually there's some other way to reveal content in the page, just find-in-page would be broken
 * plh has quit ("Leaving")
 fantasai> TabAtkins: Before you'd walk up and try to find something auto that could fail open rather than failing closed
 fantasai> myles: So if you catch an event and do nothing, different from not catching the event??
 fantasai> florian: I don't think anyone said that
 fantasai> florian: question is if you don't respond to event, do you stay hidden or get auto-revealed
 fantasai> TabAtkins: Default being to reveal
 fantasai> TabAtkins: if you're responding on your own, would do CancelDefault
 fantasai> jarhar: There's no way to possibly have the browser build the content
 * dauwhe has quit (Ping timeout: 180 seconds)
 fantasai> jarhar: page is in control of the style, same as 'hidden'
 TabAtkins> s/CancelDefault/preventDefault()/
 fantasai> jarhar: CSS property says this is hidden, and until the page reveals, it should stay hidden
 fantasai> jarhar: There's internal state in the thing, and when you search for it, it would unlock similar to 'auto'
 fantasai> jarhar: but direction we're going, page maintains state, and it has to remove the CSS property
 fantasai> TabAtkins: I would like to have more discussion about that
 fantasai> TabAtkins: feels backwards for bad pages
fantasai> TabAtkins: broken JS
 astearns> ack vmpstr
 * Zakim sees no one on the speaker queue
 fantasai> levin: Use cases we're targetting here are things like wikipedia collapsed sections
 fantasai> levin: where there are already handlers that expand the content
fantasai> levin: this would add that find-in-page can expand the content
 fantasai> levin: if there's an error
 fantasai> levin: It prevents pages from figuring out what character is type by incrementally constructing a DOM but never revealing that content
 fantasai> levin: somewhat possible now with scroll offsets, but they're visible always
 fantasai> levin: Content you're searching is visible
 fantasai> levin: would allow you to search content, and remains visible
 vmpstr> S/levin/vmpstr/
 fantasai> TabAtkins: Framing of strict improvement over 'hidden' makes me a little happier
 fantasai> TabAtkins: but think there should be some discussion about whether that's the right way to go
 TabAtkins> s/'hidden'/'display:none'/
 fantasai> +1 to Tab's concern
 fantasai> and to smfr's
 fantasai> astearns: Hearing some concerns around what happens when events break
  astearns: ..
 fantasai> astearns: Wonder if we should take this back to the issue and get more of the proposal fleshed out, and answer questions, then bring back on a regular call
 fantasai> astearns: Any other discussion?
 fantasai> fantasai: Just +1 to TabAtkins and smfr's questions and conerns

@josepharhar
Copy link
Contributor Author

Thanks for the questions at TPAC!

@fantasai
I agree the details element is an important use case, it was brought up in this issue: WICG/display-locking#162

@emilio

  • We could keep find-in-page synchronous for cases where we aren’t firing beforematch now that we are only going to fire it on hidden-matchable subtrees, but what is the benefit of keeping it synchronous? In stable chrome we are currently doing the full async code path for every find-in-page and there doesn’t seem to be any issues.
  • For window.find, I don’t currently have plans to implement beforematch and such in it since it doesn’t really seem like there are important use cases for it and it has very low usage. The only reason I can think of is being able to test beforematch in WPT. Previously, I was more hesitant to change window.find since making it async could break the synchronous scrolling behavior of window.find. We could make the scrolling happen synchronously for non beforematch/hidden-matchable matches, but having both sync and non-sync behavior doesn’t sound amazing… what do you think?

@smfr
You mentioned other use cases for beforematch than just find-in-page:

  • ScrollToTextFragment is definitely a big use case we are supporting.
  • Element fragments are more problematic since the page must scroll synchronously when the fragment is changed, which isn’t compatible with the async steps we have for the beforematch event which allows the page to reveal the content asynchronously. In addition, the page can already see the fragment on page load and observe changes with the hashchange event.
  • What are the "addresses" and "metadata" use cases you talked about?

@vmpstr
Copy link
Member

vmpstr commented Oct 28, 2020

To recap, the proposal is to add a new keyword to content-visibility, called hidden-matchable which acts like hidden but allows searchability (find-in-page and scroll-to-text) and the beforematch event.


In addition to @josepharhar's comments, I want to address another common question: should the default behavior of the beforematch be to un-hide the content automatically?

We've considered this in the past, and I think it adds to the complexity of the feature. I don't think there is an elegant way to un-hide the element when it's hidden by a css property: we can't modify the style sheet since the rule may be coming from some large class applied to a number of elements; we can either 1. add a pseudo class to keep the 'expanded' state or 2. modify inline style (ie set the style attribute on the element).

For 1, we then need a way to clear the pseudo class in order to hide the element again: Element.clearPseudoClassX? We can also clear it automatically if we remove the hidden-matchable property which means to hide something the script has to remove and re-add the property, which isn't ergonomic.

For 2, I think modifying inline style is awkward, especially if the page is using the style attribute for its own purposes (ie appending a new value to an existing string).

I think that requiring script to remove the value as a response to beforematch is the simplest approach. It also allows script to modify any other styles (e.g. change the orientation of the arrow in the section heading to indicate that its expanded), which is a common use case already.


For the details element, I think we can add an attribute to opt-in the details element into the behavior that it would essentially apply content-visibility: hidden-matchable and have a default handler that effective would remove it. In other words, we can make the details element be searchable and expandable with one attribute, but I feel that it is a separate discussion

@vmpstr vmpstr added the Agenda+ label Oct 28, 2020
@josepharhar
Copy link
Contributor Author

In today's meeting, I would like to discuss:

  1. The idea of exposing hidden content to searching (find-in-page and ScrollToTextFragment)
  2. Is it the correct decision to integrate with content-visibility
  3. Should it be script which unhides the content as opposed to the browser

@tabatkins
Copy link
Member

tabatkins commented Nov 4, 2020

Related issue about representing the visible state of auto explicitly: #5695

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed [css-contain-2] Proposal: content-visibility: hidden-matchable.

The full IRC log of that discussion <dael> Topic: [css-contain-2] Proposal: content-visibility: hidden-matchable
<dael> github: https://github.com//issues/5595
<dael> jarhar: I proposed this property which allows UA to search for text inside hidden content which find in page and scroll to text
<dael> jarhar: Looking for resolution on 3 points. 1 is the general idea good? 2) is using content-visibility a good idea 3) does it make sense for script to be responsible to reveal or the browsers?
<dael> jarhar: Starting with 1 does it sound like a good idea?
<dael> TabAtkins: Yes, I like the feature. We should persue something
<dael> astearns: Anyone with opposite opinion?
<dael> smfr: Do we think authors can make rational decisions about to use hidden-matchable vs hidden? Is there a case where they would not want find in page behavior?
<dael> chrishtr: Yes, one example is when you want ot hide content which does not make sense for user. tabbed content and it's a previous view. Not in your current route so doesn't make sense to search
<dael> smfr: Makes sense
<dael> smfr: I think it's reasonable feature. Seems special-case-y
<dael> Rossen_: What was the use case?
<fantasai> s/special-case-y/special-case-y, I don't really like it/
<dael> jarhar: Use case if the user searches for something with find in page. Page has hidden content like mobile wikipedia where there's collapsed sections. User wants to find text inside the collapsed. Page should be able to show the sections in response to the search
<heycam> q+
<dael> TabAtkins: One use case for content-visibility is let page spam a bunch of content into the dom and this allows the dom content to be searchable even if not displayed
<smfr> q+
<dael> astearns: Rossen_ is that enough of an answer?
<dael> Rossen_: Thank you
<astearns> ack heycam
<dael> heycam: I don't have a strong opinion. Seems reasonable. I think we need to have some way to expose hidden content for searching. I wonder if some better names could be used. Seems clearly 2 use cases. content hidden away and not part of current presentation but some content hidden for virtual scrolling. Wonder if better names might help authors to use the right one. No specific suggestions
<astearns> ack smfr
<dael> smfr: On previous call I mentioned things in browsers that index content of web pages. Scroll to and find text isn't the only things that care. Browsers will index for selecting later. Somewhat concerned about a11y. Content must not be accessible to things such as tab order. WEird if you can find the content since there's a result in there if you're using voice over do you instantiate the content when voiceover goes there or are they hidden?
<dael> jarhar: I see the tab order point.
<dael> jarhar: I'm not very familiar with voice over or indexing pages for later use within browser features
<dael> TabAtkins: Tab order is intentional. Tabbing the auto-expended sections open. Good a11y the thing that expands the section should be tabbable. Don't know you should be able to tab in
<dael> vmpstr: No use cae where only way to find is via find in page. You can expand with tab or clcik. This is expanding to find via find in page. No case where only way to find it is find in page
<astearns> ack fantasai
<dael> chrishtr: For a11y doesn't make sense to expose to default order just like doesn't amke sense for tabbing because you're tabbing through what's seen right now. Would be good to expose find in page to cause hidden content to be shown when you search it
<dael> fantasai: Based on the use cases I think behavior of keeping out of tab order makes sense. I think targetting element using fragment ID should be similar to find in page. Possibly some other API
<dael> chrishtr: YOu lean fragment navigation?
<dael> fantasai: Yeah
<dael> jarhar: We were thinking of that earlier but got complicated when we impl async flow where make browser wait to scroll for two request animation frames so we give the page time to reveal the element before browser scrolls. Couldn't do the same thing for element fragment ID scrolling b/c page can observer sync change so we would need to not include the async step or break the current behavior
<dael> jarhar: Considering the page can see changes to fragment idea seemed like we could not fire before match on fragment IDs
<dael> fantasai: But then page needs to know if it's a dependant. If you looka t use cae with collapsable sections you want them to auto-expend even if someone gave you a link into the subsection. That shouldn't be worse than a text fragment ID. THe fact that the sub-section has an ID is a good thing and we shouldn't treat it as less convenient. Shouldn't make the author do extra work to support that
<dael> jarhar: Makes sense.
<dael> jarhar: Wondering about separating navigating to and script showing it. Not sure right now on the best path forward
<dael> astearns: WE're at time. Answer I'm hearing to the first question is yes it's a good idea but not just for the things you have defined. Good to flush out other ways of nav to other hidden places
<dael> smfr: Would like an explicit request for a11y input
<dael> astearns: I'll cut it off there

@josepharhar
Copy link
Contributor Author

Thanks for the discussion today!

@smfr could you elaborate on the things in browsers that index content of web pages for searching?

@alice, @smfr requested input from a11y - do you have any thoughts about hidden-matchable DOM being included or excluded from the tab order as mentioned in the irc log or any other a11y thoughts about content-visibility: hidden-matchable?

@alice
Copy link

alice commented Nov 6, 2020

We went back and forth on this a while ago - we came to the conclusion that with the way assistive technologies (ATs) work today, it makes the most sense not to expose this content to ATs until it is visible on the page. This does mean that an AT-specific find in page feature will not be able to use the hidden-matchable functionality, unfortunately, but the alternative (exposing that content to AT, even with a "hidden" flag set) would mean that AT users would not benefit from the intended performance benefits of the feature, which are even more acute when using AT.

As far as excluding this content from the tab order goes... it seems obvious to me that we would not want hidden-matchable content in the tab order. Is there some reason why it's not?

@cookiecrook
Copy link
Contributor

We went back and forth on this a while ago - we came to the conclusion that with the way assistive technologies (ATs) work today, it makes the most sense not to expose this content to ATs until it is visible on the page.

  1. Is “We” here the TAG? Googlers? Some other group?
  2. Are any of those discussions linkable?

This does mean that an AT-specific find in page feature will not be able to use the hidden-matchable functionality, unfortunately, but the alternative (exposing that content to AT, even with a "hidden" flag set) would mean that AT users would not benefit from the intended performance benefits of the feature, which are even more acute when using AT.

This might depend on the implementation. If each element were exposed fully to the Accessibility tree, I agree that it would negate the perf benefit, but… Hypothetically, what if a general “find text” API were exposed in such a way that the AT could leverage the same path as the UA? VoiceOver already offloads some of its search functionality (next heading, next table, etc.) to WebKit. Perhaps a similar path could be used here.

@alice
Copy link

alice commented Nov 7, 2020

  1. Is “We” here the TAG? Googlers? Some other group?

Just me, talking with the folks working on this proposal.

  1. Are any of those discussions linkable?

I think WICG/display-locking#102 is the relevant public thread.

Hypothetically, what if a general “find text” API were exposed in such a way that the AT could leverage the same path as the UA? VoiceOver already offloads some of its search functionality (next heading, next table, etc.) to WebKit. Perhaps a similar path could be used here.

This is why I noted "the way ATs work today" specifically. I agree, deeper integration into an AT's find-in-page mechanism would be ideal.

@cookiecrook
Copy link
Contributor

cookiecrook commented Nov 8, 2020

This is why I noted "the way ATs work today" specifically. I agree, deeper integration into an AT's find-in-page mechanism would be ideal.

I’m suggesting this new API proposal could (should) allow that. The web app does not need to know if the agent initiating the search is the UA, or if it’s an AT behind it. How the UA exposes that search API to the AT is an implementation detail.

@alice
Copy link

alice commented Nov 8, 2020

I’m suggesting this new API proposal could (should) allow that. The web app does not need to know if the agent initiating the search is the UA, or if it’s an AT behind it. How the UA exposes that search API to the AT is an implementation detail.

I don't think we're disagreeing at all. I think we both agree that hidden-matchable contents should not be exposed in full to ATs, and that if possible with that limitation, AT find in page should be able to access contents within hidden-matchable trees.

@josepharhar
Copy link
Contributor Author

In the last meeting, it sounded like there was concern over beforematch/hidden-matchable being available to other algorithms. I'd be happy to add support (fire beforematch) for these cases which I understand:

  • Element fragments on navigation (can't make window.location.hash changes from script have async scrolling)
  • window.find since we can try making the scrolling async since it isn't specced and has very low usage

I’m suggesting this new API proposal could (should) allow that. The web app does not need to know if the agent initiating the search is the UA, or if it’s an AT behind it. How the UA exposes that search API to the AT is an implementation detail.

I agree, and I would be happy to say that the user agent should feel free to fire beforematch under hidden-matchable during behavior similar enough to the user intent in find-in-page.

@chrishtr
Copy link
Contributor

/sub

@josepharhar
Copy link
Contributor Author

After thinking some more about the element fragment case for beforematch, I think it could get complicated:

  • If we try to make it have async scrolling, even in the navigation case like I mentioned in my last comment, it might still break some things, I won't know until I actually change it and see what happens
  • If we make it have sync scrolling, which wouldn't change the existing brittle elementfragment behavior, we would be making beforematch have different semantics in the elementfragment case vs the scrolltotextfragment/find-in-page case because the scrolling would happen at a different time for each. If the timing matters to a page which uses beforematch for both of them, which seems likely, we would get cases where the page reveals content after the scroll occurs for elementfragment and the page would reveal the content before the scroll for scrolltotextfragment/find-in-page with the exact same beforematch event handler.

It seems like we probably won't be able to make beforematch for elementfragments work the same as it does for scrolltotextfragment/find-in-page, which could be worse than omitting beforematch for elementfragments.

In addition, are already capable of expanding content in response to changes to the elementfragment via the hashchange event, and you can see that mobile wikipedia already expands specific content when navigating with an elementfragment: try navigating here in mobile device emulation mode and you will see that only the target section is expanded: https://en.m.wikipedia.org/wiki/COVID-19_pandemic#Prevention

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed [css-contain-2] Proposal: content-visibility: hidden-matchable.

The full IRC log of that discussion <dael> Topic: [css-contain-2] Proposal: content-visibility: hidden-matchable
<dael> github: https://github.com//issues/5595
<dael> jarhar: Last time we talked on this some concerns on a11y on this. Simon mentioned browsers indexing pages
<dael> jarhar: What I talked in GH for a11y there was discussion with jcraig and Alice which I hope resolve the a11y concerns
<dael> jarhar: Anchro navigations is interesting. The thing about adding before the element anchors we can't have async behavior when scripting. Even doing it on nav is breaking. Probably best to keep sync scrolling for the fragments
<dael> jarhar: Could fire before-match but then it would have different behavior than find in page. Could be cases with an element frag scroll before the lement is revealed but find in page is okay
<dael> jarhar: Gave example on mobile wikipedia where element fragment navigation works where you expand the fragment. I see argument of a one stop shop but on the other hand depending on how handler impl it might not reveal it on time and that might not be great
<dael> jarhar: It would be cool is smfr could expand more on how browsers index. Interested in supporting more.
<dael> jarhar: We could talk more about if people think this is the right idea if that's fine
<dael> astearns: First thing, concerns about a11y. Any comments or concerns on that discussion to bring up?
<dael> astearns: Okay, we'll assume GH was enough
<dael> astearns: Second is indexing pages
<dael> smfr: I need to figure this out. May be Safari looks at DOM so not an issue. I need to research more on that
<dael> jarhar: Thanks, I appreciate it
<dael> astearns: Extending proposal to anchor naivagations. You're proposing not to
<dael> jarhar: We could make it a one stop shop but might break some websites which expect the async behavior and you'd get different for find in page vs element nav. Anyone with thoughts on which idea sounds better
<dael> fantasai: I just don't understand events model. I haven't dug into it.
<dael> jarhar: Elaborating a bit. In chrome when I impl when Iput before match event for find in page it was async. Between text adn scroll I added event. Some sites in before match change the style async where it reveals after the scroll. TO support that we changed find in page scrolling to be async. Nothing breaks if we wait 2 animation frames.
<dael> jarhar: Added async to support this
<dael> jarhar: With element fragments it's a little more brittle. Sync behavior is more baked in. Making async is likely to break. Could keep it sync but it might not work on all sites. Want to avoid pages not revealing content on time due to security mitigations. It would be bad to have a page miss expanding content in responce to before match
<dael> fantasai: I think it makes sense.
<dael> fantasai: Concern is that I don't want us to be in a world where the behavior of an element target or ID targetting element has substantially different behavior thenusing text fragment style of ID content
<dael> fantasai: Having one of those expand a collapsed section and the other not is weird
<dael> jarhar: Makes sense
<vmpstr> q+
<dael> fantasai: I don't know how to solve technical end, but having behave different is not good
<dael> jarhar: scroll to text frag we were in better place b/c newer. When I made it async it didn't break
<tantek> with fragmentions the URL also changes, which I think is correct because it is analogous to fragment-ID navigation
<dael> fantasai: There's scroll to text fragment which is in URL and find in page which isn't URL. Having those different is better than having 2 types of fragment be different. Clicking on a paragraph and if it has an ID determines different behavior is bad. I don't have a solution
<dael> jarhar: Good concern. I can dig more and see if there's a way to make scrolling async for navigations. Might not be clear if I break anything but hopefully there's tests
<astearns> ack vmpstr
<dael> vmpstr: I wanted to point out that you metnioned should be no difference if linking with a fragment link vs scroll to text. Currently pages can expand fragment link nav. Not mech to expand a section when there's scroll tot ext fragment.
<fantasai> https://www.w3.org/TR/selectors-4/#the-target-within-pseudo
<dael> vmpstr: This prop brings parity to same level. Not same API but capability is the same
<dael> fantasai: I understand from you can get same functionality. But if there's a doc with collapsed section, some has ID and some don't. Asking for the ID shouldn't change if it closes or not. If author is expected to have 2 impl chances are they're impl the thing they thought of and one will uncollapse and the other won't
<tantek> TBH this is one of the problems with Google's scrollToText as compared to fragmentions. Pages can expand both fragment link nav *and* fragmention link nav, but not scrollToText
<dael> fantasai: More understandable if targets are different. Less okay if 2 different types of target have different behavior
<dael> fantasai: We do have target in pseudo class and that should be matched by text fragments and selectors. Styling-wise it can be done. Don't know JS stuff
<fantasai> s/target/:target-within/
<dael> astearns: And we are at time. I suggest we go back to see if there is a solution for fantasai's concern. Let's keep this on the agenda and bring it up at the beginning of the next call to answer if this is a good thing b/c I'd like to get you that answer
<dael> jarhar: Sounds great

@astearns
Copy link
Member

My plan is to have a quick discussion (10 min?) at the beginning of the next meeting focused on a yes/no answer to the “Is this worth pursuing” question. So please bring up any latent deal-breakers here.

Does the difference in show/hide behavior for various ways of scrolling to content have to be solved for this to be viable?
Are there objections to ScrollToTextFragment that would make this moot?
Is there anything not yet discussed or that I’ve glossed over that show a fundamental problem with this approach?

Let’s please argue through everything we can asynchronously here before the next meeting starts.

@josepharhar
Copy link
Contributor Author

Thanks for the discussion!

My plan is to have a quick discussion (10 min?) at the beginning of the next meeting focused on a yes/no answer to the “Is this worth pursuing” question. So please bring up any latent deal-breakers here.

From what I could hear, there was no objection about exposing hidden content, it was just about which algorithms, accessibility, and other details. If anyone has an issue with the approach in general, please say so, otherwise we’ll just focus on the details.

If possible I’d like to discuss point 2 from this comment, which is whether it’s the right idea to integrate this feature with content-visibility, as the first agenda item next time.

Does the difference in show/hide behavior for various ways of scrolling to content have to be solved for this to be viable?

The consistency argument in favor of firing beforematch for element fragments is pretty strong. I agree we should plan on firing beforematch for these fragments. Let’s continue this discussion of how to do so in the parallel html issue: whatwg/html#6040

@smfr
Copy link
Contributor

smfr commented Dec 2, 2020

  • What are the "addresses" and "metadata" use cases you talked about?

I brought these up because I think adding CSS behaviors for a single browser feature like Find is odd. Find isn't necessarily the only way that UAs look for things in page content.

addresses: WebKit API has a way for clients to ask for all the identified bits of metadata in certain categories in the content (e.g. addresses, telephone numbers), and these can be matched eagerly.

metadata: Safari indexes locally the text content of pages that you visit for Spotlight (searching outside of the browser can offer up a link to a page that you have previously visited).

In both cases, page content is traversed via the renderer tree (i.e. taking styles like display:none and visibility:hidden into account). My issue with content-visibility: hidden-matchable is that it focusses too narrowly on the Find use case, and not on other use cases like these which also involve searching page content, but more indirectly.

Secondarily, a question: UAs can't run their Find In Page logic in content-visibility: hidden content without actually doing style resolution, because they need to know if the find result will end up inside display:none or visibility:hidden content. I think that implies that UAs would have to do some amount of render tree building in order to implement Find inside content-visibility: hidden-matchable. Is that something you've considered?

@FremyCompany
Copy link
Contributor

Re: "I feel this discussion was not rooted in concrete cases": what do you mean exactly? There are real-world examples in the explainer and in this issue. Likewise multiple additional ones were mentioned in the discussion today.

Not the issue per se, but the discussion we had today in general (there was a lot of process drama, blame shifted around, and theoretical arguments that I didn't feel were aimed at finding a solution). I believe that, at this point, we should focus on whether we want to solve the presented use cases (I do) and whether there is another way to do this that makes more sense than what's on the table. I haven't heard any yet, and I would love people who have objections or after-thoughts to articulate precise proposals solving or hinting at solutions for these use cases, or point why they don't believe this is worth fixing given the cost of the current proposal, which I think is pretty solid.

@chrishtr
Copy link
Contributor

chrishtr commented Feb 9, 2021

Not the issue per se, but the discussion we had today in general (there was a lot of process drama, blame shifted around, and theoretical arguments that I didn't feel were aimed at finding a solution). I believe that, at this point, we should focus on whether we want to solve the presented use cases (I do) and whether there is another way to do this that makes more sense than what's on the table. I haven't heard any yet, and I would love people who have objections or after-thoughts to articulate precise proposals solving or hinting at solutions for these use cases, or point why they don't believe this is worth fixing given the cost of the current proposal, which I think is pretty solid.

Ok got it, thanks for clarifying!

@chrishtr
Copy link
Contributor

chrishtr commented Feb 9, 2021

One additional point I'd like to make (@astearns suggested I talk it through) is regarding potential risk to the platform if we get this wrong.

There was quite a bit of discussion today about how this feature touches some things that are very important parts of the web platform - in particular, progressive enhancement, how to express meaning in HTML elements, and how it relates to CSS. I agree that all of these things are very important, and I think it's more than fair to say all of us in this group also think so.

So what if this feature ships and we end up deciding it was not the right thing, and need to back it out or replace it with a better solution? What would break / how hard would it be to do this?

I think it would be quite easy: we'd just stop firing beforematch, and treat content-visibility: hidden-matchable as an alias of content-visibility: hidden.

Sites could not possibly break due to this, in the sense of a broken display or javascript errors. Likewise it should also still be possible for users to find all the content they want, because sites can't rely on find-in-page or search engines to drive users to the content they want - the sites also have UX affordances such as buttons, scrolling widgets, or accordion icons that have click event listeners to show the hidden content.

The main problem for sites would be if they come to depend (in the sense of expecting it to work as part of their UX plan for users) more deeply on beforematch and would be unhappy to lose the feature. If the feature needs to get backed out or replaced, and this sites-want-it problem is deemed important enough, then we'd need to have a replacement feature, fulfilling the same use cases, already implemented before the old one is removed, and give sites some time to migrate.

@emilio
Copy link
Collaborator

emilio commented Feb 10, 2021

So one thing that comes to mind regarding this, and which might not have been considered (or if it was, the explainer doesn't seem to say...), and which would:

  • Simplify the handshake that the page and the browser needs to do.
  • Remove the need to add new CSS property values or tie the page to use a particular way to hide / not hide the content.
  • Has existing precedents.

Why not, instead of adding a per-match beforematch event which only fires on elements with a particular CSS property, we do a global pair of events like beforeprint / afterprint (beforefind / afterfind? Do we even need afterfind?)

In those events, the page could unhide all the content that it wants findable (it could maybe even get the string to be found, perhaps? not sure). It seems like a simpler design, and similar to how pages adapt to print in other ways other than CSS.

My reasoning for why this is likely better, even without the search string, is that all browsers have find-as-you-type kind of functionality, so in practice unless I'm missing something, beforematch is likely to actually match large parts of the document for find-in-page, when the user starts typing (and thus most of the content would be findable).

Getting the string to be found is perhaps more appealing in the scroll-to-text-fragment use-case, though I assume that the way this feature has been designed is to prevent exposing the exact fragment, which would have privacy implications. But then again the page can observe what the user has searched for with beforematch, right? And anyhow, I don't think getting the query string is necessary, and it'd likely be better.

@chrishtr I wonder if such a solution was considered and if so why was it discarded? At least for find-in-page, it seems like a much simpler solution.

@chrishtr
Copy link
Contributor

Why not, instead of adding a per-match beforematch event which only fires on elements with a particular CSS property, we do a global pair of events like beforeprint / afterprint (beforefind / afterfind? Do we even need afterfind?)

In those events, the page could unhide all the content that it wants findable (it could maybe even get the string to be found, perhaps? not sure). It seems like a simpler design, and similar to how pages adapt to print in other ways other than CSS.

I think your idea is: batch-unhide all the things and render them all at once whenever any of these algorithms run. And then once the find-in-page or scroll-to-fragment operation is done, leave things in the opened state. Is that correct?

I'm not sure this works better. Here are reasons I can think of:

  • Performance: requires full rendering of everything. This would mean in particular page loads that use scroll-to-fragment would get a lot slower. Right now, Chromium's implementation only has to do style recalc (and even then it can be optimized further in the future).

  • Undesirable UX: sites may not want all sections or infinite-list content to be shown at once. For example, mobile Wikipedia would be much slower to scroll through (more gestures required) if all sections were opened at once, which is what would happen if you load the page with scroll-to-text or had just done a find-in-page. Or sites might have a UX that makes no sense to be "all open" - e.g. they have content in modal-like widgets.

My reasoning for why this is likely better, even without the search string, is that all browsers have find-as-you-type kind of functionality, so in practice unless I'm missing something, beforematch is likely to actually match large parts of the document for find-in-page, when the user starts typing (and thus most of the content would be findable).

The point you make about lots of beforematch events firing has been raised before, in particular in the TAG review. I think a good way to solve it is to not fire the event on every keystroke, but instead at a slower rate, and/or only fire if there are enough characters typed to narrow the match sufficiently.

@chrishtr I wonder if such a solution was considered and if so why was it discarded? At least for find-in-page, it seems like a much simpler solution.

No, what you propose here hasn't been considered as yet.

@emilio
Copy link
Collaborator

emilio commented Feb 10, 2021

Why not, instead of adding a per-match beforematch event which only fires on elements with a particular CSS property, we do a global pair of events like beforeprint / afterprint (beforefind / afterfind? Do we even need afterfind?)
In those events, the page could unhide all the content that it wants findable (it could maybe even get the string to be found, perhaps? not sure). It seems like a simpler design, and similar to how pages adapt to print in other ways other than CSS.

I think your idea is: batch-unhide all the things and render them all at once whenever any of these algorithms run. And then once the find-in-page or scroll-to-fragment operation is done, leave things in the opened state. Is that correct?

Sorta. If the page doesn't have access to the search string / fragment directive / etc, then yes, it can only unhide ~everything and pray. But if it does have access to it (which might be a reasonable thing...) then the page can decide what to show or what not.

Undesirable UX: sites may not want all sections or infinite-list content to be shown at once. [...] Or sites might have a UX that makes no sense to be "all open" - e.g. they have content in modal-like widgets.

Right, but those are also existing issues (for find-in-page, at least) with this proposal, right? As in, that's what happens if you do a find in page and type e.g. the "a" character with beforematch, right? (Assuming nearly all sections of a wikipedia article are going to have an "a" character around). The modal widget thing has also the same issue with beforematch.

With the search string exposed as part of the event, pages could decide which thing to show.

@chrishtr
Copy link
Contributor

Sorta. If the page doesn't have access to the search string / fragment directive / etc, then yes, it can only unhide ~everything and pray. But if it does have access to it (which might be a reasonable thing...) then the page can decide what to show or what not.

Are you suggesting then to expose the find-in-page or scroll fragment text to the page? This could be a privacy problem.

Undesirable UX: sites may not want all sections or infinite-list content to be shown at once. [...] Or sites might have a UX that makes no sense to be "all open" - e.g. they have content in modal-like widgets.

Right, but those are also existing issues (for find-in-page, at least) with this proposal, right? As in, that's what happens if you do a find in page and type e.g. the "a" character with beforematch, right? (Assuming nearly all sections of a wikipedia article are going to have an "a" character around). The modal widget thing has also the same issue with beforematch.

This is what the mitigation I mentioned is about. It would not fire the event if you type "a" if there are too many matches / "a" is too short of a string / it's been too little time since you typed another character. This would be something that is up to the UA to optimize.

With the search string exposed as part of the event, pages could decide which thing to show.

Wouldn't this mean the site has to implement search themselves? Or would they use window.find (which we'd then write a spec for)?

This also won't work for find-in-page unless there was an event provided to script to listen in on what is being typed.

It's true that if you directly expose the find-in-page or search query text to script, then the script can be smarter about things. It can even do stuff like bringing in "search results" that are not even in the DOM at all (which I think is bad, for reasons of it not being good to keep semantic document state out of the document, as it messes up progressive rendering and accessibility goals in multiple ways). And as I mentioned there is a security / privacy problem.

@fantasai
Copy link
Collaborator

A few of us (@smfr, @emilio, @fantasai, @FremyCompany, @frivoal) got together to try and think a way out of the current apparent deadlock. Here's what we came up with.

Goals:

  • Build primitives for making <details> work
  • Make it so that it can work without JS

Design: UA does the reveal, sets an attribute so page can respond without JS, fires event to allow page to adapt if more than that is necessary.

Proposal: Add new value to 'hidden' attribute (e.g. hidden=until-found) to represent hidden-matchable state, remove attribute when UA wants to reveal the content. It does not on its own hide the content; that's achieved by matching this attribute through selectors and applying display:none or content-visibility:hidden, as appropriate. (Default to ??? in the UA stylesheet.) It does mean though, that the content remains searchable even if it’s hidden away using something that would otherwise make it not searchable. Match triggers if element or content within is targeted (e.g. using find, using scrollToElement or .focus(), using fragID). In the case of search, only trigger on "find next", not merely when finding all the matches so that e.g. Wikipedia doesn't reveal all sections as soon as you type 's' into the search box.

Note: In WebKit, find normally requires layout, though a specialized path finding probable matches could conceivably be built.

ISSUE: Should sequential navigation ("go to next heading", tab navigation) trigger a match? Seems to depend on the use case.

P.S. We should also fire an event when beginning a search so the page can can update DOM with suspended content, but this is a separate issue.

@josepharhar
Copy link
Contributor Author

Thanks for the proposal!

Improving <details> sounds great!
Using a CSS attribute selector for hidden=until-found which hides the content and letting the browser remove the attribute sounds great! It allows a wider variety of use cases to work without script.
I don't think that supporting find-in-page or other algorithms in display:none makes sense since it can't have the style and layout resolution needed for them, but supporting visibility:hidden and content-visibility:hidden would be good.

Let's resolve on this at the F2F tomorrow so we can continue to make progress.

@FremyCompany
Copy link
Contributor

FremyCompany commented Feb 11, 2021

I would note that letting the browser remove the attribute isn't sufficient, because if the DOM is generated via tools like React, the attribute would reappear at the next React update. So, the onbeforematch event is still required to support JS-driven websites (and other use cases, like rehydration of content).

So, given that, I propose that the default behavior (that is, if you don't call preventDefault) of onbeforematch would be to remove the hidden attribute if its value allows it, and if the parent element is a <details> tag, also set its open attribute if it currently doesn't exist. Since the event tunnels and bubbles, that should work transparently, and authors can do something else if they would rather do.

The issue of how search would function on <details> given its content is currently out of the tree while hidden (akin to display: none) should be discussed separately. Maybe we can change the behavior of <details> to rely on content-visibility:hidden for its content instead? Or we can provide a way to opt into this behavior, so as to not break compat.

There is still one thing which I don't like, and that is the "if you fail to unhide once, you never get the event anymore" because I don't see why it's useful to punish the page in this way. If calling onbeforematch didn't reveal the content, you move to the next match and call it a day, I don't see why we want a persistant flag hidden to the page that disables the feature, that sounds like a footgun.

I was also wondering if the website could eventually return a Promise to the event to notify when the revealing has been done, so that the browser doesn't have to rely on heuristics like "the next frame". There are already precedents for this, as described on MDN. Of course, if waitUntil is never called, the default timeout could be the next frame. That would indicate the website just let the browser remove the attribute, which will have an impact instantly.

@chrishtr
Copy link
Contributor

chrishtr commented Feb 11, 2021

There is still one thing which I don't like, and that is the "if you fail to unhide once, you never get the event anymore" because I don't see why it's useful to punish the page in this way. If calling onbeforematch didn't reveal the content, you move to the next match and call it a day, I don't see why we want a persistant flag hidden to the page that disables the feature, that sounds like a footgun.

The reason is to prevent the page from violating privacy by trying to read what you are typing into the search. However, it could be that this particular privacy mitigation doesn't end up being the best idea. How about we have spec text such as "the User Agent may skip calling page-defined event handlers if doing so is likely to lead to a privacy risk for the user. In these cases, content which would have been matched by the search but are currently not visible to the user are skipped."

@smfr
Copy link
Contributor

smfr commented Feb 11, 2021

I don't think we can support preventDefault on beforematch events because of how those are sent after a delay.

@smaug----
Copy link

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?
Or is the idea that one can't use .hidden API to set the value to "until-found", only setAttribute.
That would be a bit awkward and even error prone, I think.

@hftf
Copy link

hftf commented Feb 12, 2021

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

  • CSS already has tools to control the visibility of content. They include display: none, visibility: hidden, and now content-visibility: hidden. (HTML5 has the hidden attribute as well, and there are probably more hiding mechanisms I haven’t mentioned.)

  • Precedents already exist in CSS for controlling (enabling or disabling) other primitive user interaction abilities via specific properties. They include selectability and copyability via user-select, and clickability and hoverability via pointer-events.

  • In a similar fashion, a new property could let authors declare the searchability of an arbitrary element. It could be called something like user-search or content-matchable or whatever. Has this been considered?

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.

  • Toggleable/collapsible/expandable/foldable sections (or section headings)
    • Wikipedia mobile site. Not implemented using <details>, but arguably I suppose it could work semantically.
    • Recursively nested comment threads (forums, Reddit, outliners)
    • Generated table of contents, .focus() should still work
  • Paginated lengthy content
  • Automatically scrolling content (accordions, carousels, marquees)
  • “Infinite scrolling” (Twitter)
  • Audio/video captions (usually, only the current caption is visible, unless you open the entire transcript)
  • Slideshow presentations (usually, only one slide is visible at a time, unless you open the slide overview)
  • Modals temporarily blocking main content (the modal may not even be conceptually part of the document)
  • Really anywhere you’ve seen a “read more” or “show the rest of this thread” button to click to reveal or load on demand (won’t name examples, since it’s so ubiquitous)
  • Spoiler tags

@chrishtr
Copy link
Contributor

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
Copy link
Contributor

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
Copy link
Member

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
Copy link
Contributor

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----
Copy link

smaug---- commented Feb 14, 2021

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
Copy link
Contributor

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
Copy link
Contributor Author

I am now proposing this feature to be an attribute instead of a CSS property in whatwg/html: whatwg/html#6040 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
css-contain-2 Current Work HTML Requires coordination with HTML people
Projects
None yet
Development

No branches or pull requests