├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── contain-intrinsic-size.html ├── explainers ├── auto-expanding-details-explainer.md ├── beforematch-spec-draft.md ├── beforematch.md ├── contain-intrinsic-size.md ├── content-visibility-hidden-matchable.md ├── content-visibility.md ├── hidden-content-explainer.md ├── images │ └── beforematch.gif ├── isvisible.md └── update-rendering.md ├── find-in-page-compat.md ├── index.html ├── privacy-assessments ├── auto-expanding-details-privacy.md ├── beforematch.md ├── contain-intrinsic-size.md └── isvisible.md ├── resources └── find-in-page │ ├── display_types_chrome.png │ ├── display_types_firefox.png │ ├── display_types_safari.png │ ├── occlusion_chrome.png │ ├── occlusion_firefox.png │ ├── occlusion_safari.png │ ├── overflow_auto_chrome.png │ ├── overflow_auto_firefox.png │ ├── overflow_auto_safari.png │ ├── overflow_hidden_chrome.png │ ├── overflow_hidden_firefox.png │ ├── overflow_hidden_safari.png │ ├── search-incremental.html │ ├── visibility_chrome.png │ ├── visibility_firefox.png │ └── visibility_safari.png ├── sample-code ├── collapsed-sections.html ├── contain-intrinsic-size-examples.html ├── css-collapsed-sections.html └── tabbed-ui.html └── w3c.json /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | All documentation, code and communication under this repository are covered by the [W3C Code of Ethics and Professional Conduct](https://www.w3.org/Consortium/cepc/). 4 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Web Platform Incubator Community Group 2 | 3 | This repository is being used for work in the W3C Web Platform Incubator Community Group, governed by the [W3C Community License 4 | Agreement (CLA)](http://www.w3.org/community/about/agreements/cla/). To make substantive contributions, 5 | you must join the CG. 6 | 7 | If you are not the sole contributor to a contribution (pull request), please identify all 8 | contributors in the pull request comment. 9 | 10 | To add a contributor (other than yourself, that's automatic), mark them one per line as follows: 11 | 12 | ``` 13 | +@github_username 14 | ``` 15 | 16 | If you added a contributor by mistake, you can remove them in a comment with: 17 | 18 | ``` 19 | -@github_username 20 | ``` 21 | 22 | If you are making a pull request on behalf of someone else but you had no part in designing the 23 | feature, you can remove yourself with the above syntax. 24 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | All Reports in this Repository are licensed by Contributors 2 | under the 3 | [W3C Software and Document License](http://www.w3.org/Consortium/Legal/2015/copyright-software-and-document). 4 | 5 | Contributions to Specifications are made under the 6 | [W3C CLA](https://www.w3.org/community/about/agreements/cla/). 7 | 8 | Contributions to Test Suites are made under the 9 | [W3C 3-clause BSD License](https://www.w3.org/Consortium/Legal/2008/03-bsd-license.html) 10 | 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Important Note 2 | 3 | The work here has all been adopted in CSSWG or WHATWG as needed. This repo is 4 | archived for the historical record. 5 | 6 | ## Display locking 7 | 8 |
9 | Note that this feature should not be confused with the 10 | Screen Wake Lock API. 11 |
12 | 13 | ## Introduction 14 | 15 | Display Locking is an umbrella term of related features designed primarily to 16 | allow developers to increase performance of their sites. In addition, some of 17 | the features in the display locking project enable site behaviors that were not 18 | previously easy to accomplish (e.g. searchability in collapsed sections). 19 | 20 | This document provides an overview of the features under the Display Locking 21 | projects with links that provide additional information. 22 | 23 | ## Features 24 | 25 | ### `content-visibility` 26 | 27 | #### Summary 28 | 29 | `content-visibility` is a CSS property designed to allow developers and browsers 30 | to easily scale to large amount of content and control when rendering work 31 | happens. 32 | 33 | #### Status 34 | 35 | The feature has been accepted by the CSS Working Group, and is a part of the 36 | [css-contain-2]() module. 37 | 38 | The feature is implemented in Chromium M85. 39 | 40 | #### Additional information 41 | 42 | * [spec](https://www.w3.org/TR/css-contain-2/#content-visibility) 43 | * [explainer](https://github.com/WICG/display-locking/blob/master/explainers/content-visibility.md) 44 | * [TAG review](https://github.com/w3ctag/design-reviews/issues/306) 45 | * [article](web.dev/content-visibility) 46 | 47 | ### `hidden=until-found` and searchable `details` elements. 48 | 49 | #### Summary 50 | 51 | Leveraging `content-visibility`, we can also support searchable hidden content. 52 | We are applying this automatically to details elements, to make the contents 53 | of a details element available to find-in-page. 54 | 55 | We are also adding a new attribute `hidden=until-found` to allow developers to create 56 | hidden, but searchable, content. 57 | 58 | #### Status 59 | 60 | The searchable `details` element feature is available in Chromium behind the 61 | `--enable-blink-features=AutoExpandDetailsElement` flag. 62 | 63 | * [spec PR](https://github.com/whatwg/html/pull/6466) 64 | 65 | `hidden=until-found` is currently being implemented. 66 | 67 | ### `contain-intrinsic-size` 68 | 69 | #### Summary 70 | 71 | `contain-intrinsic-size` is a CSS property that allows the developer to specify 72 | an intrinsic size to use when size-containment is specified. This enables the 73 | developers to specify “placeholder size” on content which is meant to be sized 74 | by intrinsic sizing, but has size containment applied to it. 75 | 76 | #### Status 77 | 78 | The feature is currently implemented and shipped in Chromium M83. 79 | 80 | #### Additional information 81 | 82 | * [spec](https://www.w3.org/TR/css-sizing-4/#intrinsic-size-override) 83 | * [explainer](https://github.com/WICG/display-locking/blob/master/explainers/contain-intrinsic-size.md) 84 | * [TAG review](https://github.com/w3ctag/design-reviews/issues/437) 85 | * [privacy assessment](https://github.com/WICG/display-locking/blob/master/privacy-assessments/contain-intrinsic-size.md) 86 | 87 | 88 | ### `renderpriority` attribute 89 | 90 | #### Summary 91 | 92 | `renderpriority` ([placeholder name](https://github.com/WICG/display-locking/issues/200)) 93 | is an HTML attribute that indicates a request from the developer to keep the element 94 | and its subtree updated with a certain priority. The User Agent is then responsible for 95 | scheduling the updates using the specified priority as a strong hint for prioritizing 96 | the work. 97 | 98 | #### Status 99 | 100 | This feature is in active development. 101 | 102 | * [discussion & open questions](https://github.com/WICG/display-locking/blob/master/explainers/update-rendering.md) 103 | * [issues](https://github.com/WICG/display-locking/labels/updateRendering) 104 | 105 | ## Disclaimer 106 | 107 | As the proposed features evolve, several competing API shapes might be 108 | considered at the same time, the decisions on particular behaviors might not be 109 | finalized, and some documentation may be out of date. 110 | 111 | This document was last updated on May 28, 2020. 112 | -------------------------------------------------------------------------------- /contain-intrinsic-size.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /explainers/auto-expanding-details-explainer.md: -------------------------------------------------------------------------------- 1 | Auto-expanding `
` explainer 2 | 3 | # The problem 4 | 5 | Today, users can’t search for content inside `
` elements when they are closed. If the user wants to search the page for content inside `
` elements with find-in-page, then they have to manually expand every `
` element in the page before they use find-in-page. 6 | 7 | # The solution 8 | 9 | The solution is to make the hidden contents of closed details elements searchable by find-in-page and have the browser automatically open them when trying to scroll to their hidden contents. 10 | 11 | In addition to find-in-page, this feature should also work for Element fragments (navigating to a hash with an element id) and [ScrollToTextFragment](https://github.com/WICG/scroll-to-text-fragment/issues/173) in order to make content hidden inside `
` elements more findable and shareable. 12 | 13 | This feature has already been [added to the HTML spec](https://github.com/whatwg/html/pull/6466). 14 | 15 | # Privacy concerns 16 | 17 | A security and privacy self review can be found [here](/privacy-assessments/auto-expanding-details-privacy.md). TL;DR this feature does not reveal any new sensitive information to the page due to the existing `scroll` events and `:target` pseudo selector. 18 | -------------------------------------------------------------------------------- /explainers/beforematch-spec-draft.md: -------------------------------------------------------------------------------- 1 | # beforematch event 2 | 3 | _These changes will likely go into the 4 | [find-in-page](https://html.spec.whatwg.org/multipage/interaction.html#find-in-page) 5 | section of the HTML spec_ 6 | 7 | When a new _active match_ is set, either by advancing through the match list or 8 | due to a new find-in-page request, a `beforematch` event is fired on a node 9 | identified by the _active match_'s [range 10 | start](https://dom.spec.whatwg.org/#concept-range-start). This process follows 11 | the following algorithm: 12 | 13 | 1. Identify the candidate match which will become the new _active match_. The 14 | _active match_'s DOM range must not be 15 | [collapsed](https://dom.spec.whatwg.org/#range-collapsed). 16 | 17 | 2. At the next rendering opportunity, specifically step 12 "run the animation 18 | frame callbacks" of 19 | [update-the-rendering](https://html.spec.whatwg.org/multipage/webappapis.html#update-the-rendering): 20 | 21 | 2.1. If the DOM range representing the _active match_ has been collapsed, 22 | start the search over again starting at this collapsed range. 23 | 24 | 2.2. Let "_matchable ancestor_" be the nearest flat-tree ancestor element of 25 | the beginning of the DOM range representing the _active match_ which has 26 | the content-visibility: hidden-matchable property. 27 | 28 | 2.3. If the beforematch event has been disabled or there is no _matchable 29 | ancestor_, run 30 | [scroll into view](https://drafts.csswg.org/cssom-view/#scroll-an-element-into-view) 31 | on the _active match_ and end the algorithm. 32 | 33 | 2.4. Fire the beforematch event on the _matchable ancestor_. 34 | 35 | 2.5. Signal a need for another run of update-the-rendering. 36 | 37 | 3. At the next rendering opportunity (the _next_ Step 12 of 38 | [update-the-rendering](https://html.spec.whatwg.org/#update-the-rendering)): 39 | 40 | 3.1. Disable the beforematch event for the remaining lifetime of the 41 | document and start the search over again starting at the end of the 42 | _active match_'s DOM range if any of the following conditions are true: 43 | - The DOM range representing the _active match_ has been collapsed. 44 | - The _active match_ has the `content-visibility: hidden-matchable` or 45 | `content-visibility: hidden` in any ancestors. 46 | - The _active match_ has the `display: none` property in any ancestors. 47 | - The _active match_'s `visibility` property is not `visible` in any 48 | ancestors. 49 | 50 | 3.2. Run 51 | [scroll into view](https://drafts.csswg.org/cssom-view/#scroll-an-element-into-view) 52 | on the _active match_. 53 | 54 | # content-visibility: hidden-matchable 55 | 56 | _These changes will likely go into the 57 | [css-contain-2](https://www.w3.org/TR/css-contain-2/#content-visibility) 58 | module_. 59 | 60 | 'hidden-matchable': 61 | 62 | This value behaves very similarly to 'hidden'. 63 | That is, the element [skips its contents](https://www.w3.org/TR/css-contain-2/#skips-its-contents). 64 | 65 | The skipped contents must not be accessible to user-agent features such as 66 | tab-order navigation, nor be selectable or focusable. 67 | 68 | However, unlike 'hidden', the skipped contents must be accessible to the 69 | find-in-page algorithm in order to allow the `beforematch` event to fire. 70 | (TODO: reference the find-in-page beforematch spec) 71 | -------------------------------------------------------------------------------- /explainers/beforematch.md: -------------------------------------------------------------------------------- 1 | # The `beforematch` event 2 | 3 | This file has been replaced by 4 | [hidden-content-explainer.md](hidden-content-explainer.md) 5 | -------------------------------------------------------------------------------- /explainers/contain-intrinsic-size.md: -------------------------------------------------------------------------------- 1 | # The `contain-intrinsic-size` CSS property 2 | 3 | `contain-intrinsic-size` represents the intrinsic layout sizing of a DOM 4 | subtree, which is applied when `contain: size` is present. This feature extends 5 | size containment by allowing the developer to specify an intrinsic size other 6 | than 0x0, which is a common result of size containment. 7 | 8 | Intrinsic sizing is an input to layout of ancestors, and is an important input 9 | to the layout constraint algorithms of the web. As one example, if an element 10 | has [`width: max-content`](https://drafts.csswg.org/css-sizing-3/#valdef-width-max-content) 11 | CSS on it, then it is sized to the [max-content inline size](https://drafts.csswg.org/css-sizing-3/#max-content-inline-size), 12 | which is the maximum intrinsic width of elements in the subtree. Currently, such 13 | intrinsic sizes are determined implicitly from other factors [2], and the other 14 | factors have additional undesirable layout side-effects. 15 | 16 | Under size containment, the intrinsic size is determined without consideration 17 | of element's children. This means that typically the intrinsic size will be 0x0, 18 | with some exceptions such as `display: grid` which also considers its tracks 19 | when determining the intrinsic size. 20 | 21 | The `contain-intrinsic-size` property extends size containment by allowing the 22 | developer to specify the size directly. In that sense, one motivation for the 23 | `contain-intrinsic-size` property could be 24 | [explaining](https://extensiblewebmanifesto.org) these algorithms. One practical 25 | application could be its use in testing their behavior. 26 | 27 | ## Use cases 28 | 29 | (See also the [main 30 | explainer](https://github.com/WICG/display-locking/blob/master/README.md) for 31 | display-locking for more motivating examples.) 32 | 33 | ### Virtualization 34 | 35 | Adding `contain: size layout; contain-intrinsic-size: XXpx YYpx` to blocks of DOM that 36 | are known to be of offscreen or known-invisible allows the web browser to avoid 37 | rendering cost for this offscreen content, while minimizing impact of the layout 38 | of on-screen content. This allows the web author to control 39 | [virtualization](https://github.com/chrishtr/rendering/blob/master/virtualization.md) 40 | of rendering costs, in order to improve web site performance. 41 | 42 | ### Async rendering lifecycle 43 | 44 | Another motivating use-case for `contain-intrinsic-size` is to use it in cases when the 45 | layout of a subtree is *not available*. The layout can be unavailable in 46 | situations such as: 47 | * The subtree is not yet fully loaded from the network, or rendered into DOM 48 | * a custom element, framework or the User Agent has temporarily skipped rendering 49 | for the subtree as an optimization 50 | * content-visibility property enforces size containment while not rendering the 51 | subtree. 52 | 53 | Note that these three cases can be seen as the same use case, if the concept of 54 | "rendering" is extended to include asynchronous, scheduled factors such as the 55 | network, a DOM rendering framework [1], a [custom 56 | element](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements), 57 | dynamic replaced elements such as embedded SVG documents, images and videos. In 58 | other words, the [rendering event 59 | loop](https://github.com/chrishtr/rendering/blob/master/rendering-event-loop.md) 60 | is only one source of potential asynchrony in an expanded concept of rendering. 61 | 62 | In such cases, the developer may still wish for the element to participate in 63 | the intrinsic sizing aspects of layout, by providing placeholder sizing, because 64 | otherwise there may be an undesirable, jarring [shift of the 65 | layout](https://web.dev/layout-instability-api) of the page as the content 66 | renders. 67 | 68 | ### Examples 69 | 70 | Please take a look at the following 71 | [examples](https://wicg.github.io/display-locking/sample-code/contain-intrinsic-size-examples.html) 72 | with explanations. 73 | -------------------------------------------------------------------------------- /explainers/content-visibility-hidden-matchable.md: -------------------------------------------------------------------------------- 1 | ## content-visibility: hidden-matchable. 2 | 3 | Content visibility hidden matchable is an extension to the `content-visibility` 4 | feature. It adds a new value to the possible set of properties: 5 | * `content-visibility: hidden-matchable`: in this configuration, the content is 6 | hidden from the user (similar to `content-visibility: hidden`), but the 7 | content remains searchable via user-agent find-in-page algorithms. 8 | 9 | Possible use case is Deep links and searchability into pages with hidden content 10 | (example: mobile Wikipedia; scroll-to-text support for collapsed sections) 11 | 12 | 13 | The property applies `contain: style layout size paint`. The element with this 14 | property is invisible to rendering/ hit testing, but is visible to UA algorithms 15 | such as find-in-page. When the match is found, the `beforematch` event will fire, 16 | but the content will not automatically display. If it is the intent of the site 17 | to show the matched content, then beforematch event handler has to make the 18 | content visible. 19 | 20 | ### Examples 21 | 22 | ```html 23 | 28 | 29 |
30 | ... some content goes here ... 31 |
32 | ``` 33 | 34 | Like with `content-visibility: hidden`, the rendering of the subtree is managed 35 | by the developer. However, it allows find-in-page to search for text within the 36 | subtree and fire the activation signal if the active match is found. 37 | 38 | One intended use-case for this configuration is that the subtree is hidden and 39 | "collapsed" (note the absense of `contain-intrinsic-size` which makes size 40 | containment use empty size for intrinsic sizing). This is common when content is 41 | paginated and the developer allows the user to expand certain sections with 42 | button clicks. In the `content-visibility` case the developer may also listen to 43 | the activation event and start rendering the subtree when the event targets the 44 | element in the subtree. This means that find-in-page is able to expand an 45 | otherwise collapsed section when it finds a match. 46 | 47 | Another intended use-case is a developer-managed virtual scroller. 48 | -------------------------------------------------------------------------------- /explainers/content-visibility.md: -------------------------------------------------------------------------------- 1 | ## content-visibility 2 | 3 | `content-visibility` is a CSS property designed to allow developers and browsers 4 | to easily scale to large amount of content and control when rendering 5 | [\[1\]](#foot-notes) work happens. More concretely, the goals is to avoid 6 | rendering and layout measurement work for content not visible to the user. 7 | 8 | The following use-cases motivate this work: 9 | 10 | 1. Fast display of large HTML documents (examples: HTML one-page spec; other long 11 | documents) 12 | 2. Scrollers with a large amount of content, without resorting to virtualization 13 | (examples: Facebook and Twitter feeds, CodeMirror documents) 14 | 3. Measuring layout for content not visible on screen 15 | 4. Optimizing single-page-app transition performance 16 | 17 | ## Summary 18 | 19 | In the below, "invisible to rendering/hit testing" means not drawn or returned 20 | from any hit-testing algorithms in the same sense as `visibility: hidden`, where 21 | the content still conceptually has layout sizes, but the user cannot see or 22 | interact with it. 23 | 24 | Also, "visible to UA algorithms" means that find-in-page, link navigation, etc 25 | can find the element. 26 | 27 | `content-visibility: visible` - default state, subtree is rendered. 28 | 29 | `content-visibility: auto` - avoid rendering cost when offscreen 30 | * Use cases: (1), (3), (5) 31 | * Applies `contain: style layout`, plus `contain: size` when invisible 32 | * Invisible to rendering/hit testing, except when subtree intersects viewport 33 | * Visible to UA algorithms 34 | 35 | `content-visibility: hidden` - hide content, but preserve cached state and still 36 | support style/layout measurement APIs 37 | * Use cases: (4), (5) 38 | * Applies `contain: style layout size` 39 | * Invisible to rendering/hit testing 40 | * Not visible to UA algorithms 41 | 42 | ## Motivation & background 43 | 44 | On the one hand, faster web page loads and interactions directly improve the 45 | user experience of the web. On the other hand, web sites each year grow larger 46 | and more complex than the last, in part because they support more and more use 47 | cases, and contain more information, and the most common UI pattern for the 48 | web is scrolling. This leads to pages with a lot of non-visible (offscreen or 49 | hidden) DOM, and since the DOM presently renders atomically, it inherently 50 | takes more and more time to render on the same machine. 51 | 52 | For these reasons, web developers need ways to reduce loading and rendering time 53 | of web apps that have a lot of non-visible DOM. Two common techniques are to mark 54 | non-visible DOM as "invisible" [\[2\]](#foot-notes), or to use virtualization 55 | [\[3\]](#foot-notes). Browser implementors also want to reduce loading and 56 | rendering time of web apps. Common techniques to do so include adding caching of 57 | rendering state [\[4\]](#foot-notes), and avoiding rendering work 58 | [\[5\]](#foot-notes) for content that is not visible. 59 | 60 | These techniques can work in many cases but have drawbacks and limitations: 61 | 62 | a. [\[2\]](#foot-notes) and [\[3\]](#foot-notes) usually means that such content 63 | is not available to user-agent features, such as find-in-page functionality. 64 | Also, content that is merely placed offscreen may or may not have rendering 65 | cost (it depends on browser heuristics), which makes the technique 66 | unreliable. 67 | 68 | b. Caching intermediate rendering state is [hard 69 | work](https://martinfowler.com/bliki/TwoHardThings.html), and often has 70 | performance limitations and cliffs that are not obvious to developers. 71 | Similarly, relying on the browser to avoid rendering for content that is clipped 72 | out or not visible is sometimes not reliable, as it's hard for the browser to 73 | efficiently detect what content is not visible and does not affect visible 74 | content in any way. 75 | 76 | Previously adopted web APIs, in particular the 77 | [contain](https://developer.mozilla.org/en-US/docs/Web/CSS/contain) and 78 | [will-change](https://developer.mozilla.org/en-US/docs/Web/CSS/will-change) CSS 79 | properties, add ways to specify forms of rendering 80 | [isolation](https://github.com/chrishtr/rendering/blob/master/isolation.md) or 81 | isolation hints, with the intention of them being a mechanism for the web 82 | developer to help the browser optimize rendering for the page. 83 | 84 | While these forms of isolation help, they do not guarantee that isolated content 85 | does not need to be rendered at all. Ideally there would be a way for the 86 | developer to specify that specific parts of the DOM need not be rendered, and 87 | pair that with a guarantee that when later rendered, it would not invalidate 88 | more than a small amount of style, layout or paint in the rest of the document. 89 | 90 | ## Description of proposal 91 | 92 | A new `content-visibility` CSS property is proposed. This property controls 93 | whether DOM subtrees affected by the property are invisible to painting/hit 94 | testing. This is the mechanism by which rendering work can be avoided. Some 95 | values of `content-visibility` allow the user-agent to automatically manage 96 | whether subtrees affected are rendered or not. Other values give the developer 97 | complete control of subtree rendering. The possible values are the following: 98 | 99 | * `content-visibility: visible`: this is the default state, in which this 100 | feature does not affect anything consequential. 101 | * `content-visibility: auto`: this configuration allows the user-agent to 102 | automatically manage whether content is invisible to rendering/hit testing or not. 103 | * `content-visibility: hidden`: this configuration gives the 104 | developer complete control of when the subtree is rendered. Neither the 105 | user-agent nor its features should need to process or render the subtree. 106 | 107 | It is also worth noting that when the element is not rendered, then 108 | `contain: layout style paint size;` is added to its style to ensure that the 109 | subtree content does not affect elements outside of the subtree. 110 | Furthermore, when the element is rendered in the `content-visibility: auto` 111 | configuration (i.e. the user-agent decides to render the element), then 112 | `contain: layout style paint;` applies to the element. 113 | 114 | ## Example usage 115 | 116 | ```html 117 | 123 | 124 |
125 | ... some content goes here ... 126 |
127 | ``` 128 | 129 | The `.locked` element's `content-visibility` configuration lets the user-agent 130 | manage rendering the subtree of the element. Specifically when this element is 131 | near the viewport, the user-agent will begin rendering the element. When the 132 | element moves away from the viewport, it will stop being rendered. 133 | 134 | Recall that when not rendered, the property also applies size containment to the 135 | element. This means that when not rendered, the element will use the specified 136 | `contain-intrinsic-size`, making the element layout as if it had a single block 137 | child with 100px width and 200px height. This ensures that the element still 138 | occupies space when not rendered. At the same time, it lets the element size to 139 | its true contents when the subtree is rendered (since size containment no longer 140 | applies), thus removing the concern that estimates like 100x200 are sometimes 141 | inaccurate (which would otherwise result in displaying incorrect layout for 142 | on-screen content). 143 | 144 | One intended use-case for this configuration is to make it easy for developers to 145 | avoid rendering work for off-screen content. 146 | 147 | A second use-case is to support simple scroll virtualization. 148 | 149 | ```html 150 | 156 | 157 |
158 | ... some content goes here ... 159 |
160 | ``` 161 | 162 | In this case, the rendering of the subtree is managed by the developer only. 163 | This means that if script does not modify the value, the element's subtree will 164 | remain unrendered, and it will use the `contain-intrinsic-size` input when 165 | deciding how to size the element. However, the developer can still call methods such 166 | as `getBoundingClientRect()` to query and measure layout for the invisible content. 167 | 168 | One intended use-case for this mode are measuring layout geomery for content not displayed. 169 | 170 | A second use-case is preserving rendering state for [single-page app](https://en.wikipedia.org/wiki/Single-page_application) 171 | content that is not currently visible to the user, but may be displayed again 172 | soon via user interaction. 173 | 174 | ## Alternatives considered 175 | 176 | The `display: none` CSS property causes content subtrees not to render. However, 177 | there is no mechanism for user-agent features to cause these subtrees to render. 178 | Additionally, the cost of hiding and showing content cannot be eliminated since 179 | `display: none` does not preserve the layout state of the subtree. 180 | 181 | `visibility: hidden` causes subtrees to not paint, but they still need style and 182 | layout, as the subtree takes up layout space and descendants may be `visibility: 183 | visible`. (It's also possible for descendants to override visibility, creating 184 | another complication.) Second, there is no mechanism for user-agent features to cause 185 | subtrees to render. Note that with sufficient containment and intersection 186 | observer, the functionality provided by `content-visibility` may be mimicked. 187 | This relies on more browser heuristics to ensure contained invisible content is 188 | cheap -- `content-visibility` is a stronger signal to the user-agent that work 189 | should be skipped. 190 | 191 | Similar to `visibility: hidden`, `contain: strict` allows the browser to 192 | automatically detect subtrees that are definitely offscreen, and therefore that 193 | don't need to be rendered. However, `contain: strict` is not flexible enough to 194 | allow for responsive design layouts that grow elements to fit their content. To 195 | work around this, content could be marked as `contain: strict` when offscreen 196 | and then some other value when on-screen (this is similar to `content-visibility`). 197 | Second, `contain: strict` may or may not result in rendering work, depending on 198 | whether the browser detects the content is actually offscreen. Third, it does 199 | not support user-agent features in cases when it is not actually rendered to the 200 | user in the current application view. 201 | 202 | 203 | 204 | [1]: Meaning, the [rendering 205 | part](https://github.com/chrishtr/rendering/blob/master/rendering-event-loop.md) 206 | of the browser event loop. 207 | 208 | [2]: Examples: placing `display:none` CSS on DOM subtrees, or by placing content 209 | far offscreen via tricks like `margin-left: -10000px` 210 | 211 | [3]: In this context, virtualization means representing content outside of the 212 | DOM, and inserting it into the DOM only when visible. This is most commonly used 213 | for virtual or infinite scrollers. 214 | 215 | [4]: Examples: caching the computed style of DOM elements, the output of text / 216 | block layout, and display list output of paint. 217 | 218 | [5]: Examples: detecting elements that are clipped out by ancestors, or not 219 | visible in the viewport, and avoiding some or most rendering for such content. 220 | 221 | 222 | -------------------------------------------------------------------------------- /explainers/hidden-content-explainer.md: -------------------------------------------------------------------------------- 1 | # The `hidden=until-found` HTML attribute and the `beforematch` event 2 | 3 | ## Summary (TL;DR) 4 | 5 | This is an explainer for two coupled features: 6 | 7 | 1. The `hidden=until-found` HTML attribute. This adds `until-found` 8 | as a new value for the existing `hidden` HTML boolean attribute. When this 9 | value is used, the browser 10 | will make the affected content searchable by user-agent algorithms such as 11 | find-in-page. When the user-agent wants to scroll this hidden content into view, 12 | the it will automatically remove the `hidden` attribute from the element 13 | to reveal it. 14 | 15 | 2. The `beforematch` event is fired before the browser removes the 16 | `hidden=until-found` attribute to allow the page to change other state in 17 | conjunction with the removal of the `hidden` attribute and the browser 18 | scrolling. 19 | 20 | The browser should fire `beforematch` on the `hidden=until-found` element and 21 | then remove the `hidden=until-found` attribute at render timing for these cases: 22 | * There is a new find-in-page 23 | [active match](https://html.spec.whatwg.org/multipage/interaction.html#fip-matches) 24 | which is located in a subtree of an element with the `hidden=until-found` attribute. 25 | * There is a [scroll-to-text](https://github.com/WICG/ScrollToTextFragment) 26 | navigation (`example.com/#:~:text=foo`), where the target text is located 27 | inside a `hidden=until-found` element. 28 | * There is an element fragment navigation or change (`example.com/#foo`), 29 | where the target is an element in the subtree of a `hidden=until-found` element. 30 | * [`window.find`](https://developer.mozilla.org/en-US/docs/Web/API/Window/find) 31 | found a text match located inside a `hidden=until-found` 32 | element. `window.find` won't be supported until [`window.find` gets 33 | specced](https://github.com/whatwg/html/issues/3539). 34 | 35 | If the matching text spans multiple `hidden=until-found` siblings, only the 36 | first `hidden=until-found` will be removed and the `beforematch` event will only 37 | be fired on the first one. 38 | 39 | If there are multiple `hidden=until-found` elements in the flat tree ancestor 40 | chain of the target element to reveal, then all of them will be removed and all 41 | of them will receive the `beforematch` event. 42 | 43 | ## Motivation 44 | 45 | With the evolution of the web, there are always new and interesting ways that 46 | developers choose to organize the information on their pages. Some of these 47 | approaches (e.g. the common case of text scrolling), lend themselves naturally to 48 | user-agent features like find-in-page. This is not an accident, since 49 | find-in-page was designed with common use-cases in mind. 50 | 51 | However, other approaches like collapsed sections of text do not work well with 52 | user-agent features since the page does not get any indication that the user 53 | initiated a find-in-page request, or scroll-to-text navigation. 54 | 55 | `hidden=until-found` and the `beforematch` event is a step in the direction that 56 | allows developers to leverage information that the user-agent already has to 57 | make these search and navigation experiences great. Specifically, it makes it 58 | possible to process text for find-in-page match in sections that are not 59 | visible. In turn, `hidden=until-found` sections will be made visible, allowing 60 | the user to use find-in-page or link navigation to find content in collapsed 61 | sections -- something that is not currently possible. 62 | 63 | ## Primary use case: collapsed searchable sections 64 | ```html 65 | 66 | 67 | 68 | 86 | 87 | Please explore the following sections: 88 | 92 | 93 | 97 | 98 | 102 | 103 | 123 | ``` 124 | 125 | ![hiddenuntilfound](images/beforematch.gif) 126 | 127 | As you can see in the above gif, the flow of the use case is as follows: 128 | 1. The page loads and all subsections are hidden with only the headings visible, 129 | similar to a `
` element. 130 | 2. User searches for hidden text, such as "lorem ipsum". 131 | 3. The browser removes the `hidden=until-found` attribute on the element 132 | containing the text "lorem ipsum". 133 | 4. User may click on the section to collapse it again. 134 | 135 | In this example, most of the content of the page is hidden in collapsed 136 | sections. It uses the `hidden=until-found` HTML attribute to hide the content 137 | while letting it be searchable by find-in-page. When a match is found, the 138 | browser automatically expands the section by removing the `hidden` attribute. 139 | 140 | Note that the net effect of this is that the user is able to find matches in 141 | collapsed sections which are automatically expanded. 142 | 143 | The same effect occurs when scroll-to-text navigation targets text in a hidden 144 | section. For instance, navigating to `example.com/page.html#:~:text=lorem` would 145 | make the browser expand the introduction section as a result of the 146 | scroll-to-text fragment navigation match. 147 | 148 | One possible real-world application of this is the collapsed sections on mobile 149 | wikipedia pages. find-in-page and scroll-to-text currently can't find text 150 | inside of the collapsed sections, but with `hidden=until-found` they could be 151 | searchable and automatically expanded. 152 | 153 | Using this feature is a good optimization for low power mobile devices that 154 | don't want to render all of the content in the page but still making it 155 | accessible to features such as find-in-page. Making long articles with collapsed 156 | sections accessible to find-in-page will improve the user experience. 157 | 158 | ## Comparison to the `
` element 159 | 160 | The [`
` 161 | element](https://html.spec.whatwg.org/#interaction-with-details) works very similarly to this 162 | feature. This feature empowers developers to build their own auto-expandable 163 | details elements and more by exposing the primitive features used to make the 164 | `
` element be searchable. 165 | 166 | ## Privacy concerns 167 | 168 | The `beforematch` event as well as the DOM modifications made by the browser 169 | when it removes the `hidden` attribute expose additional information to the page 170 | about find-in-page and ScrollToTextFragment. 171 | 172 | For find-in-page, this new information no more exploitable than the existing 173 | `scroll` events. It is already possible to snoop on find-in-page by creating a 174 | scrollable area containing every next character the user could type into 175 | find-in-page, listening to scroll events to see which caracter the user typed 176 | in, then prepending the new character to all of the next possible search terms. 177 | If the scrollable area is 1px tall or otherwise very small or hard to see, then 178 | the user may not be able to tell it is happening. This is demonstrated in 179 | [search-incremental.html](/resources/find-in-page/search-incremental.html). 180 | 181 | In order to mitigate find-in-page snooping from both `scroll` events and 182 | `hidden=until-found`/`beforematch`, browsers should avoid scrolling to every 183 | character the user types into the find-in-page dialog by adding a delay between 184 | keystrokes and scrolling. This prevents the page from incrementally building the 185 | user's search query one character at a time. If a snooping page has to build the 186 | user's search query at something like 5 characters at a time, the page would 187 | need to include so many potential results that it would become very hard or 188 | impossible to recreate the user's search query. 189 | 190 | As for the ScrollToTextFragment case, the browser firing the `beforematch` event 191 | and removing the `hidden` attribute on the target text does not reveal more 192 | information than is already revealed by the exising scrolling and `:target` 193 | pseudo selector that ScrollToTextFragment applies. 194 | 195 | ## Responses to DOM and style changes in the `beforematch` event handler 196 | 197 | If the `beforematch` event handler 198 | [collapses](https://dom.spec.whatwg.org/#range-collapsed) the DOM range of the 199 | target text or changes the style to remove the target text from rendering, the 200 | browser will not scroll to the target text. 201 | 202 | ## Usage of `content-visibility` 203 | 204 | `hidden=until-found` will be implemented as a presentational style of 205 | `content-visibility:hidden` as opposed to the existing `hidden` attribute which 206 | applies a presentational style of `display:none`. This improves the 207 | performance of searching the content inside the `hidden=until-found` subtree 208 | because `content-visibility: hidden`, unlike `display: none`, allows the rendering state 209 | needed to perform a text search to be cached. 210 | This means that once the first run of 211 | find-in-page or ScrollToTextFragment computes these values, the subsequent 212 | runs can reuse the cached rendering state. 213 | 214 | ## Accessibility 215 | 216 | `hidden=until-found` subtrees will not be included in the accessibility tree 217 | because they are not visible on the screen. This will be implemented in the same 218 | way that `content-visibility:hidden` content is removed from the accessibility 219 | tree. 220 | 221 | Websites are encouraged to provide a way to reveal `hidden=until-found` content 222 | without the use of find-in-page, ScrollToTextFragment, or element fragment 223 | navigation in order to ensure that all users can access the hidden content using 224 | a method other than find-in-page, such as the clickable/activatable label to 225 | expand a `
` element. 226 | 227 | ## Supporting `window.find()` 228 | 229 | Another potential user-agent algorithm we could add beforematch to is 230 | `window.find`. `window.find` works very similarly to find-in-page and exists in 231 | Firefox, Safari, and Chrome, but is not specified and has rather low usage. The 232 | only benefit I see to adding support to `window.find` would be to make it easier 233 | to add WPT tests for beforematch, since we cant have WPTs for find-in-page. 234 | However, that would also require speccing `window.find`. 235 | 236 | ## Backwards compatibility with the `hidden` attribute 237 | 238 | If a browser which doesn't implement this feature processes a 239 | `hidden=until-found` attribute, it will apply `display:none` instead of 240 | `content-visibility:hidden`. This should make it visually appear the same on all 241 | browsers, but `content-visibility:hidden` still allows some parts of the element 242 | to be rendered: the [generated box](https://drafts.csswg.org/css2/#visibility) 243 | of the element. 244 | 245 | If the `hidden=until-found` element still shows a generated box, then it is best 246 | to avoid letting the styles causing the generated box to apply to the 247 | `hidden=until-found` element. Here are some examples: 248 | 249 | Before usage of `hidden=until-found`: 250 | ```html 251 | 258 | 259 | 260 | ``` 261 | 262 | Mitigation 1: Add an extra div 263 | ```html 264 | 271 | 272 | 275 | ``` 276 | 277 | Mitigation 2: Change selectors 278 | ```html 279 | 287 | ``` 288 | 289 | ## Alternatives considered 290 | Given the purpose of displaying `hidden=until-found` text when it is searched 291 | for, there are a number of alternatives we have considered. 292 | 293 | ### Use a CSS property instead of an HTML attribute 294 | Instead of having the `hidden=until-found` HTML attribute, we could have a CSS 295 | property named `content-visibility: hidden-matchable`. In order to reveal the 296 | content in response to find-in-page or ScrollToTextFragment, the `beforematch` 297 | event handler would need to manually remove the `content-visibility: 298 | hidden-matchable` property. [This was proposed as a prior iteration of this 299 | feature](https://github.com/w3c/csswg-drafts/issues/5595). 300 | ```html 301 | 306 | 309 | 314 | ``` 315 | #### Pros 316 | * Having visibility be controlled by a CSS property makes more sense. 317 | * It's harder to apply an attribute to a lot of content at once than it is to 318 | apply a CSS property to a lot of content at once. CSS is more ergonomic. 319 | * If you have a custom element which wants to apply hidden-matchable to its 320 | light DOM children, you can easily do so with a CSS selector which doesn't 321 | actually modify the state of the light DOM children. With this attribute, you 322 | would have to modify the light DOM children. 323 | #### Cons 324 | * Requires script to reveal hidden content instead of having the browser do it 325 | automatically. This makes it easier to use and harder to implement poorly for 326 | web developers. 327 | * If the page takes too long to reveal the hidden content, such as in the case 328 | of asynchronously applying styles, the browser won't be able to scroll to the 329 | target text. 330 | 331 | *Note: the following alternatives were written as alternatives to the previously 332 | proposed `content-visibility: hidden-matchable` CSS property and might not make 333 | as much sense as alternatives to the proposed `hidden=until-found` HTML 334 | attribute.* 335 | 336 | ### Automatic revealing with internal state 337 | Instead of having an HTML attribute, this feature would be implemented as a CSS 338 | property which automatically reveals itself in response to find-in-page by 339 | setting an internal flag on elements which are considered active by 340 | find-in-page. This used to be implemented in Blink as a prior iteration of this 341 | feature. 342 | #### Pros 343 | * The browser reveals the content and scrolls to it without the need for any 344 | script. 345 | * Since there is no event causing script to run, the interaction and scrolling 346 | occurs entirely within the browser, which guarantees that we can scroll to 347 | the element without complications. 348 | * Less privacy concerns since the browser doesn't explicitly signal new 349 | information to the page when a match is found or revealed. 350 | #### Cons 351 | * Doesn't allow the page to change other state in conjunction with displaying 352 | hidden content. For example, the html example earlier in this explainer uses 353 | the beforematch event to change the arrow in the clickable title section which 354 | expand and collapses the section to show whether or not the section is 355 | expanded or collapsed. This is a very common pattern, and without the page 356 | being notified about the reveal, it isn't possible. 357 | * Doesn't make it feasible for script to toggle the expanded/collapsed state 358 | since script can't see the internal flag representing the expanded/collapsed 359 | state. 360 | * Automatic revealing and adding internal hidden state to track revealed 361 | sections gets complicated and confusing in the browser implementation. 362 | 363 | ### Automatic revealing with `element.style` 364 | Instead of having an HTML attribute, this feature would be implemented as a CSS 365 | property which would automatically get overwritten by the browser via 366 | `element.style` or something similar when the content should be revealed. 367 | #### Pros 368 | * The browser reveals the content and scrolls to it without the need for any 369 | script. 370 | * Since there is no event causing script to run, the interaction and scrolling 371 | occurs entirely within the browser, which guarantees that we can scroll to 372 | the element without complications. 373 | * Don't need to maintain internal state in the browser. 374 | * If a developer knows how it works, they can change the style back to hidden. 375 | #### Cons 376 | * May require modifying `element.style` of multiple elements. 377 | * If script later modifies `element.style`, then the matching text would become 378 | invisible again. In general, having the browser change DOM or style like this 379 | isn't a good idea because it would be likely to clash with how the page is 380 | maintaining the same state and isn't very intuitive to the developer. 381 | * Doesn't make it easy for the page to change other state in conjunction with 382 | the reveal. 383 | * Requires privacy mitigations since the reveal/match is observable by the page. 384 | 385 | ### Automatic revealing with activation event 386 | This is like "Automatic Revealing," but with an added "activation" event emitted 387 | when content is revealed to allow the page to change other state and styles if 388 | needed. 389 | #### Pros 390 | * The browser reveals the content and scrolls to it without the need for any 391 | script. 392 | * Allows script to modify state and style when content is revealed. 393 | #### Cons 394 | * Doesn't make it feasible for script to toggle the expanded/collapsed state 395 | since script can't see the internal flag representing the expanded/collapsed 396 | state. 397 | * Automatic revealing and adding internal hidden state to track revealed 398 | sections gets complicated and confusing in the browser implementation. 399 | * Requires privacy mitigations since the reveal/match is observable by the page. 400 | 401 | ### CSS pseudo selector 402 | A pseudo selector, such as `:target`, would be applied to the element 403 | containing the matching text when it is searched for. This pseudo selector 404 | could be applied to the entire ancestor chain. 405 | #### Pros 406 | * Allows content to become visible when searched for with only CSS. 407 | * Allows other styles to be changed when the content is displayed. 408 | #### Cons 409 | * If CSS with a pseudo selector is used to make text visible, then when 410 | find-in-page is closed or the search text changes, the pseudo selector would 411 | be removed and then any selector which is displaying the text based on that 412 | pseudo selector would not apply, causing the expanded section to unexpectedly 413 | collapse. 414 | * There is no way in CSS to say "change my style if a descendant has a pseudo 415 | class on it." For this reason, developers would be unable to change styles 416 | outside of the particular element that has the matching text, which would make 417 | the functionality of Example 1 not possible. Although this could be mitigated 418 | for some cases by applying the pseudo selector to the entire ancestor chain, 419 | it can be complicated or impossible to provide the right selector which can 420 | modify a style on an unrelated element. 421 | * Requires privacy mitigations since the reveal/match is observable by the page. 422 | * Not elegant or not even possible for script to listen for the reveal and 423 | change other state in the page. 424 | -------------------------------------------------------------------------------- /explainers/images/beforematch.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WICG/display-locking/1abded5a9e9bade0a11c22acc9e3b9c9e3c5eb48/explainers/images/beforematch.gif -------------------------------------------------------------------------------- /explainers/isvisible.md: -------------------------------------------------------------------------------- 1 | # Element.isVisible explainer 2 | 3 | The web features several ways that content can be hidden. Each of the ways may 4 | have distinct characteristics and are used for different purposes: 5 | 6 | * `visibility: hidden`: this hides the element visually but keeps its layout box and allows for the descendant to 7 | make itself visible. In other words, this property doesn't affect the subtree, 8 | with the exception of providing the `visibility` value to be inherited by 9 | descendant styles. 10 | * `opacity: 0`: this hides the element and its subtree visually but keeps its layout box and allows for animations 11 | that fade content in or out. 12 | * `display: none`: this hides the element and its subtree, it also destroys 13 | rendering state (removes its layout box) and makes the DOM subtree not take up any time while 14 | processing rendering. 15 | * `content-visibility: hidden`: this hides the subtree of an element, without 16 | destroying the rendering state (i.e. its layout box is preserved). It also makes the DOM subtree not take up any 17 | time while processing rendering, but allows for the possibility for such 18 | rendering state to be forced (e.g. via calls to getBoundingClientRect). It 19 | also allows the element's subtree to be shown again quicker than `display: 20 | none` would allow, since `content-visibility: hidden` would preserve rendering 21 | state. 22 | 23 | There are times when script wants to determine whether an element is visible to 24 | the user, or would be visible if it was in the viewport. This can be used for a 25 | variety of reasons, such as general state tracking of visibility. 26 | 27 | This can be hard to compute correctly, since the script author needs to remember to 28 | check all the necessary methods by which content can be hidden (including 29 | accounting for the fact that new methods could be added). It also is hard to do 30 | efficiently, since for example access into the subtree hidden by 31 | `content-visibility: hidden` may cause rendering work to be updated. 32 | 33 | Additionally, checking if an element is hidden by a closed shadow tree, such as 34 | the case with `
` element is difficult, if not impossible 35 | 36 | For this reason, we propose to add Element.isVisible function to compute the 37 | values, so that script authors may use this as a correct and efficient way to 38 | determine the necessary visibility. This also returns a correct value for 39 | elements slotted inside closed shadow trees. 40 | 41 | The spec draft for the function can be found 42 | [here](https://drafts.csswg.org/cssom-view/#dom-element-isvisible). Note that 43 | the options specified to isVisible call allow developers to customize the check 44 | they would like to make. 45 | -------------------------------------------------------------------------------- /explainers/update-rendering.md: -------------------------------------------------------------------------------- 1 | ## `renderpriority` attribute. 2 | 3 | _Note that issues referenced in this document can refer to either the 4 | `renderpriority` attribute or `updateRendering()` JavaScript API. The issues 5 | discussed apply to both._ 6 | 7 | ### TL;DR 8 | The `renderpriority` attribute is an HTML attribute that informs the User 9 | Agent to keep the element's rendering state updated with a specified priority. 10 | 11 | (Note that the `renderpriority` name is a 12 | [placeholder name](https://github.com/WICG/display-locking/issues/200)) 13 | 14 | ### Motivation 15 | The web includes a number of features and heuristics, such as 16 | content-visibility, containment and others, that allow the User Agent to skip 17 | rendering work for elements and contents of elements when they are not visible to the 18 | user. However if that content is subsequently brought on-screen, or its rendering state is 19 | queried via a DOM API, there may be a significant delay to render the content. 20 | 21 | An example use case is optimizing the speed of single-page-application navigations. If 22 | the application can predict a likely user action, then it can prerender the next 23 | view offscreen via `content-visibility: hidden` plus `renderpriority`. This will make the 24 | single-page application navigations faster for the user. 25 | 26 | ### Proposal: `renderpriority` element attribute 27 | When present, this attribute informs the User Agent that it should keep the 28 | element and its subtree updated according to the specified priority. The timing 29 | and frequency of updates are kept in the User Agent's control to allow 30 | flexibility in prioritizing this work. 31 | 32 | The values that the attribute takes inform the User Agent of developer intent: 33 | * `user-blocking` is the highest priority, and is meant to be used for updates 34 | that are blocking the user’s ability to interact with the page, such as 35 | rendering the core experience or responding to user input. 36 | 37 | * `user-visible` is the second highest priority, and is meant to be used for 38 | updates that visible to the user but not necessarily blocking user actions, 39 | such as rendering secondary parts of the page. This is the default priority. 40 | 41 | * `background` is the lowest priority which permits updates, and is meant to be 42 | used for updates that are not time-critical, such as background updates for 43 | speculative layout. 44 | 45 | * `never` is the value that skips rendering updates. Note that this value only 46 | has an effect if the rendering of the page would already have been skipped -- 47 | See Notes and Clarification below. 48 | 49 | * `auto` is the default priority, which allows the User Agent select an 50 | approriate priotization for rendering work. 51 | 52 | Note that the attribute values follow [the postTask API](https://wicg.github.io/scheduling-apis/#sec-task-priorities) 53 | example. 54 | 55 | 56 | ### Interaction with `content-visibility` 57 | Since the User Agent typically keeps rendering state of subtrees up-to-date, 58 | this feature would be a no-op in a majority of cases. For instance, having 59 | `renderpriority` on a visible, on screen, element would not have to do any 60 | work since the rendering state of such an element is already kept up to date. 61 | (Note that it is an [open question](https://github.com/WICG/display-locking/issues/202) 62 | whether the behavior of visible elements with `renderpriority` should cause 63 | asynchronous updates) 64 | 65 | We're proposing this feature as an enhancement for the `content-visibility` CSS 66 | property. For example, when `content-visibity: hidden` property is applied to 67 | the element, it ensures that the element's subtree is not visible and that its 68 | rendering state is not updated to save CPU time. Adding `renderpriority` on 69 | such an element, however, would cause the User Agent to continually process its 70 | rendering with a given priority. 71 | 72 | ### Examples 73 | 74 | Consider the following example. 75 | 76 | ```html 77 |
78 | 79 | ... 80 |
81 | ``` 82 | 83 | Here the contents of `#container` are not visible, and its rendering state 84 | is not necessarily up-to-date since the contents of the element are 85 | [skipped](https://www.w3.org/TR/css-contain-2/#skips-its-contents) 86 | 87 | This is typically done to avoid rendering work in this subtree. However, when 88 | the developer decides that the contents should now be visible, they remove 89 | the `content-visibility: hidden` style. This causes all of the rendering to be 90 | updated in the subsequent frame. This work, in turn, can cause undue delay 91 | (for example, some experimental data from Facebook indicates up to a 92 | [250ms](https://web.dev/content-visibility/#hiding-content-with-content-visibility:-hidden) 93 | delay due to this work in practice). 94 | 95 | The solution is to add the `renderpriority` attribute: 96 | 97 | ```html 98 |
99 | 100 | ... 101 |
102 | ``` 103 | 104 | Here, the developer has added `renderpriority=background`, which means that they 105 | would like the User Agent to keep the rendering state of `#container`'s content 106 | to be kept up to date with a low priority. 107 | 108 | Assuming that the User Agent completes this work (i.e. it is not otherwise busy 109 | doing more important rendering work), then when the developer removes the 110 | `content-visibility` style, the contents are displayed without undue delay. 111 | This is a consequence of the fact that the rendering state should already be 112 | up-to-date, completed cooperatively with the rest of the required work. Note 113 | that there may still be rendering work to be done, since the act of removing 114 | `content-visibility: hidden` may cause layout changes that need to be updated 115 | (e.g. containment may be turned off). 116 | 117 | ### Performance Potential 118 | 119 | One of the benefits of this feature comes from the fact that the work can be 120 | delayed until later. This is, of course, already possible via properties such as 121 | `display: none` and `content-visibility: hidden`. This means, on its own, this 122 | benefit is not sufficient to justify adding a new attribute. 123 | 124 | However, consider how a page with `display: none` would typically work: 125 | 1. The user navigates to the page, which loads, parses, and renders all of the 126 | DOM. 127 | 2. DOM that is styled with `display: none` does not generate layout boxes, which 128 | means that rendering work like layout and painting is skipped. 129 | 3. Sometime later, a user action, for example, causes the page to remove the 130 | `display: none` style from some large subtree. 131 | 4. At this point, the user agent renders the full subtree synchronously. 132 | 133 | This process is similar for `content-visibility: hidden` subtrees. 134 | 135 | The synchronous rendering could cause jank, since the amount of work is 136 | dependent on the DOM and that work must be done synchronously. The key 137 | observation here is that some time may pass between initial load and when the 138 | page would like to display hidden content. This naturally leads to a proposal: 139 | let's use that time to render the hidden content incrementally without causing 140 | jank. That way, when the page ultimately displays the content, the rendering 141 | cost is small. 142 | 143 | We need to be careful not to render all of `content-visibility: hidden` content 144 | though, since we don't know whether the page intends to show it to the user at 145 | all. It is also unclear whether some content is more important, meaning we 146 | should do more rendering work in such subtrees even if we risk a small amount of 147 | jank. 148 | 149 | This leads us to the `renderpriority` attribute. It allows for the two behaviors 150 | we want: take the opportunity to use idle time for incremental rendering, and 151 | to let the page dictate the importance of each hidden content piece. The only 152 | heuristic here is how much work the User Agent will do, which should be left up 153 | to the implementation. 154 | 155 | Note that one can draw an equivalence to adding `content-visibility: auto` to 156 | items in a large list. The initial visible content is rendered, but the content 157 | off-screen remains unrendered. As the user continuously scrolls, more and more 158 | content enters the viewport and renders. This accomplishes two things: the 159 | initial load is significantly faster, since we only render on-screen items, and 160 | the progressive rendering of new content does not jank -- since it is rendered 161 | one item at a time. We have observed [substatial savings in 162 | performance](web.dev/content-visibility) in using this approach. The 163 | renderpriority attribute should allow similar performance gains for general 164 | content, the availability of which is not tied to the viewport intersection as 165 | is the case with `content-visibility: auto`. 166 | 167 | ### Notes and Clarifications 168 | * If the User Agent does not optimize the rendering of an element, by skipping 169 | work, then the attribute has no effect on such an element. Note, however, that 170 | the value can still affect subtree elements that _are_ optimized. 171 | Specifically, the value dictates the maximum priority that would be used on 172 | the subtree element. In the example below, `.is_optimized` will be processed 173 | with a `background` priority, since that is the maximum priority established 174 | by its parent that is no higher than `user-visible`, regardless of whether the parent is itself optimized. 175 | 176 | ```html 177 |
178 |
179 |
180 | ``` 181 | 182 | * Note that the UA must be careful about selecting the `auto` priority that is 183 | lower than `user-blocking`, since the priority cannot be overriden to be 184 | higher -- it can only be lowered. This means that if the overall default 185 | `auto` value is equivalent to `user-visible`, for example, then setting a 186 | value of `user-blocking` on any element would have no effect. For this reason, 187 | we recommend that the default behavior of `auto` is equivalent to 188 | `user-blocking` unless the user agent has a good reason to enforce a lower 189 | priority. 190 | 191 | * Setting the attribute on an element whose rendering state is not updated due 192 | to `display: none`, ancestor style that prevents update (e.g. ancestor 193 | `content-visibility: hidden`), or similar styles has no effect. In other 194 | words, this attribute would not force rendering state to be updated on 195 | elements whose rendering work is required to be skipped. ([more 196 | details](https://github.com/WICG/display-locking/issues/199)). Note that this 197 | does _not_ include elements that themselves have `content-visibility: hidden` 198 | style, since their rendering is updated and the attribute would cause the 199 | subtree to be udpated as well. 200 | 201 | * Setting the attribute on an element that contains descendants with 202 | `content-visibility: hidden`, `display: none`, or similar styles would not 203 | cause the contents of such elements to be updated. This is a consequence of 204 | the fact that a fully updated parent element has all its rendering work 205 | completed without updating such descendants. ([more details](https://github.com/WICG/display-locking/issues/196)). 206 | If such an update is desired, a `renderpriority` attribute should be set on 207 | such elements. Note that recursive `renderpriority` settings may be considered 208 | in the future. 209 | -------------------------------------------------------------------------------- /find-in-page-compat.md: -------------------------------------------------------------------------------- 1 | # Find-in-page compatibility across browsers 2 | 3 | This page documents similarities and differences across browsers when using the browser find-in-page UI in different situations. 4 | 5 | ## Browsers tested 6 | 7 | The test was conducted on the following browsers: 8 | * Chrome Canary 85.0.4164.0 9 | * Firefox Nightly 79.0a1 10 | * Safari Technology Preview Release 107 (Safari 13.2, WebKit 15610.1.14.1) 11 | 12 | ## Tests 13 | 14 | ### Display Types 15 | 16 | This test checks whether find-in-page crosses the boundary of different display 17 | types: block, inline-block, and inline. 18 | 19 | ```html 20 | 21 | 22 | 27 | 28 |

The following two words are in separate blocks:

29 |
one
two
30 | 31 |

The second word is in a block sibling of the first:

32 |
one
two
33 | 34 |

The following two words are in separate inline-blocks:

35 |
one
two
36 | 37 |

The second word is in a inline-block sibling of the first:

38 |
one
two
39 | 40 |

The following two words are in separate inlines:

41 |
one
two
42 | 43 |

The second word is in a inline sibling of the first:

44 |
one
two
45 | ``` 46 | 47 | Searching for "onetwo" without quotes. 48 | 49 | #### Chrome results 50 | 51 | 52 | 53 | Chrome finds text in separate inlines, and when the second word is an inline 54 | sibling of the first. It does not find the text in any other cases. 55 | 56 | #### Firefox results 57 | 58 | 59 | 60 | Firefox finds text in separate inlines, separate inline-blocks, and 61 | corresponding sibling tests. It does not find text across blocks. 62 | 63 | #### Safari results 64 | 65 | 66 | 67 | Safari finds text in separate inlines, separate inline-blocks, and 68 | corresponding sibling tests. It does not find text across blocks. Note that 69 | there is a visual highlight inconsistency: in one of the cases only the second 70 | word is highlighted. 71 | 72 | ### Visibility 73 | 74 | This test checks whether matches are found in content that is hidden by 75 | different means: visibility hidden, display none, opacity 0, and low opacity 76 | (0.01). 77 | 78 | ``` 79 | 80 | 81 | 88 | 89 | In the following examples, "target" is the word to search for: 90 | 91 |
92 | 93 |

visibility: hidden element below

94 | 95 | 96 |
97 | 98 |

display: none element below

99 |
target
100 | 101 |
102 | 103 |

opacity: 0 element below

104 |
target
105 | 106 |
107 | 108 |

opacity: 0.01 element below

109 |
target
110 | ``` 111 | 112 | Searching for "target" without quotes. 113 | 114 | #### Chrome results 115 | 116 | 117 | 118 | Chrome finds text in opacity: 0 and opacity: 0.01 cases. It does not find 119 | results in other cases. The matches are scrolled into view, but the highlights 120 | are not visible. 121 | 122 | #### Firefox results 123 | 124 | 125 | 126 | Firefox finds text in opacity: 0 and opacity: 0.01 cases. It does not find 127 | results in other cases. The matches are scrolled into view but the highlights 128 | are not visible. 129 | 130 | #### Safari results 131 | 132 | 133 | 134 | Safari finds text in opacity: 0 and opacity: 0.01 cases. It does not find 135 | results in other cases. The matches are scrolled into view and the highlight is 136 | visible at full opacity (although the match remains invisible). 137 | 138 | ### Overflow hidden 139 | 140 | This test checks whether matches are found when they are clipped out by 141 | overflow: hidden elements. 142 | 143 | ``` 144 | 145 | 146 | 150 | 151 | Search for "target" 152 | 153 |
154 | 155 |

below is an overflow: hidden element with a 1000px tall spacer and a div with text

156 | 157 |
158 |
159 |
target
160 |
161 | 162 |
163 |

first spacer after container ends here

164 |
165 |

second spacer after container ends here

166 | ``` 167 | 168 | Searching for "target" without quotes. 169 | 170 | #### Chrome results 171 | 172 | 173 | 174 | Chrome finds the match, and scrolls the page to where the match would have been 175 | if it was visible. Neither the match nor the highlight are visible. 176 | 177 | #### Firefox results 178 | 179 | 180 | 181 | Firefox finds the match, and scrolls the page to where the match would have 182 | been if it was visible. Neither the match nor the highlight are visible. 183 | 184 | #### Safari results 185 | 186 | 187 | 188 | Safari finds the match, it scrolls the overflow: hidden container's contents to 189 | expose the match, and it scrolls the page to expose the container. Both the 190 | match and the highlight are visible. 191 | 192 | ### Overflow auto 193 | 194 | This test ensures that find-in-page scrolls nested scrollers to expose matches 195 | not visible, but reachable by the user. 196 | 197 | ``` 198 | 199 | 200 | 204 | 205 | Search for "target" 206 | 207 |
208 | 209 |

below is an overflow: auto element with a 1000px tall spacer and a div with text

210 | 211 |
212 |
213 |
target
214 |
215 | 216 |
217 |

first spacer after container ends here

218 |
219 |

second spacer after container ends here

220 | ``` 221 | 222 | Searching for "target" without quotes. 223 | 224 | #### Chrome results 225 | 226 | 227 | 228 | Chrome finds the match, it scrolls the overflow: auto container's contents to 229 | expose the match, and it scrolls the page to expose the container. Both the 230 | match and the highlight are visible. 231 | 232 | #### Firefox results 233 | 234 | 235 | 236 | Firefox finds the match, it scrolls the overflow: auto container's contents to 237 | expose the match, and it scrolls the page to expose the container. Both the 238 | match and the highlight are visible. 239 | 240 | #### Safari results 241 | 242 | 243 | 244 | Safari finds the match, it scrolls the overflow: auto container's contents to 245 | expose the match, and it scrolls the page to expose the container. Both the 246 | match and the highlight are visible. 247 | 248 | ### Occlusion 249 | 250 | This test case checks whether matches can be found if they are occluded by 251 | position: relative and position: absolute elements. 252 | 253 | ``` 254 | 255 | 256 | 275 | 276 |

The "target" text below is occluded by a relpos element

277 | 278 |

279 | target text 280 |
281 |
282 | 283 |

The text below is occluded by a abspos element

284 | 285 |
286 | target text 287 |
288 |
289 | ``` 290 | 291 | Searching for "target" without quotes. 292 | 293 | #### Chrome results 294 | 295 | 296 | 297 | Chrome finds occluded matches. Neither the highlight nor the match are visible. 298 | 299 | #### Firefox results 300 | 301 | 302 | 303 | Firefox finds occluded matches. Neither the highlight nor the match are 304 | visible. 305 | 306 | #### Safari results 307 | 308 | 309 | 310 | Safari finds occluded matches. The highlight is always visible. Furthermore, 311 | when the match is the active match, the matched text is also visible on top of 312 | the occluding element. 313 | 314 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /privacy-assessments/auto-expanding-details-privacy.md: -------------------------------------------------------------------------------- 1 | # Auto-expanding `
` security and privacy self-review questionnaire 2 | 3 | ## Questions to Consider 4 | 5 | ### 2.1. What information might this feature expose to Web sites or other parties, and for what purposes is that exposure necessary? 6 | 7 | This feature will open details elements in response to find-in-page and ScrollToTextFragment. When a details element is opened, the page can observe it via the `toggle` event which is fired and the `open` attribute. It is necessary that we continue to fire this event and add the attribute when the details element is opened because the page may be relying on them to reconcile other state in the page or in script with the open state of the details element. 8 | 9 | ### 2.2. Is this specification exposing the minimum amount of information necessary to power the feature? 10 | 11 | Yes. 12 | 13 | ### 2.3. How does this specification deal with personal information or personally-identifiable information or information derived thereof? 14 | 15 | If you consider find-in-page queries or ScrollToTextFragment queries personal information or PII, it is dealt with the same way "sensitive information" is in the next section. 16 | 17 | No new information stored on the device is exposed by this feature. 18 | 19 | ### 2.4. How does this specification deal with sensitive information? 20 | 21 | The search queries present in the ScrollToTextFragment and find-in-page features may be sensitive information, and are considered in the "Privacy Considerations" section. 22 | 23 | ### 2.5. Does this specification introduce new state for an origin that persists across browsing sessions? 24 | 25 | This feature does not store any new data in the browser. 26 | 27 | ### 2.6. What information from the underlying platform, e.g. configuration data, is exposed by this specification to an origin? 28 | 29 | No information from the underlying platform is exposed by this feature. 30 | 31 | ### 2.7. Does this specification allow an origin access to sensors on a user's device 32 | 33 | No. 34 | 35 | ### 2.8. What data does this specification expose to an origin? Please also document what data is identical to data exposed by other features, in the same or different contexts. 36 | 37 | This feature does not expose any information about an origin's state and does not enable sending or receiving of any data to or from a network connection. 38 | 39 | ### 2.9. Does this specification enable new script execution/loading mechanisms? 40 | 41 | No. 42 | 43 | ### 2.10. Does this specification allow an origin to access other devices? 44 | 45 | No. 46 | 47 | ### 2.11. Does this specification allow an origin some measure of control over a user agent's native UI? 48 | 49 | No. 50 | 51 | ### 2.12. What temporary identifiers might this specification create or expose to the web? 52 | 53 | None. 54 | 55 | ### 2.13. How does this specification distinguish between behavior in first-party and third-party contexts? 56 | 57 | ScrollToTextFragment doesn't work on cross-origin iframes, so that isn't a concern for this feature. 58 | 59 | Find-in-page does work on cross origin iframes, but every time find-in-page scrolls to a match in an iframe it will continue to emit `scroll` events which are already revealing more information than this feature would. 60 | 61 | ### 2.14. How does this specification work in the context of a user agent's Private Browsing or "incognito" mode? 62 | 63 | This feature will work the same regardless of incognito mode being enabled or disabled. 64 | 65 | ### 2.15. Does this specification have a "Security Considerations" and "Privacy Considerations" section? 66 | 67 | A Privacy Considerations section can be found further down in this document. There is no Security Considerations section because this feature does not expose any security vulnerabilities. 68 | 69 | ### 2.16. Does this specification allow downgrading default security characteristics? 70 | 71 | No. 72 | 73 | ## Privacy Considerations 74 | 75 | ### 1. What privacy attacks have been considered? 76 | 77 | The page could observe the `toggle` event or the addition of the `open` attribute when this feature automatically expands details elements in an attempt to find out what the user was searching for with find-in-page or ScrollToTextFragment. If the page listens to the relevant events, it may be able to determine whether the user clicked on the details element to expand it or if it was automatically opened by this feature. 78 | 79 | ### 2. What privacy attacks have been deemed out of scope (and why)? 80 | 81 | The aforementioned privacy attack is out of scope because it is less powerful than existing vulnerabilities for find-in-page and ScrollToTextFragment, meaning that this feature has a zero information delta with find-in-page and ScrollToTextFragment. 82 | 83 | For find-in-page, vulnerabilities already exist which use the `scroll` event which is synchronous unlike the `toggle` event this feature will trigger. Every time find-in-page scrolls to a result, the page fires a `scroll` event. If the page creates a tiny scrollable area with every next possible character the user could type, it can recreate what the user typed into find-in-page. An example page which uses this attack can be found [here](/resources/find-in-page/search-incremental.html). If we were to remove the `scroll` events from find-in-page then this feature could become another vector for this attack, but this is unlikely to happen because it would break find-in-page for web pages which rely on the `scroll` event. This attack could be addressed regardless of the particular vector by adding a delay to find-in-page's scrolling which allows the user to type in enough characters to prevent the page incrementally building the user's search query, which Safari already does today. 84 | 85 | For ScrollToTextFragment, this feature exposes less than the existing `:target` pseudo selector added by ScrollToTextFragment. 86 | 87 | ### 3. What privacy mitigations have been implemented? 88 | 89 | No privacy mitigations have been implemented. 90 | 91 | ### 4. What privacy mitigations have considered and not implemented (and why)? 92 | 93 | Adding a delay to the frequency find-in-page queries are sent to the page would help mitigate the possibility of this feature being used to snoop on find-in-page. Due to the existing `scroll` events, this feature does not make the situation any worse and therefore should not be blocked on adding a delay to find-in-page. However, the find-in-page delay is planned to be implemented in chromium. 94 | -------------------------------------------------------------------------------- /privacy-assessments/beforematch.md: -------------------------------------------------------------------------------- 1 | # beforematch event security and privacy self-review questionnaire 2 | 3 | The `beforematch` event ([explainer](https://github.com/WICG/display-locking/blob/master/explainer-beforematch.md)) is fired on elements in the following cases, before the scrolling occurs: 4 | * When the fragment is changed to scroll to an element by id, including on navigation to a url which includes a fragment. 5 | * I will refer to this case as "ElementFragment." 6 | * When the [ScrollToTextFragment](https://github.com/WICG/ScrollToTextFragment) feature finds text and scrolls to it. 7 | * I will refer to this case as "ScrollToTextFragment." 8 | * When the find-in-page (ctrl+f) feature is used to search for text. 9 | * I will refer to this case as "find-in-page." 10 | 11 | ## Questions to Consider 12 | 13 | ### 2.1. What information might this feature expose to Web sites or other parties, and for what purposes is that exposure necessary? 14 | 15 | This feature may expose hints as to what the user is searching for to webpages. I wrote more detailed considerations about this in the "Privacy Considerations" section at the bottom of this document. 16 | 17 | This exposure is necessary in order to fulfill the use case of displaying content that was searched for, as described in [the beforematch explainer](https://github.com/WICG/display-locking/blob/master/explainer-beforematch.md). 18 | 19 | ### 2.2. Is this specification exposing the minimum amount of information necessary to power the feature? 20 | 21 | Yes, this is exposing only the information required for the `beforematch` event to function as specified. 22 | 23 | ### 2.3. How does this specification deal with personal information or personally-identifiable information or information derived thereof? 24 | 25 | No new information stored on the device is exposed by this feature. 26 | 27 | If the user enters this type of information into their device by using the ScrollToTextFragment or find-in-page features, then this feature may expose it as described in the "Privacy Considerations" section. 28 | 29 | ### 2.4. How does this specification deal with sensitive information? 30 | 31 | The search queries present in the ScrollToTextFragment and find-in-page features may be sensitive information, and are considered in the "Privacy Considerations" section. 32 | 33 | ### 2.5. Does this specification introduce new state for an origin that persists across browsing sessions? 34 | 35 | This feature does not store any new data in the browser. 36 | 37 | ### 2.6. What information from the underlying platform, e.g. configuration data, is exposed by this specification to an origin? 38 | 39 | No information from the underlying platform is exposed by this feature. 40 | 41 | ### 2.7. Does this specification allow an origin access to sensors on a user's device 42 | 43 | No. 44 | 45 | ### 2.8. What data does this specification expose to an origin? Please also document what data is identical to data exposed by other features, in the same or different contexts. 46 | 47 | This feature does not expose any information about an origin's state and does not enable sending or receving of any data to or from a network connection. 48 | 49 | ### 2.9. Does this specification enable new script execution/loading mechanisms? 50 | 51 | No. 52 | 53 | ### 2.10. Does this specification allow an origin to access other devices? 54 | 55 | No. 56 | 57 | ### 2.11. Does this specification allow an origin some measure of control over a user agent's native UI? 58 | 59 | This feature allows the page to respond to find-in-page, which is part of the user agent's native UI. However, this feature does not allow control over find-in-page. 60 | 61 | ### 2.12. What temporary identifiers might this specification create or expose to the web? 62 | 63 | None. 64 | 65 | ### 2.13. How does this specification distinguish between behavior in first-party and third-party contexts? 66 | 67 | With regards to cross origin iframes, this behavior will occur in each beforematch case: 68 | * In the ElementFragment case, the scrolling, fragments, and beforematch events are fully insulated from each other when they occur in different cross origin iframes. 69 | * In the ScrollToTextFragment case, text inside of a cross origin iframe will not be searched for or scrolled to. Therefore, no beforematch event will be emitted. 70 | * In the find-in-page case, content in cross origin iframes can be searched for and scrolled to. In this case, the cross origin iframe will get the beforematch event and scrolling will happen as normal, but the main frame won't know anything about it, which maintains the insulation between origins. 71 | 72 | ### 2.14. How does this specification work in the context of a user agent's Private Browsing or "incognito" mode? 73 | 74 | This feature will work the same regardless of incognito mode being enabled or disabled. 75 | 76 | ### 2.15. Does this specification have a "Security Considerations" and "Privacy Considerations" section? 77 | 78 | I included a Privacy Considerations section further down this document. I did not include a Security Considerations section because I do not believe this feature exposes any security vulnerabilities. 79 | 80 | ### 2.16. Does this specification allow downgrading default security characteristics? 81 | 82 | No. 83 | 84 | ### 2.17. What should this questionnaire have asked? 85 | 86 | I have no suggestions to improve this questionnaire. 87 | 88 | ## Privacy Considerations 89 | 90 | ### 1. What privacy attacks have been considered? 91 | 92 | The beforematch event could be used to guess what the user is searching for. 93 | * In the ElementFragment case, there are no new vulnerabilities. Any information possibly exposed by beforematch is already exposed by `window.location.hash`, the `hashchange` event, and `document.getElementById`. The following code snippet's `elementFromFragment` is the same element that `beforematch` will fire on when an element is scrolled to on hash change: 94 | ```javascript 95 | window.addEventListener('hashchange', () => { 96 | const elementFromFragment = document.getElementById(window.location.hash); 97 | }); 98 | ``` 99 | * In the ScrollToTextFragment case, the beforematch event will hint to what the user was searching for by firing on the block level element containing the text which was searched for. However, the :target pseudo selector which is already added by ScrollToTextFragment is also applied to the same element that beforematch would fire on, so the beforematch event will not expose anything new in this case. 100 | * In the find-in-page case, the same information will be exposed as the ScrollToTextFragment case. However, if the user is incrementally searching by typing in a search dialog character by character, it will result in repeated beforematch events being fired. It may be possible to reconstruct what the user is searching for in this case by having elements in the page which match every next possible character the user could search for, and then when a match occurs, changing the text of all of the elements to contain every next possible match, and so on. Here is an example page which conveys this idea. I couldn't actually get it to work properly, but with some more work I think it might: 101 | ```html 102 | 107 | 145 | ``` 146 | 147 | ### 2. What privacy attacks have been deemed out of scope (and why)? 148 | 149 | No attacks have been deemed out of scope. 150 | 151 | However, find-in-page attacks may already be possible due to the fact that pages can already intercept ctrl+f and already have the power to spoof the functionality and appearance of the browser's native find-in-page. In fact, doing this may be even easier and more reliable than using beforematch to extract the user's search text. 152 | 153 | Another find-in-page attack which may already be possible is listening to selection events. In Chrome, when the find-in-page dialog is closed, the target text gets selected and fires a selection event. By listening for ctrl+f and then looking at the next selection event, the page could see exactly what the user searched for if there is a match. 154 | In Firefox, this selection event is fired every time matching text is found, not just when the dialog is closed, allowing the page to see each character that the user is typing if there is a match. 155 | 156 | For the ScrollToTextFragment case, you can already figure out what block-level element containing the search result was by looking at the element with the :target pseudo selector. 157 | 158 | ### 3. What privacy mitigations have been implemented? 159 | 160 | No privacy mitigations have been implemented. 161 | 162 | For the find-in-page privacy case, I could imagine a mitigation where we would choose not to fire beforematch repeatedly in this case. In the example page above, the scroll offset would not be change in between firings of the event, which we could use as a heuristic to combat this case. However, I'm not sure that it couldn't be circumvented or if it would cause issues when trying to use the feature legitimately. 163 | 164 | ### 4. What privacy mitigations have considered and not implemented (and why)? 165 | 166 | No mitigations have been implemented. 167 | 168 | Besides the possible mitigation I mentioned in the above section, no others have been considered. 169 | -------------------------------------------------------------------------------- /privacy-assessments/contain-intrinsic-size.md: -------------------------------------------------------------------------------- 1 | ### 2.1. What information might this feature expose to Web sites or other parties, and for what purposes is that exposure necessary? 2 | 3 | This feature exposes the intrinsic sizing control to web developers in order to 4 | better control layout when size containment is present. 5 | 6 | ### 2.2. Is this specification exposing the minimum amount of information necessary to power the feature? 7 | 8 | Yes 9 | 10 | ### 2.3. How does this specification deal with personal information or personally-identifiable information or information derived thereof? 11 | 12 | This feature does not expose or deal with PII or PII-derived data. 13 | 14 | ### 2.4. How does this specification deal with sensitive information? 15 | 16 | This feature does not expose or deal with sensitive information. 17 | 18 | ### 2.5. Does this specification introduce new state for an origin that persists across browsing sessions? 19 | 20 | No 21 | 22 | ### 2.6. What information from the underlying platform, e.g. configuration data, is exposed by this specification to an origin? 23 | 24 | None 25 | 26 | ### 2.7. Does this specification allow an origin access to sensors on a user’s device 27 | 28 | No 29 | 30 | ### 2.8. What data does this specification expose to an origin? Please also document what data is identical to data exposed by other features, in the same or different contexts. 31 | 32 | This specification does not expose any data. It only allows the UA's rendering 33 | engine to consider new inputs from the origin. This is analogous to CSS `min-width` 34 | and `min-height` features, which act as inputs without exposing any data. 35 | 36 | ### 2.9. Does this specification enable new script execution/loading mechanisms? 37 | 38 | No 39 | 40 | ### 2.10. Does this specification allow an origin to access other devices? 41 | 42 | No 43 | 44 | ### 2.11. Does this specification allow an origin some measure of control over a user agent’s native UI? 45 | 46 | No 47 | 48 | ### 2.12. What temporary identifiers might this this specification create or expose to the web? 49 | 50 | None 51 | 52 | ### 2.13. How does this specification distinguish between behavior in first-party and third-party contexts? 53 | 54 | This specifically allows additional layout controls for the developer. It does 55 | not distinguish first- and third-party context. 56 | 57 | ### 2.14. How does this specification work in the context of a user agent’s Private Browsing or "incognito" mode? 58 | 59 | Private Browsing or "incognito" mode context do no affect this specification. 60 | 61 | ### 2.15. Does this specification have a "Security Considerations" and "Privacy Considerations" section? 62 | 63 | Yes 64 | 65 | ### 2.16. Does this specification allow downgrading default security characteristics? 66 | 67 | No 68 | 69 | ### 2.17. What should this questionnaire have asked? 70 | 71 | This questionnaire seems very thorough. Some questions are somewhat hard to 72 | answer when considering a specification such as this one, but it was a good 73 | exercise to think about the specification from all privacy and security angles. 74 | -------------------------------------------------------------------------------- /privacy-assessments/isvisible.md: -------------------------------------------------------------------------------- 1 | # Element.isVisible Privacy and Security Self-Review. 2 | 3 | * What information might this feature expose to Web sites or other parties, and for what purposes is that exposure necessary? 4 | 5 | For the most part, this function exposes information that is already available 6 | to the page, and is retrievable by other means. The exception to this case is 7 | getting the value from a closed shadow tree. Specifically, if a light DOM 8 | element is not visible because of the structure of a closed shadow tree, this 9 | function would be able to return the correct result, but this result is not 10 | easily retrieved by other means. 11 | 12 | It is being exposed, because it is difficult to efficiently and correctly 13 | compute this value. The function is provided as a useful and efficient convenience. 14 | 15 | * Do features in your specification expose the minimum amount of information necessary to enable their intended uses? 16 | 17 | Yes. 18 | 19 | * How do the features in your specification deal with personal information, personally-identifiable information (PII), or information derived from them? 20 | 21 | The feature does not deal with such information. 22 | 23 | * How do the features in your specification deal with sensitive information? 24 | 25 | The feature does not deal with such information. 26 | 27 | * Do the features in your specification introduce new state for an origin that persists across browsing sessions? 28 | 29 | No. 30 | 31 | * Do the features in your specification expose information about the underlying platform to origins? 32 | 33 | No. 34 | 35 | * Does this specification allow an origin to send data to the underlying platform? 36 | 37 | No. 38 | 39 | * Do features in this specification enable access to device sensors? 40 | 41 | No. 42 | 43 | * Do features in this specification enable new script execution/loading mechanisms? 44 | 45 | No. 46 | 47 | * Do features in this specification allow an origin to access other devices? 48 | 49 | No. 50 | 51 | * Do features in this specification allow an origin some measure of control over a user agent's native UI? 52 | 53 | No. 54 | 55 | * What temporary identifiers do the features in this specification create or expose to the web? 56 | 57 | None. 58 | 59 | * How does this specification distinguish between behavior in first-party and third-party contexts? 60 | 61 | This feature does not make a distinction between contexts, it acts on DOM state 62 | already available to the page, including closed shadow trees. 63 | 64 | * How do the features in this specification work in the context of a browser’s Private Browsing or Incognito mode? 65 | 66 | This feature does not make a distinction between regular or private browsing 67 | contexts. 68 | 69 | * Does this specification have both "Security Considerations" and "Privacy Considerations" sections? 70 | 71 | No. 72 | 73 | * Do features in your specification enable origins to downgrade default security protections? 74 | 75 | No. 76 | 77 | * How does your feature handle non-"fully active" documents? 78 | 79 | This feature does not make a dinstinction between fully active or non-fully 80 | active documents. 81 | 82 | * What should this questionnaire have asked? 83 | 84 | It asked all the necessary questions. 85 | -------------------------------------------------------------------------------- /resources/find-in-page/display_types_chrome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WICG/display-locking/1abded5a9e9bade0a11c22acc9e3b9c9e3c5eb48/resources/find-in-page/display_types_chrome.png -------------------------------------------------------------------------------- /resources/find-in-page/display_types_firefox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WICG/display-locking/1abded5a9e9bade0a11c22acc9e3b9c9e3c5eb48/resources/find-in-page/display_types_firefox.png -------------------------------------------------------------------------------- /resources/find-in-page/display_types_safari.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WICG/display-locking/1abded5a9e9bade0a11c22acc9e3b9c9e3c5eb48/resources/find-in-page/display_types_safari.png -------------------------------------------------------------------------------- /resources/find-in-page/occlusion_chrome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WICG/display-locking/1abded5a9e9bade0a11c22acc9e3b9c9e3c5eb48/resources/find-in-page/occlusion_chrome.png -------------------------------------------------------------------------------- /resources/find-in-page/occlusion_firefox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WICG/display-locking/1abded5a9e9bade0a11c22acc9e3b9c9e3c5eb48/resources/find-in-page/occlusion_firefox.png -------------------------------------------------------------------------------- /resources/find-in-page/occlusion_safari.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WICG/display-locking/1abded5a9e9bade0a11c22acc9e3b9c9e3c5eb48/resources/find-in-page/occlusion_safari.png -------------------------------------------------------------------------------- /resources/find-in-page/overflow_auto_chrome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WICG/display-locking/1abded5a9e9bade0a11c22acc9e3b9c9e3c5eb48/resources/find-in-page/overflow_auto_chrome.png -------------------------------------------------------------------------------- /resources/find-in-page/overflow_auto_firefox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WICG/display-locking/1abded5a9e9bade0a11c22acc9e3b9c9e3c5eb48/resources/find-in-page/overflow_auto_firefox.png -------------------------------------------------------------------------------- /resources/find-in-page/overflow_auto_safari.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WICG/display-locking/1abded5a9e9bade0a11c22acc9e3b9c9e3c5eb48/resources/find-in-page/overflow_auto_safari.png -------------------------------------------------------------------------------- /resources/find-in-page/overflow_hidden_chrome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WICG/display-locking/1abded5a9e9bade0a11c22acc9e3b9c9e3c5eb48/resources/find-in-page/overflow_hidden_chrome.png -------------------------------------------------------------------------------- /resources/find-in-page/overflow_hidden_firefox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WICG/display-locking/1abded5a9e9bade0a11c22acc9e3b9c9e3c5eb48/resources/find-in-page/overflow_hidden_firefox.png -------------------------------------------------------------------------------- /resources/find-in-page/overflow_hidden_safari.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WICG/display-locking/1abded5a9e9bade0a11c22acc9e3b9c9e3c5eb48/resources/find-in-page/overflow_hidden_safari.png -------------------------------------------------------------------------------- /resources/find-in-page/search-incremental.html: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 14 | 15 | 76 | -------------------------------------------------------------------------------- /resources/find-in-page/visibility_chrome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WICG/display-locking/1abded5a9e9bade0a11c22acc9e3b9c9e3c5eb48/resources/find-in-page/visibility_chrome.png -------------------------------------------------------------------------------- /resources/find-in-page/visibility_firefox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WICG/display-locking/1abded5a9e9bade0a11c22acc9e3b9c9e3c5eb48/resources/find-in-page/visibility_firefox.png -------------------------------------------------------------------------------- /resources/find-in-page/visibility_safari.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WICG/display-locking/1abded5a9e9bade0a11c22acc9e3b9c9e3c5eb48/resources/find-in-page/visibility_safari.png -------------------------------------------------------------------------------- /sample-code/collapsed-sections.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 53 | 54 |

Collapsed Sections Example

55 | 56 |
Summary
57 |
58 |

59 | In this examples, there is content that is considered above the fold, such as this text. 60 | It is visible on load and appears near the top of the page. It cannot be collapsed, as indicated 61 | by the asterisk next to the section title. Additional information is provided 62 | in sections located below. These sections are collapsed by default. They do not incur rendering 63 | cost since they are display-locked. However, they are still searchable via user interactions. For 64 | example, they are expandable by clicking the button next to the section title. They are also 65 | expandable via find-in-page. 66 |

67 |

68 | You can try this out by using find in page to find "github", for example. 69 |

70 |

71 | Note that render-subtree does not seem to be supported by your browser. This means 72 | that you will not be able to use find-in-page to navigate into collapsed sections. 73 |

74 |
75 | 76 | 86 | 87 | 88 | 95 | 133 | -------------------------------------------------------------------------------- /sample-code/contain-intrinsic-size-examples.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 63 | 64 |
65 | Note that the browser you are using does not support contain-intrinsic-size. The examples below will not demonstrate the intended effect. In order to see the difference in layouts, please enable contain-intrinsic-size support. On Chrome Canaray this can be done with --enable-blink-features=CSSIntrinsicSize command line flag. 66 |
67 |
68 |
Example 1: 69 |

In this example, the divs are not sized by anything so they naturally 70 | occupy all available width, and enough width to fit their content. 71 |

When 'contain: size' is added, the left-hand-side div does not consider its 72 | children for sizing. This means it still takes up all available width, but 73 | 0 height. The right-hand-side element, however, starts using 74 | contain-intrinsic-size as its intrinsic size, so it still takes up all of 75 | the width but sizes the height to its contain-intrinsic-size height. 76 |

77 |
without contain-intrinsic-size
78 |
with contain-intrinsic-size: 100px 75px
79 |
80 |
This is sample content
81 |
82 |
83 |
This is sample content
84 |
85 | 86 |
87 | 88 | 93 |
94 |
Example 2: 95 |

In this example, the elements's width is sized to max-content. This means 96 | that it will use the intrinsic size information when determining the size. 97 | However, when size containment is applied, the child information cannot be 98 | used. 99 |

With size containment, the left hand size element becomes 0 width and 0 100 | height (and its content is laid out with overflow). The right hand side 101 | element uses the contain-intrinsic-size and sizes both the width and the 102 | height to the specified size. 103 |

104 |
without contain-intrinsic-size
105 |
with contain-intrinsic-size: 100px 75px
106 |
107 |
This is sample content
108 |
109 |
110 |
This is sample content
111 |
112 | 113 |
114 | 115 | 121 |
122 |
Example 3: 123 |

In this example, the elements are explicitly sized. They have 250px width 124 | and 150px height. Size containment has no effect, since the specified size takes 125 | priority. 126 |

127 |
without contain-intrinsic-size
128 |
with contain-intrinsic-size: 100px 75px
129 |
130 |
This is sample content
131 |
132 |
133 |
This is sample content
134 |
135 | 136 |
137 | 138 | 156 |
157 |
Example 4: 158 |

This example demonstrates why this feature is useful. Note that there are 159 | enough elements to be scrollable here. It is important to 160 | note that in this example, when we add size containment we only do 161 | it for off-screen elements (as determined by an intersection observer). To 162 | put it differently, when "add 'contain: size'" is pressed, the size containment 163 | will start being added and removed automatically based on screen visibility. 164 | 165 |

Note that on the left hand size, the experience of scrolling is not great, 166 | because offscreen elements are 0 sized (with border). However, although the 167 | height for contain-intrinsic-size is a rough estimate, the scrolling 168 | experience is much better. 169 | 170 |

Here, the effect is achieved by intersection observer. However, it can 171 | also be achieved automatically by simply specifying content-visibility: auto. 172 | This example demonstrates how important contain-intrinsic-size is when used 173 | with content-visibility: auto. 174 | 175 |

Note that the experience can be made better with improved estimates of the 176 | sizes without the worry of specifying a value that is too large. A 177 | large value with height or min-height would have noticeable (and visibly broken to the user) consequences on 178 | visible content (assuming the property is added unconditionally). The 179 | contain-intrinsic-size property, however, is ignored when size containment is 180 | not present. 181 |

182 |
without contain-intrinsic-size
183 |
with contain-intrinsic-size: 100px 30px
184 |
185 |
0. This is sample content
186 |
1. This is sample content
187 |
2. This is sample content
188 |
3. This is sample content
189 |
4. This is sample content
190 |
5. This is sample content
191 |
6. This is sample content
192 |
7. This is sample content
193 |
8. This is sample content
194 |
9. This is sample content
195 |
10. This is sample content
196 |
11. This is sample content
197 |
12. This is sample content
198 |
13. This is sample content
199 |
14. This is sample content
200 |
15. This is sample content
201 |
16. This is sample content
202 |
17. This is sample content
203 |
18. This is sample content
204 |
19. This is sample content
205 |
20. This is sample content
206 |
21. This is sample content
207 |
22. This is sample content
208 |
23. This is sample content
209 |
24. This is sample content
210 |
25. This is sample content
211 |
26. This is sample content
212 |
27. This is sample content
213 |
28. This is sample content
214 |
29. This is sample content
215 |
216 |
217 |
0. This is sample content
218 |
1. This is sample content
219 |
2. This is sample content
220 |
3. This is sample content
221 |
4. This is sample content
222 |
5. This is sample content
223 |
6. This is sample content
224 |
7. This is sample content
225 |
8. This is sample content
226 |
9. This is sample content
227 |
10. This is sample content
228 |
11. This is sample content
229 |
12. This is sample content
230 |
13. This is sample content
231 |
14. This is sample content
232 |
15. This is sample content
233 |
16. This is sample content
234 |
17. This is sample content
235 |
18. This is sample content
236 |
19. This is sample content
237 |
20. This is sample content
238 |
21. This is sample content
239 |
22. This is sample content
240 |
23. This is sample content
241 |
24. This is sample content
242 |
25. This is sample content
243 |
26. This is sample content
244 |
27. This is sample content
245 |
28. This is sample content
246 |
29. This is sample content
247 |
248 | 249 |
250 | 251 | 291 | -------------------------------------------------------------------------------- /sample-code/css-collapsed-sections.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 167 | 168 | 171 |
172 |

Note that this is a demo page of direct integration of render-subtree property with Wikipedia.

173 |
174 |
175 |
176 |
177 |

Wikipedia

178 |
179 |
180 |
181 | This article is about the online encyclopedia. For Wikipedia's home page, 182 | see Main Page. For Wikipedia's visitor introduction, see Wikimedia:About. 183 | For other uses, see Wikipedia (disambiguation). 184 |
185 |
186 | "The Free Encyclopedia" redirects here. For other encyclopedias, see Lists 187 | of encyclopedias. 188 |
189 |

190 | Wikipedia (/ˌwɪkɪˈpiːdiə/ (listen) wik-ih-PEE-dee-ə or /ˌwɪkiˈpiːdiə/ 191 | (listen) wik-ee-PEE-dee-ə) is a multilingual online encyclopedia created and 192 | maintained as an open collaboration project[3] by a community of volunteer 193 | editors using a wiki-based editing system.[4] It is the largest and most 194 | popular general reference work on the World Wide Web,[5][6][7] and is one of 195 | the most popular websites ranked by Alexa as of October 2019.[8] It features 196 | exclusively free content and no commercial ads, and is owned and supported 197 | by the Wikimedia Foundation, a non-profit organization funded primarily 198 | through donations.[9][10][11][12] 199 |

200 | 201 | 202 | 203 | 208 | 211 | 212 | 213 | 218 | 221 | 222 | 223 | 228 | 231 | 232 | 233 | 238 | 242 | 243 | 244 | 249 | 252 | 253 | 254 | 259 | 262 | 263 | 264 | 269 | 272 | 273 | 274 | 279 | 282 | 283 | 284 | 289 | 293 | 294 | 295 | 300 | 303 | 304 | 305 | 310 | 313 | 314 | 315 | 320 | 324 | 325 | 326 | 331 | 334 | 335 | 336 | 341 | 344 | 345 |
Wikipedia
204 |
205 | Type of site 206 |
207 |
209 | Online encyclopedia 210 |
214 |
215 | Available in 216 |
217 |
219 | 307 languages 220 |
224 |
225 | Owner 226 |
227 |
229 | Wikimedia Foundation 230 |
234 |
235 | Created by 236 |
237 |
239 | Jimmy Wales
240 | Larry Sanger[1] 241 |
245 |
246 | Website 247 |
248 |
250 | www.wikipedia.org 251 |
255 |
256 | Alexa rank 257 |
258 |
260 | 9 (Global, November 2019) 261 |
265 |
266 | Commercial 267 |
268 |
270 | No 271 |
275 |
276 | Registration 277 |
278 |
280 | Optional[note 1] 281 |
285 |
286 | Users 287 |
288 |
290 | >313,871 active users[note 2] and >85,534,289 291 | registered users 1,145 administrators (English) 292 |
296 |
297 | Launched 298 |
299 |
301 | January 15, 2001; 18 years ago 302 |
306 |
307 | Current status 308 |
309 |
311 | Active 312 |
316 |
317 | Content license 318 |
319 |
321 | CC Attribution / Share-Alike 3.0
322 | Most text is also dual-licensed under GFDL; media licensing varies. 323 |
327 |
328 | Written in 329 |
330 |
332 | LAMP platform[2] 333 |
337 |
338 | OCLC number 339 |
340 |
342 | 52075003 343 |
346 |

347 | Wikipedia was launched on January 15, 2001, by Jimmy Wales and Larry 348 | Sanger.[13] Sanger coined its name,[14][15] as a portmanteau of "wiki" 349 | (the Hawaiian word for "quick"[16]) and "encyclopedia". While it was 350 | Initially an English-language encyclopedia, versions in other languages 351 | were quickly developed. With at least 5,972,764 articles,[note 3] the 352 | English Wikipedia is the largest of the more than 290 Wikipedia 353 | encyclopedias. Overall, Wikipedia comprises more than 40 million 354 | articles in 301 different languages[17] and by February 2014 it had 355 | reached 18 billion page views and nearly 500 million unique visitors 356 | per month.[18] 357 |

358 |

359 | In 2005, Nature published a peer review comparing 42 hard science 360 | articles from Encyclopædia Britannica and Wikipedia and found that 361 | Wikipedia's level of accuracy approached that of Britannica,[19] 362 | although critics suggested that it might not have fared so well in a similar 363 | study of a random sampling of all articles or one focused on social science 364 | or contentious social issues.[20][21] The following year, 365 | Time magazine stated that the open-door policy of allowing anyone 366 | to edit had made Wikipedia the biggest and possibly the best encyclopedia 367 | in the world, and was a testament to the vision of Jimmy Wales.[22] 368 |

369 |

370 | Wikipedia has been criticized for exhibiting systemic bias, for presenting 371 | a mixture of "truth, half truth, and some falsehoods",[23] and 372 | for being subject to manipulation and spin in controversial topics.[24] 373 | In addition, Wikipedia has gender bias, particularly on its English-language 374 | site, where the dominant majority of editors are male. However, Edit-a-thons 375 | have been held to encourage female editors and increase the coverage of 376 | women's topics.[25][26] Facebook announced that by 2017 it would 377 | help readers detect fake news by suggesting links to related Wikipedia 378 | articles. YouTube announced a similar plan in 2018.[27] 379 |

380 | 381 |

382 |
383 | History 384 |

385 | 388 | 553 | 554 |

555 |
556 | Openness 557 |

558 | 561 | 677 | 678 |

679 |
680 | Policies and laws 681 |

682 | 685 | 723 | 724 |
725 | 726 | 744 | -------------------------------------------------------------------------------- /sample-code/tabbed-ui.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 72 | 73 |
74 |
75 |
tab one
76 |
tab two
77 |
tab three
78 |
79 |
80 |
81 | Contents of tab one. 82 | Note that with render-subtee, we can use find-in-page 83 | to find contents of tabs two and three. 84 |

Unfortunatelly, your browser does not 85 | support render-subtree

86 |
87 |
88 | Contents of tab two. 89 |
90 |
91 | Contents of tab three. 92 |
93 |
94 |
95 | 96 | 138 | -------------------------------------------------------------------------------- /w3c.json: -------------------------------------------------------------------------------- 1 | { 2 | "group": [80485] 3 | , "contacts": ["marcoscaceres"] 4 | , "repo-type": "cg-report" 5 | } 6 | --------------------------------------------------------------------------------