Skip to content

[css-view-transitions-1] Add snapshot viewport concept #8037

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from
Nov 16, 2022

Conversation

jakearchibald
Copy link
Contributor

I also tried to tighten up the language around the document element capture.

@jakearchibald jakearchibald added the css-view-transitions-1 View Transitions; Bugs only label Nov 7, 2022
Comment on lines 823 to 833
1. Render the region of the [=document element=] that intersects the [=snapshot viewport=],
on a transparent canvas the size of the [=snapshot viewport=],
following the [=capture rendering characteristics=], and these additional characteristics:

- Areas outside the [=scrolling box=] should be rendered as if they were scrolled to, without moving the [=layout viewport=].
This must not trigger events related to scrolling or resizing, such as {{IntersectionObserver}}s.

Issue: "scrolling box" and "layout viewport" are not exported. They either need exporting, or replaced with better references.

* The origin of |element|'s [=ink overflow rectangle=] is anchored to canvas origin.
- Areas that cannot be scrolled to (i.e. they are out of scrolling bounds),
should render transparent.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bramus what's your take on this? I'm not sure if I'm using the right language.

I'm trying to say that, if the keyboard is open, and it's changed the size of the viewport, we should capture the area under the keyboard as if it were removed, but the layout viewport stayed the same size.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The css-viewport spec speaks of “interactive widgets”. I guess you could simply say “areas obscured by interactive widgets should render transparent”, and leave the definition up to the css-viewport spec.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure we want them to render transparent though. I was trying to clarify that with the "Areas outside the [=scrolling box=] should be rendered as if they were scrolled to" language.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I see. Was (incorrectly) focussing on the last line there. The way you worded things in your comment is much clearer than the text currently in the spec.

My hunch would be to try to include a reference to the interactive widgets. Does “the presence of interactive widgets and their effects on layout are taken into account when rendering“ capture it? Possibly, explicitly also mention that this implies that areas obscured by the interactive widgets do get rendered if they are in the snapshot viewport, and that no scroll/resize events get triggered.

@@ -393,6 +393,30 @@ urlPrefix: https://wicg.github.io/navigation-api/; type: interface;
:: a boolean. Initially false.
</dl>

## The snapshot viewport ## {#snapshot-viewport-concept}

The <dfn>snapshot viewport</dfn> covers all areas of the window that could potentially display web content. This area is consistent regardless of transitionary UI that overlays content, or reduces the size of other viewports, such as scrollbars, virtual keyboards, or URL bars that can be scrolled away.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Break at "This area is..." for semantic line-feed. Probably the same at, ", or reduces the..."

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, good catch. I think there are a few other places I didn't correctly apply the formatting too,


* The origin of |element|'s [=ink overflow rectangle=] is anchored to canvas origin.
- Areas that cannot be scrolled to (i.e. they are out of scrolling bounds),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you share an example for this case.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On mobile, when the document is scrolled to the very top, the URL bar is not overlaying content. I assume the same can happen with the bottom of the page when the keyboard is open.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it.

The resolution was that we won't paint occluded elements which can't be scrolled to but the root element background will be painted there. For example if an element has the following CSS:

position: fixed;
top: -10px;
left: -10px;

It could be occluded by the URL bar and the user can't scroll to it. So we should skip painting this element, but the area should have the root element background. That could be a color or a repeated image.

The current spec text indicates that this area should be transparent.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LG other than updating for this. phone-browser-scrolled-to-top-with-url.svg also shows that the area under the URL bar in the snapshot is transparent but we should paint the root background there (it should have the blue color).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hah, I'd forgotten to push. Done!

@jakearchibald
Copy link
Contributor Author

@bramus @khushalsagar I've added some diagrams to explain the captured area. Does it make more sense now?

@bramus
Copy link
Contributor

bramus commented Nov 8, 2022

The diagrams make it much clearer; nice!

Copy link
Member

@khushalsagar khushalsagar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking great. The diagrams are awesome!


* The origin of |element|'s [=ink overflow rectangle=] is anchored to canvas origin.
- Areas that cannot be scrolled to (i.e. they are out of scrolling bounds),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it.

The resolution was that we won't paint occluded elements which can't be scrolled to but the root element background will be painted there. For example if an element has the following CSS:

position: fixed;
top: -10px;
left: -10px;

It could be occluded by the URL bar and the user can't scroll to it. So we should skip painting this element, but the area should have the root element background. That could be a color or a repeated image.

The current spec text indicates that this area should be transparent.

