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.

vmpstr commented 3 years ago

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 commented 3 years ago

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 commented 3 years ago

Thanks for the questions at TPAC!

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

@emilio

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

vmpstr commented 3 years ago

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

josepharhar commented 3 years ago

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 commented 3 years ago

Related issue about representing the visible state of auto explicitly: https://github.com/w3c/csswg-drafts/issues/5695

css-meeting-bot commented 3 years ago

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/w3c/csswg-drafts/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 commented 3 years ago

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 commented 3 years ago

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 commented 3 years ago

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 commented 3 years ago
  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 https://github.com/WICG/display-locking/issues/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 commented 3 years ago

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 commented 3 years ago

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 commented 3 years ago

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:

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 commented 3 years ago

/sub

josepharhar commented 3 years ago

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

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 commented 3 years ago

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/w3c/csswg-drafts/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 commented 3 years ago

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 commented 3 years ago

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: https://github.com/whatwg/html/issues/6040

smfr commented 3 years ago
  • 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?

smfr commented 3 years ago

Also how is content-visibility: hidden-matchable expected to interact with UA features like Reader view? If the content is important enough to allow Finding, should it be included in Reader views?

vmpstr commented 3 years ago

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.

Thank you for the examples. I agree that the spec should allow the UA to traverse/search through the hidden-matchable content to support these use cases.

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?

That’s a good point. In our prototype in Blink, we do recalc style, build the layout tree and do some layout as well in order to support this feature, which is necessary, as you said.

Also how is content-visibility: hidden-matchable expected to interact with UA features like Reader view? If the content is important enough to allow Finding, should it be included in Reader views?

Reader view sounds similar to Spotlight indexing. So I think hidden-matchable content could also be exposed to Reader.

chrishtr commented 3 years ago

In terms of preparing for the CSSWG meeting today, based on comments here and various offline discussions, I think we have consensus that the answer to both of the following questions is "yes":

  1. Is it useful to have a way to specify that hidden content can be searched, and expose that to script?
  2. Should the solution for item 1 apply to all methods of searching the UA provides, and all web-exposed APIs for searching?

I hope we can resolve on the "yes" answers in the meeting.

Then there is:

  1. Is having the content-visibility: hidden-matchable CSS value the right way to declare this feature in HTML content? Or is it better to have an HTML attribute, or an independent CSS property?

Once we resolve on 1 and 2, I hope to gather feedback on 3 in the remainder of the 10 minutes. And as a quick reminder, there is some discussion of why we ended up proposing the hidden-matchable value at the top of this issue. (It doesn't cover an attribute alternative though.)

css-meeting-bot commented 3 years ago

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/w3c/csswg-drafts/issues/5595
<dael> jarhar: Couple of things I'd like to resolve quickly
<dael> jarhar: Like to resolve 1) do we have agreement it's useful to have a way to spec hidden content that's searchable in general
<dael> jarhar: 2) Seems like in previous discussions we've talked what algos and things the searching should be exposed to. I'd like to get resolution that this feature should work for all methods of seatching UA provides and all web APIs for searching
<dael> jarhar: If we get those then we can discuss if content-visibility:hidden-matchable is right
<dael> jarhar: Issues with in general having this feature?
<smfr> q+
<dael> Rossen_: Question here, we're talking about searching and a lot of that doesn't lend naturally to css. Meta question for searching is if content presented visually is also available in the DOM so it can be indexed and searched
<dael> Rossen_: And how does that relate to assistive technologies and other layers using that approach. Those are the layers to hit before answering if searchable. Is that fiar?
<dael> jarhar: Was question about a11y? There has been discussion on GH about a11y. Earlier Chris mentioned previous discussion about how a11y tree shows content-visibility auto or hidden content
<dael> Rossen_: My question was if this hidden-matchable is presented to a11y it sounds like your answer is most likely yes it's visible so question is about if it's visible to search
<dael> chrishtr: Question is if it's good to have a way to have content in dom which is hidden from visual display but exposed to ways to search in the document, find in page, reader modes, a11y tools. Correct?
<dael> Rossen_: Yes. And how and where does css play a role since it's mostly visual layer
<dael> Rossen_: If what you're saying...if all the methods you desc will be able to get to the content besides what we paint on screen I think the answer lends easily for if it's available to search
<dael> Rossen_: I think I got my answer. Want to go to queue
<dael> smfr: Two points. One is content-visibility as I understand is optimization so UA doesn't hav e to build render tree. Issue with allowing finding inside is if UA on every page load tries to look for readerizable content it means every page load your hidden-matchable content will still need to be figured out enough to give right answer to indexing code. So you lose the optimization
<fantasai> [smfr mentions that 'visibility' and 'display: none' need to be resolved, for example]
<dael> smfr: Second, anybody who wrote browser code knows you have to think about is content hidden by style, hide from APIs not just visually. display:none does, visibility-hidden sometimes does. Now we have 2 more and I'm uncomfortable adding more variations to is this content available in this scenario
<fantasai> s/visibility-hidden/visibility:hidden/
<dael> chrishtr: Yes, if UA on initial load always indexes and goes into hidden-matchable subtrees performance advantage is lost. I would recommend doing it in a smarter way that doesn't interfere with performance
<dael> chrishtr: This is an additional feature which is different and therefore has a cost of impl complexity. It is useful, though, b/c it's common to have collapsed sections or offscreen that's not rendered for performance but should still be searchable. For that reason I think it's justified
<dael> smfr: I think you said for first point that yes UA has to do the work and in some UAs the advantange can be lost but depends on what UA does.
<dael> chrishtr: I would say it depends on what UA is allowed to do and UA should be allowed to index. There are definitely performance footguns to avoid
<florian> [In the abstract, I feel confortable with the intent of proposed resolution 1 and 2 as initially exposed, but the concerns raised by smfr seem very relevant to me]
<dael> Rossen_: smfr does that satisfy your questions?
<dael> smfr: I guess. It seems unfortunate that the UA can trigger potentially expensive content building in this case
<dael> florian: Clarification question. smfr if I'm hearing you in your view searching and indexing are not separate. index powers the search. Or is index for something other than search?
<dael> smfr: Original obj was why is cmd+f special. There's more indirect. Safari indexes and in other parts of OS you search and get the webpage. And ideally the results would be the same as you cmd+F on the web page. That's why we're saying it should be same results.
<dael> TabAtkins: Seems like that's what htis is intending to do better. Something hideen-matchable is intended to be exposed. ctl+f is off of dom
<dael> smfr: It doesn't. ctr+f doesn't find display:none things. So we run off of display:none type things resolved. If you have display:none inside c-v:h-m content you don't want that to show
<dael> TabAtkins: So you're talking about expensive rendering is pulling something from dom so it shows up in structure for indexing
<dael> smfr: Right and thats up until you render which is fairly expensive
<dael> chrishtr: There is a significant cost, yes. UA should be allowed to index but do so in a way that doesn't harm perf. This is an additive thing b/c shouldn't index thigns that are display:none. It's an advantage to a11y but UA needs to be careful on how you schedule work
<Rossen_> q?
<Rossen_> ack smfr
<smfr> q-
<dael> florian: Could do most of the page and have hidden-matchable as lazy parts. People don't search in ms of load
<dael> chrishtr: Right, something like lazy background processing
<dael> Rossen_: We're in the time allocated. I don't hear alignment to resolve on the two initial asks. I also see lots of conversation in GH. Happy to give it another 10 minutes next week if the general consensus is achieved on issue
josepharhar commented 3 years ago

One is content-visibility as I understand is optimization so UA doesn't hav e to build render tree. Issue with allowing finding inside is if UA on every page load tries to look for readerizable content it means every page load your hidden-matchable content will still need to be figured out enough to give right answer to indexing code. So you lose the optimization

The same problem already exists with content-visibility:auto, which should also be searchable. I think this is more of an issue with content-visibility in general rather than content-visibility:hidden-matchable.

Also how is content-visibility: hidden-matchable expected to interact with UA features like Reader view? If the content is important enough to allow Finding, should it be included in Reader views?

Reader view sounds similar to Spotlight indexing. So I think hidden-matchable content could also be exposed to Reader.

content-visibility:hidden-matchable should be considered a UA hint for features such as Reader mode, and leave it up to the UA to provide a performant implementation, just as it should for other features.

josepharhar commented 3 years ago

For concerns about the meaning of visibility of hidden-matchable, here is the intention:

auto: Content is shown to the user.

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.

hidden: Content is in the DOM but is not part of the current view. The only reason it's in the DOM is for caching, offscreen style/layout measurement, or developer convenience.

chrishtr commented 3 years ago

Responding to this comment also:

smfr: Second, anybody who wrote browser code knows you have to think about is content hidden by style, hide from APIs not just visually. display:none does, visibility-hidden sometimes does. Now we have 2 more and I'm uncomfortable adding more variations to is this content available in this scenario

One additional point: my understanding from offline conversations with @smfr is that the discomfort mentioned above is not about implementation complexity. It's about what 'matchable' means in contexts like reader modes, and whether that is a complicated mental model for developers.

fantasai commented 3 years ago

My concerns here are twofold:

css-meeting-bot commented 3 years ago

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/w3c/csswg-drafts/issues/5595
<dael> Rossen_: This issue can take a lot of time. Let's try to spend no more than 10 minutes on this.
<dael> jarhar: Hello everyone. Proposed content-visibility: hidden-matchable property. I added responses on GH to the questions from last time. Wanted to know if there are additional issues and if responses on GH suffice
<Rossen_> ack fantasai
<dael> fantasai: Once concern is if the control should be in css or in markup. Might be good to ask TAG about that.
<dael> fantasai: Details about this the main question is what operations can and can't trigger matching
<tantek> +1 to fantasai's concern, "matchability" feels like an expression of more semantically relevant content and thus may belong more in markup rather than in styling.
<dael> smfr: I think chris's last comment is a good summary of my discomfort. I think TAG feedback would be good. There are features in UAs that vary and this prop has impact on those features. TAG level discussion would be great
<fantasai> s/Details about this the main question is/Other than that, main question is defining details of/
<dael> Rossen_: I'm scrolling through open issues. I see the match event open from jarhar. Is there another active one with TAG?
<dael> jarhar: I believe I do have a TAG review open.
<Rossen_> https://github.com/w3ctag/design-reviews/issues/511
<dael> jarhar: Issue #511 on TAG
<dael> Rossen_: I believe that's scheduled to discuss during TAG F2F in a couple weeks
<dael> chrishtr: and the concern from smfr has not been yet discussed in TAG correct?
<dael> jarhar: Not that I know of
<dael> Rossen_: We have this issue crosslinked to TAG review. As the review with TAG we'll have the CSS issue as well for more context
<tantek> agreed with the reader-mode and screenreader semantics concerns comments in the issue
<dael> Rossen_: What I'm hearing right now is a pause on this issue until we have TAG review
<dael> Rossen_: Then bring it back here
<dael> Rossen_: Also heard concerns from Sam. That's the summary. Is that fair?
<dael> chrishtr: smfr you said you have discomfort. I guess not swayed by our arguemnts. But if TAG doesn't think it's a big problem you're okay?
<dael> smfr: If TAG is okay I'm okay. For example I got pinged by devs about what are a11y for hidden-matchable. There is ambig around a11y and reader mode. Prefer to resolve but understand why it exists
<dael> chrishtr: It's potential for dev confusion?
<dael> smfr: Dev and user. They ctrl f in reader mode but spotlight doesn't find it and that's confusing
<dael> chrishtr: So we'll take it to TAG
<tantek> +1 smfr
<dael> chrishtr: Your comments, fantasai, are good to consider. We shoudl work that out once we have consensus on smfr's issue
<jensimmons> We definitely don't want to create new CSS where the a11y best-practice is confusing and unknown. There should be calrity.
<Rossen_> q?
<jensimmons> *clarity
<dael> Rossen_: Cool. With that let's move forward
josepharhar commented 3 years ago

Regarding this point raised in the CSSWG discussion: "fantasai: Once concern is if the control should be in css or in markup. Might be good to ask TAG about that." We couldn't find clear guidance for whether accessibility features need to be in HTML markup or not. @alice, any thoughts as an expert?

chrishtr commented 3 years ago

The TAG review has finished and they are satisfied. They didn't raise any concerns about the points @josepharhar raised in this comment, so I think all of the points raised at the CSSWG meeting two weeks ago have been addressed satisfactorily. I think this should be enough to resolve on this new feature. Adding agenda+.

css-meeting-bot commented 3 years ago

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

The full IRC log of that discussion <Rossen_> Topic: [css-contain-2] Proposal: content-visibility: hidden-matchable
<Rossen_> github: https://github.com/w3c/csswg-drafts/issues/5595
<Rossen_> q?
<emilio> q+
<myles> jarhar: content-visibility: hidden-matchable allows the UA to search for content inside the content, for like find-in-page, which will fire an event before the browser scrolls, which allows you to report a match before the browser does. There was a TAG review. We brought up reader mode, a11y, and css property vs html attribute. The TAG review has been approved. Looking forward to the next steps
<smfr> q+
<myles> emilio: I still feel like ... this allows the page to show content in response to ... putting this property on an element interacts with beforematch which allows you to show the content, and the page needs to a handshake with the browser, where the browser fires an event, and asynchronously will restart the search after the next runloop .... I haven't thought deeply about alternative solutions to this, but it sounds like complex, hard-to-get-right
<myles> solution
<myles> emilio: that's my main concern.
<myles> emilio: I'm not sure how people are going to use this.
<Rossen_> ack emilio
<fremy> q+
<myles> emilio: ideally, i think the UA could show the content instead, but that's hard with it being a CSS property. It being an attribute could maybe allow this, but it restricts how authors can hide the content.
<chrishtr> q+
<tantek> +1 emilio
<Rossen_> ack smfr
<myles> smfr: I just wanted to reiterate what I said in the past. I don't like how we're adding yet another state to the whole display:none content-visible visibilty:hidden matrix. Will add complication in the future. I agree with emilio about the beforematch algorithm is complicated and error-prone. I would prefer the UA is the one to reveal the content.
<myles> smfr: I still think that the fact that UAs that have reader mode basically mostly undoes the optimization that is content-visibility:hidden-matchable is unfortunate. I'm not sure anyone in TAG was representing UAs that have reader mode and would be impacted by that
<myles> Rossen_: we've been shipping reader mode for quite some time
<tantek> +1 strong agreement with smfr. the complexity this adds to the author model (display:none, visibility:hidden, etc.) makes a bad thing worse.
<Rossen_> q?
<myles> smfr: In order to get reader mode correct you have to resolve styles and layout inside content-visiblity:hidden-matchabe, which defeats the optimization wehre the browser can skip layout. So if your UA needs to look through the page content to determine if there is readerable content, itw ould have to do almost all the work you would have to do if you had the real content. So it's unfortunate we've designed a feature that has that performance trap.
<myles> Performance will not be portable between implementations.
<bkardell_> q+
<myles> Rossen_: You're under the assumption that reader mode won't take advantage of content-visbility:hidden-matchable the way the regular presentation in non-reader mode would do it. I'm not sure how all reader mode implementations are done.
<Rossen_> ack fremy
<myles> fremy: My impression of the use case, let's say you have a book or a long word document, you already know the text on each page, but you don't want to lay out the whole book before the user can see the first page. So you'll put each page in a div, and you want the user to search through the book, and so if the user agent finds some text on page 30, the UA goes to page 30 and says to the website, i'm about to display page 30, please re-lay-out
<myles> fremy: I don't see any other way you can do that optimization. If you were to hook up directly into the browser UI... when i'm first loading the webpage, don't do a whole layout, but when you search on page 30, the browser really needs page 30. Before the browser actually scrolls to page 30.
<myles> fremy: If you have reader mode, it can just stop doing layout eventually... like if you have already 10 pages, just stop laying out, and if the user scrolls, then continue. Or you could skip dirty page of the book and do the layout later. If i have a book, I shoudl be able to say "layout just the pages I need, but search through the entire book"
<smfr> q+
<bkardell_> q-
<Rossen_> ack chrishtr
<tantek> trying to read https://github.com/w3ctag/design-reviews/issues/511 to understand why it was considered acceptable to consider this as a CSS property (seem very much tied to content semantics)
<myles> chrishtr: it's not hard for sites to implement against this feature. We've found the opposite with experiments in partners. These are sections of the UI int he page that are already there and there are already a click handler that shows the hidden section. So the click handler is registered against another event and that's all you do
<myles> chrishtr: All these points about reader mode were discussed multiple times in previous CSSWG meetings. We all agreed we would defer to the upcoming TAG review for them to weigh in on it.
<myles> chrishtr: There are no new arguments here. I am expressing frustration.
<tantek> +1 chrishtr, this is my recollection also
<myles> Rossen_: I appreciate, the function of the TAG is not to make decisions on behalf of CSSWG. CSSWG is the venue for this. it's up to us, not hte TAG
<myles> Rossen_: From architectural poitn of view, it makes sense.
<tantek> +1 myles, we have these issues AND there should be a TAG review
<tantek> q+
<Rossen_> ack smfr
<tantek> q++ emilio
<tantek> qq+ emilio
<tantek> q- +
<tantek> q- later
<myles> smfr: Clarification in response to fremy: find has to resolve styles and do some amount of layout to determine if something should be shown. It will not show things that are 1px tall, not show display:none. So when you have hidden-matchable stuff ... <missed>
<myles> smfr: the problem with reader is detection, not display. we show a badge to let the user opt-in to reader.
<Rossen_> ack emilio
<Zakim> emilio, you wanted to react to smfr
<Rossen_> ack emilio
<myles> emilio: regarding complexity: the feature gets disabled once the page happens to not show the element in time. Because that's racey. Not only racey with loading, but other user actions. If the user hides by clicking on the icon in the next event loop turn, the page will not be able to show anything, or find again, ever.
<myles> emilio: There are other tasks that shows the element, the find process is ... you cannot use the feature any more. which is kinda weird
<myles> Rossen_: do we have an issue on this
<myles> emilio: I raised it on the HTML spec issue. This issue is spread around so much, i don't even know where I ....
<myles> emilio: I don't want to formally object, because I don't have a better solution that addresses all the features, but I don't want to be unconstructive. But ....
<fremy> q+
<myles> chrishtr: Can we move forward and work through these issues?
<myles> Rossen_: many issues.
<myles> chrishtr: Can we just resolve that we'll generally add the features and work on the details later
<myles> emilio: the details are important.
<tantek> I would object to starting the work without considering an attribute instead
<tantek> and I think the TAG neglected that part of the review
<tantek> q?
<myles> Rossen_: the expectation is that we're resolving on starting the work, not ending the work. I heard 3 or 4 major issues that people want to put forward for this feature. I didn't hear a major objection that says "the feature doesn't make sense, or belong to CSS" which is what we're trying to identify in order to add this to our charter
<myles> Rossen_: unless we think this doesn't belong to CSS then ....
<myles> tantek: I think it doesn't belong to CSS.
<Rossen_> la
<Rossen_> q
<Rossen_> ack tantek
<myles> tantek: fundamentally this is about the semantics of content. I'm surprised this has gotten this far as a CSS property because this should be in HTML. This is about whether contetn shoudlb e searchable, which is semantic. Meaningful = shows up in searches. I am surprised this even got so far. I read TAG 511, and it's pretty thin on whether it should be a CSS property or an HTML attribute. The TAG didn't come to a good conclusion there. This WG should
<myles> have the purview to question and push back on.
<myles> tantek: The ergonomic issues that smfr and emilio are sufficient to object to starting work, until: 1. it becomes an HTML attribute, and works well with summary and details elements, which is where the use cases would work "despite the fact it's in details, it should be searchable". Once we get that, then i'd be open to re-opening the discussion about the CSS interaction: the visibility model and teh layout. Until that, we are jumping the gun and it
<myles> will be bad
<myles> chrishtr: HTML attributes are already brought up to the TAG. Semantics are mixed between CSS and HTML. Alice, and expert, says there are plenty of other semantics things that are in CSS
<Rossen_> q?
<myles> tantek: The excuse "there are already other things in CSS" is not a good excuse at all. Just because there is some overlap doesn't mean we should continue being sloppy. I have great respect for Alice, though.
<Rossen_> Zakim, close queue
<Zakim> ok, Rossen_, the speaker queue is closed
<myles> chrishtr: There are argumetns in the issue about why it makes sense to be a CSS property. Please respond to those. Please look at the issue and see the arguments I'm making, try to respond to them, and we can have a constructive discsusion
<myles> tantek: I did.
<myles> chrishtr: The TAG did think deeply about this.
<tantek> the text in 511 does not back that up
<myles> Rossen_: Yes we did! We considered the presentation model of this, compared to other ways in CSS to hide and reveal content. We did consider HTML API surface and the event model and how it fits. This was not a lightweight flippant "go ahead we don't want to deal with this" review.
<myles> Rossen_: I appreciate the candor here but this is not how things went there.
<myles> tantek: Your description doesn't match issue 511.
<myles> tantek: There needs to be more discussion there.
<myles> Rossen_: Feel free to add to the tag review additional questions or reopening it if you want to.
<myles> Rossen_: if you believe this doesn't belong to CSS primarily, please reopen.
<tantek> if there's an hour of minutes about that, please point to that. that was not clear at all in 511
<myles> Rossen_: This topic has been discussed for hours before in CSSWG, and 1 hour in TAG, specifically on that topic. We did discuss the entire name computation model for aria and other a11y-related topics and whether it makes sense. it does. We talked about the visula presentation and how contents vs content-visiblity and how it works. If we had display-contents:none with searchable, that would be sort of this feature is describing, similar to the way we
<myles> hide boxes for elements that are represented in HTML and in teh DOM while these elemnts are searchable and machable, with display:contents
<myles> Rossen_: if you're arguing about this not being in CSS, then you're also arguing against a bunch of parts of CSS which have already shipped
<myles> Rossen_: I find it very surprising to hear the fact that you're arguing against a large discussion and reasoning in TAG on the basis, and dismissed it as a "light" discussion. It was not a light discussion. I'm not going to force a resolution though. I will give people 1.5 days to cool off on this issue.
<myles> Rossen_: I'm happy to have this as the opening topic on Thursday when Alan is going to chair. And have the final resolution adopting this as part of CSS charter, and starting work, not ending work, and having this to be formally objected and brought back to the objection counsil for resolution
<tantek> clearly there are many aspects we disagree on
<myles> fremy: smfr, can I talk to you?
<myles> Rossen_: I need to end the meeting. Please don't talk over me. We resume back on thursday afternoon pacific time. Please stay healthy and happy
FremyCompany commented 3 years ago

Off-minutes, I mentioned that it might be possible to skip styling and layout when doing the search, which is something Simon said was bothering him.

The idea would be that the browser can search all the text inside (or more text than usual) inside the hidden-matchable subtree, and fire the event even if it is not 100% sure the match it found will still hold when considering the full layout. In that case, the event fires, the content is revealed, and search is restarted, possibly finding no match in the revealed content. For example, the layout might end up finding that the text had a 1px font-size, and the browser doesn't want to display this matches to the user, then search continue from there down below.

It is an optimization, the browser is still allowed to do layout and styling if it desires to. Basically, the comment was that browsers should maybe be free to have <100% precision as long as it keeps 100% recall (i.e. false positives are allowed, but false negatives are not, or should be pretty rare).

smfr commented 3 years ago

It is an optimization, the browser is still allowed to do layout and styling if it desires to. Basically, the comment was that browsers should maybe be free to have <100% precision as long as it keeps 100% recall (i.e. false positives are allowed, but false negatives are not, or should be pretty rare).

This allows Find to be less expensive. It does not deal with:

FremyCompany commented 3 years ago

hidden-matching adds a new level of ambiguity about what content is "visible"

That's true. I think that's a useful distinction to make though, because I can't find another way to achieve this. Maybe we should work on examples of use cases though, I feel this discussion was not rooted in concrete cases, which tends to yield more questions than answers. Maybe there's something obvious that already would solve this and we didn't notice.

why Find gets special treatment, given the other ways content is exposed by UAs

Making find an unique exception is something I would argue is indeed wrong. In the ideal world, the provisional content would also display in the accessibility tree (even as a place-holder template). In a way, I think we want something that says "this is not visible to the user yet, but it should be searchable/scannable" (and the UA's find feature is only one way to do so). After that, user agents might have bugs, and initially limit this to only search if that is the only thing they have budget for, but I feel this would be wrong indeed.

What are other examples of things you believe would be useful to have this type of hidden content exposed to?

Reader detection can't use the same level of more efficient but less precise content traversal without making it appear buggy to users.

Probably true. But the question is "does the Reader mode works better today"? Right now, I assume that the Reader mode doesn't see hidden content at all. In this case, we are exposing new content to the Reader mode that it should see, possibly with reduced functionality. But if it was display:none you wouldn't see this content at all, which arguably is a worse kind of buggy. I guess we should do a before/after. I am not familiar with how reader mode is implemented in each browser.


In the spirit of trying to talk about use cases, here is the one that got all of this started, mobile wikipedia:

![image](https://user-images.githubusercontent.com/364405/107413122-ab266100-6b10-11eb-9e2b-f3e9fd15b810.png) ![image](https://user-images.githubusercontent.com/364405/107413163-b9747d00-6b10-11eb-9603-8f9419347221.png)

This is done using the following piece of CSS:

image

As things stand today, the content in the sections is:

In this use case, I don't see how things would be worse if there was a toggle to say that "the content inside that display:none element should be searchable. Making this text searchable is not very complicated for the website, because simply removing the display:none fixes everything. So if the browser sends an onbeforematch event on the section, it can just add an "expanded-section" class and everything will work as expected.


The second use case I have in my mind is a Word or ePub reader. Usually, this type of document is split into "chunks of content" (like pages, or chapters) which can be layouted independently. But there is so much content that layout out everything would probably cause a visible slow down. So the trick is to load content on-demand when it becomes scrolled to. The issue is that this prevents searching this content (and, for accessible users, it prevents displaying the list of headings, etc...).

image

Here again, each of these chunks can be marked as "currently-hidden but should-be-scannable". Then when you search through the book, you find that a word you are looking for is located on page 356. So the browser sends an event asking for page 356 to be converted from "currently-hidden but should-be-scannable" to "visible". Removing display:none might be sufficient to do that, but some other processing might be necessary to achieve this (maybe some work is performed only on demand, like for instance rehydrating visualization components like interactive graphs, or maybe some of the fine-grained styling requires additional data; if that rehydration is done with a framework, it might end up shaking the dom, which means that the browser-highlighted span might get shaken up, which is why the onbeforematch event is useful, because it enables the author to say when the element is ready for search and highlighting).

In this case, I don't think it is possible not to set display:none on the many pages of the book if you want good performance. A reader view should probably add this content, but load it as it comes into view. This might require additional development from the reader view, but this seems reasonable to me. In many cases though, maybe the reader mode can just ignore the "hidden but searchable" mark?

Maybe also there should be a note or author requirement in the spec saying that using this attribute should not be done on the first chunk of content, so that the browser can apply proper heuristics wihtout having to consider "currently-hidden but should-be-scannable" content more than as chunks of text.


Are there other use cases that should be considered?

chrishtr commented 3 years ago

why Find gets special treatment, given the other ways content is exposed by UAs

Making find an unique exception is something I would argue is indeed wrong. In the ideal world, the provisional content would also display in the accessibility tree (even as a place-holder template). In a way, I think we want something that says "this is not visible to the user yet, but it should be searchable/scannable" (and the UA's find feature is only one way to do so). After that, user agents might have bugs, and initially limit this to only search if that is the only thing they have budget for, but I feel this would be wrong indeed.

We've already resolved not to make find special and expose this feature through all appropriate algorithms.

chrishtr commented 3 years ago

hidden-matching adds a new level of ambiguity about what content is "visible"

Maybe I'm being pedantic, but I don't think "ambiguity" is the right word here. There is definitely a new state to consider, but it's not ambiguous what it means.

That's true. I think that's a useful distinction to make though, because I can't find another way to achieve this. Maybe we should work on examples of use cases though, I feel this discussion was not rooted in concrete cases, which tends to yield more questions than answers. Maybe there's something obvious that already would solve this and we didn't notice.

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.

FremyCompany commented 3 years ago

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 commented 3 years ago

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 commented 3 years ago

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 commented 3 years ago

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:

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 commented 3 years ago

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:

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 commented 3 years ago

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 commented 3 years ago

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 commented 3 years ago

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:

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 commented 3 years ago

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 commented 3 years ago

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 commented 3 years ago

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 commented 3 years ago

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

smaug---- 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? 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.