@jakearchibald
Copy link
Contributor Author

@khushalsagar

Mind including the note about the filter/opacity effects too. It's very subtle that these effects are in the snapshot as opposed to on the pseudo tree generated by the transition.

It feels like the wrong place to talk about the rendering of the view transition layer.

There's already an issue in the section that documents the view transition layer:

Issue: Do we need to clarify that the stacking context for the root and top layer elements has filters and effects coming from the document element's style?

* [=list/For each=] |descendant| of [=shadow-including descendant=] {{Element}} and [=pseudo-element=] of |element|,
if |descendant| has a [=computed value=] of 'view-transition-name' that is not ''view-transition-name/none'',
then skip painting |descendant|.

Note: This is necessary since the descendant will generate its own snapshot which will be displayed and animated independently.

Issue: Refactor this so the algorithm takes a set of elements that will be captured. This centralizes the logic for deciding if an element should be included or not.

Issue: Specify what happens with 'mix-blend-mode'.
Copy link
Member

@khushalsagar khushalsagar Nov 10, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's ignored. This property is only relevant when blending an element into its target and doesn't need to impact the snapshot. How this snapshot is blended into its target is determined by the pseudo-element hosting it.

You can leave a non-normative note to clarify.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why non-normative rather than normative?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I figured it's implicit because mix-blend-mode is only relevant when an element is drawn into its target. The UA styles we add on the pseudo-element is because the corresponding DOM element's mix-blend-mode might not be accurate for what's needed during the transition. So what else could we do with the DOM element's mix-blend-mode.

I'm fine with normative text for this too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be more correct to say the element is rendered within a new stacking context? That effectively ignores mix-blend-mode on the root, but explains what happens for mix-blend-mode on inner elements.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because we require layout containment, each snapshotted element already has its own stacking context. The mix-blend-mode applies when this stacking context is drawn into its target stacking context. For View Transitions we take that stacking context's output as the snapshot and host it on the pseudo-element. Since we never draw the element's stacking context into its target, this property is effectively ignored.

The text about skipping painting of the DOM element's stacking context into its actual target is here btw: https://drafts.csswg.org/css-view-transitions-1/#create-transition-pseudo-elements:~:text=The%20new%20element%20and,none)%20until%20new%20exists. Feel free to send a PR to make this explicit.

@bramus
Copy link
Contributor

bramus commented Nov 10, 2022

Before this get merged, I want to point attention to the suggestion in #8037 (comment)

@@ -225,8 +225,8 @@ urlPrefix: https://wicg.github.io/navigation-api/; type: interface;
```

Note: This pseudo-element provides a containing block for all ''::view-transition-group()'' pseudo-elements.
The aim of the style is to size the pseudo-element to cover the [=large viewport size=]
and position all ''::view-transition-group()'' pseudo-elements relative to the origin of the large viewport.
The aim of the style is to size the pseudo-element to cover the [=snapshot viewport=]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just realized this PR missed the part about UA styles on this pseudo-element. inset: 0 is no longer correct.

  • The first part is updating the style block for html::view-transition to:

       position: fixed;
       top: 0;
       left: 0;
  • The second part is to add a point in Style transition pseudo-elements algorithm. Something like:

    1. Let |root| be the ''::view-transition'' pseudo-element.
      1. Set "width" and "height" to snapshot viewport bounds.
      2. Set "transform" to a CSS transform that would place element at snapshot viewport origin.

@jakearchibald
Copy link
Contributor Author

I've specified that the view-transition stacking layer covers the snapshot viewport, assuming we'll resolve on option 2 in #8070. I'll change the spec if things resolve differently.

@@ -336,6 +339,38 @@ urlPrefix: https://wicg.github.io/navigation-api/; type: interface;
It is, however, important to understand what steps happen in each of the phases: when the snapshots are captured, when pseudo-element DOM is created, etc.
The description of the phases below tries to be as precise as possible, with an intent to provide an unambiguous set of steps for implementors to follow in order to produce a spec-compliant implementation.

## The snapshot viewport ## {#snapshot-viewport-concept}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation looks off.

Copy link
Member

@khushalsagar khushalsagar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

@jakearchibald jakearchibald merged commit be01ea4 into w3c:main Nov 16, 2022
@jakearchibald jakearchibald deleted the viewport branch November 16, 2022 16:23
jakearchibald added a commit to jakearchibald/csswg-drafts that referenced this pull request Jan 16, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
css-view-transitions-1 View Transitions; Bugs only
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants