Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

feat: Editorial review: Add content for overlay and discrete animation features #29943

Merged
merged 36 commits into from
Nov 20, 2023
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
0c09617
feat: Add content for overlay and discrete animation features
chrisdavidmills Sep 11, 2023
25f6a67
Add rest of required updates
chrisdavidmills Sep 13, 2023
8cc056f
Merge branch 'main' into overlay-discrete-animations
chrisdavidmills Sep 27, 2023
8fdd02c
Improving popover transition examples based on josepharhar feedback
chrisdavidmills Sep 27, 2023
31142db
improve popover keyframe example with beforetoggle
chrisdavidmills Oct 10, 2023
44363dd
Merge branch 'main' into overlay-discrete-animations
chrisdavidmills Oct 10, 2023
3e5bd55
Merge branch 'main' into overlay-discrete-animations
chrisdavidmills Oct 31, 2023
39f6bb2
Merge branch 'main' into overlay-discrete-animations
chrisdavidmills Nov 1, 2023
cc7e120
Making fixes for OnkarRuikar comments
chrisdavidmills Nov 1, 2023
d9365ad
Apply fixes based on estelle and dipikabh comments
chrisdavidmills Nov 2, 2023
b6368b0
mre fixes for estelle and OnkarRuikar comments
chrisdavidmills Nov 6, 2023
012fad4
Merge branch 'main' into overlay-discrete-animations
chrisdavidmills Nov 6, 2023
0296fb0
Making fixes for next round of estelle comments
chrisdavidmills Nov 7, 2023
48ae18f
Merge branch 'main' into overlay-discrete-animations
chrisdavidmills Nov 7, 2023
d8727bb
Fixes for next round of estelle comments
chrisdavidmills Nov 8, 2023
e83cce9
Merge branch 'main' into overlay-discrete-animations
chrisdavidmills Nov 9, 2023
41105a8
comma
estelle Nov 13, 2023
b289c4a
Update files/en-us/web/api/cssstartingstylerule/index.md
chrisdavidmills Nov 14, 2023
506100e
Update files/en-us/web/api/cssstartingstylerule/index.md
chrisdavidmills Nov 14, 2023
e2937ee
Update files/en-us/web/api/popover_api/using/index.md
chrisdavidmills Nov 14, 2023
1be535b
Update files/en-us/web/api/popover_api/using/index.md
chrisdavidmills Nov 14, 2023
657a296
Update files/en-us/web/api/popover_api/using/index.md
chrisdavidmills Nov 14, 2023
d8169d1
Update files/en-us/web/css/@starting-style/index.md
chrisdavidmills Nov 14, 2023
c0bb544
Update files/en-us/web/css/@starting-style/index.md
chrisdavidmills Nov 14, 2023
b461119
Merge branch 'main' into overlay-discrete-animations
chrisdavidmills Nov 14, 2023
465deb6
Fixes for estelle latest comments, add more examples on @starting-sty…
chrisdavidmills Nov 14, 2023
0aee741
Merge branch 'main' into overlay-discrete-animations
chrisdavidmills Nov 14, 2023
a451388
More fixes for estelle comments
chrisdavidmills Nov 15, 2023
4023e96
More estelle fixes
chrisdavidmills Nov 16, 2023
086c494
Merge branch 'main' into overlay-discrete-animations
chrisdavidmills Nov 16, 2023
beb0532
More estelle and Onkar comment fixes
chrisdavidmills Nov 20, 2023
74cea43
Merge branch 'main' into overlay-discrete-animations
chrisdavidmills Nov 20, 2023
6bc44bf
Update descriptions in light of content-visibility transitions not ne…
chrisdavidmills Nov 20, 2023
44c146e
Merge branch 'overlay-discrete-animations' of github.com:chrisdavidmi…
chrisdavidmills Nov 20, 2023
9609659
Merge branch 'main' into overlay-discrete-animations
chrisdavidmills Nov 20, 2023
197b3d9
Merge branch 'main' into overlay-discrete-animations
chrisdavidmills Nov 20, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions files/en-us/web/api/cssstartingstylerule/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
title: CSSStartingStyleRule
slug: Web/API/CSSStartingStyleRule
page-type: web-api-interface
browser-compat: api.CSSStartingStyleRule
---

{{ APIRef("CSSOM") }}

The **`CSSStartingStyleRule`** interface of the [CSS Object Model](/en-US/docs/Web/API/CSS_Object_Model) represents a CSS {{CSSxRef("@starting-style")}} at-rule.

{{InheritanceDiagram}}

## Instance properties

_This interface inherits properties from its parent, {{domxref("CSSGroupingRule")}}._

## Instance methods

_This interface inherits methods from its parent, {{domxref("CSSGroupingRule")}}._

## Specifications

{{Specifications}}

## Browser compatibility

{{Compat}}

## See also

- {{CSSxRef("@starting-style")}}
- [CSS transitions](/en-US/docs/Web/CSS/CSS_transitions) module
- [Using dynamic styling information](/en-US/docs/Web/API/CSS_Object_Model/Using_dynamic_styling_information)
estelle marked this conversation as resolved.
Show resolved Hide resolved
209 changes: 208 additions & 1 deletion files/en-us/web/api/popover_api/using/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -301,4 +301,211 @@ The {{cssxref("::backdrop")}} pseudo-element is a full-screen element placed dir

See our [Popover blur background example](https://mdn.github.io/dom-examples/popover-api/blur-background/) ([source](https://github.com/mdn/dom-examples/tree/main/popover-api/blur-background)) for an idea of how this renders.

Finally, animation needs a special mention, as a lot of people are going to want to animate popovers between showing and hiding. As it stands, [a few updates to CSS behavior](https://open-ui.org/components/popover.research.explainer/#animation-of-popovers) are required to get popovers to be animatable, most notably enabling animation of elements as they move to and from `display: none`. We'll update this article as soon as animation is available for popovers.
## Animating popovers

Popovers are set to `display: none;` when hidden and `display: block;` when shown, as well as being removed from / added to the {{glossary("top layer")}} and the [accessibility tree](/en-US/docs/Web/Performance/How_browsers_work#building_the_accessibility_tree). Therefore, for popovers to be animated, the {{cssxref("display")}} property needs to be animatable. [Supporting browsers](/en-US/docs/Web/CSS/display#browser_compatibility) animate `display` with a variation on the [discrete animation type](/en-US/docs/Web/CSS/CSS_animated_properties#discrete). Specifically, the browser will flip between `none` and another value of `display` so that the animated content is shown for the entire animation duration. So, for example:

- When animating `display` from `none` to `block` (or another visible `display` value), the value will flip to `block` at `0%` of the animation duration so it is visible throughout.
- When animating `display` from `block` (or another visible `display` value) to `none`, the value will flip to `none` at `100%` of the animation duration so it is visible throughout.

> **Note:** When animating using [CSS transitions](/en-US/docs/Web/CSS/CSS_transitions), [`transition-behavior: allow-discrete`](/en-US/docs/Web/CSS/transition-behavior) needs to be set to enable the above behavior. When animating with [CSS animations](/en-US/docs/Web/CSS/CSS_animations), the above behavior is available by default; an equivalent step is not required.

### Transitioning a popover

When animating popovers with CSS transitions, the following features are required:

- {{CSSxRef("@starting-style")}} at-rule
- : Provides a set of starting values for properties set on the popover that you want to transition from when it is first shown. This is needed to avoid unexpected behavior. By default, CSS transitions only occur when a property changes from one value to another on a visible element; they are not triggered on an element's first style update, or when the `display` type changes from `none` to another type.
- {{CSSxRef("display")}} property
- : Add `display` to the transitions list so that the popover will remain as `display: block` (or another visible `display` value) for the duration of the transition, ensuring the other transitions are visible.
Copy link
Member

Choose a reason for hiding this comment

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

Optional: add that the display value, if other than block, should be in the :popover-open state, otherwise the default display none; will be overridden

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'd rather leave it out from here, as I think it might confuse more than it helps. Also, given that display is animated in several places, maybe we could deal with such details just on the display page where I talk about animating display, rather than in several places.

- {{CSSxRef("overlay")}} property
- : Include `overlay` in the transitions list to ensure the removal of the popover from the top layer is deferred until the transition completes, again ensuring the transition is visible.
estelle marked this conversation as resolved.
Show resolved Hide resolved
- {{cssxref("transition-behavior")}} property
- : Set `transition-behavior: allow-discrete` on the `display` and `overlay` transitions (or on the {{cssxref("transition")}} shorthand) to enable discrete transitions on these two properties that are not by default animatable.

Let's have a look at an example so you can see what this looks like:

#### HTML

The HTML contains a {{htmlelement("div")}} element declared to be a popover via the global [`popover`](/en-US/docs/Web/HTML/Global_attributes/popover) HTML attribute, and a {{htmlelement("button")}} element designated as the popover's display control:

```html
<button popovertarget="mypopover">Show the popover</button>
<div popover="auto" id="mypopover">I'm a Popover! I should animate.</div>
```

#### CSS

The two popover properties we want to transition are [`opacity`](/en-US/docs/Web/CSS/opacity) and [`transform`](/en-US/docs/Web/CSS/transform). We want the popover to fade in or out while growing or shrinking horizontally. To achieve this, we set a starting state for these properties on the hidden state of the popover element (selected with the `[popover]` [attribute selector](/en-US/docs/Web/CSS/Attribute_selectors)) and an end state for the shown state of the popover (selected via the [`:popover-open`](/en-US/docs/Web/CSS/:popover-open) pseudo-class). We also use the [`transition`](/en-US/docs/Web/CSS/transition) property to define the properties to animate and the animation's duration as the popover gets shown or hidden.

```css
html {
font-family: Arial, Helvetica, sans-serif;
}

/* Transition for the popover itself */

[popover]:popover-open {
opacity: 1;
transform: scaleX(1);
}

[popover] {
font-size: 1.2rem;
padding: 10px;

/* Final state of the exit animation */
opacity: 0;
transform: scaleX(0);

transition:
opacity 0.7s,
transform 0.7s,
overlay 0.7s allow-discrete,
display 0.7s allow-discrete;
/* Equivalent to
transition: all 0.7s allow-discrete; */
}
estelle marked this conversation as resolved.
Show resolved Hide resolved

/* Needs to be after the previous [popover]:popover-open rule
to take effect, as the specificity is the same */
@starting-style {
[popover]:popover-open {
opacity: 0;
transform: scaleX(0);
}
}

/* Transition for the popover's backdrop */

[popover]::backdrop {
background-color: rgb(0 0 0 / 0);
transition:
display 0.7s allow-discrete,
overlay 0.7s allow-discrete,
background-color 0.7s;
/* Equivalent to
transition: all 0.7s allow-discrete; */
}

[popover]:popover-open::backdrop {
background-color: rgb(0 0 0 / 0.25);
}

/* The nesting selector (&) cannot represent pseudo-elements
so this starting-style rule cannot be nested */

@starting-style {
[popover]:popover-open::backdrop {
background-color: rgb(0 0 0 / 0);
}
}
```

As discussed earlier, we have also:

- Set a starting state for the `transition` inside the `@starting-style` block.
- Added `display` to the list of transitioned properties so that the animated element is visible (set to `display: block`) throughout the popover's entry and exit animations. Without this, the exit animation would not be visible; in effect, the popover would just disappear.
- Added `overlay` to the list of transitioned properties to make sure that the removal of the element from the top layer is deferred until the animation has been completed. The effect of this may not be noticeable for basic animations such as this one, but in more complex cases, omitting this property can result in the element being removed from the overlay before the transition completes.
- Set `allow-discrete` on both properties in the above transitions to enable [discrete transitions](/en-US/docs/Web/CSS/CSS_animated_properties#discrete).

You'll note that we've also included a transition on the [`::backdrop`](/en-US/docs/Web/CSS/::backdrop) appearing behind the popover when it opens, providing a nice darkening animation.

#### Result

The code renders as follows:

{{ EmbedLiveSample("Transitioning a popover", "100%", "200") }}

Copy link
Member

@estelle estelle Nov 13, 2023

Choose a reason for hiding this comment

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

Suggested change
Because the popover is transitioning from `display: none` to `display: block, every time the popover opens, it transitions from the `@start-style` styles to the`[popover]:popover-open` styles. When the popover exits, it transitions from `[popover]:popover-open` state to the default `[popover]` state.

I think it's important to delineate that every time it opens it goes to start-style, not just the first time.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agreed that we need to make this clear. I've added these notes in appropriate places.

I've also added an explanatory section and an example to the @starting-style page to explain and demonstrate the behavior. I've linked the notes in other places to the example so it can be seen in action.

> **Note:** Because popovers change from `display: none` to `display: block` each time they are shown, the popover transitions from its `@starting-style` styles to its `[popover]:popover-open` styles every time the entry transition occurs. When the popover closes, it transitions from its `[popover]:popover-open` state to the default `[popover]` state.
>
> It is possible for the style transition on entry and exit to be different in such cases. See our [Demonstration of when starting styles are used](/en-US/docs/Web/CSS/@starting-style#demonstration_of_when_starting_styles_are_used) example for a proof of this.

### A popover keyframe animation

When animating a popover with CSS keyframe animations, there are some differences to note:

- You don't provide a `@starting-style`; instead, you provide the starting values in an explicit keyframe (using `0%` or `from`). Also, include a visible `display` value.
- You don't explicitly enable discrete animations; there is no equivalent to `allow-discrete` inside keyframes.
- You don't need to set `overlay` inside keyframes either; the `display` animation handles the animation of the popover from shown to hidden.

Let's look at an example.

#### HTML

The HTML contains a {{htmlelement("div")}} element declared as a popover, and a {{htmlelement("button")}} element designated as the popover's display control:

```html
<button popovertarget="mypopover">Show the popover</button>
<div popover="auto" id="mypopover">I'm a Popover! I should animate.</div>
```

#### CSS

We have defined keyframes that specify the desired entry and exit animations, and an entry animation for the backdrop only. Note that it wasn't possible to animate the backdrop fade out — the backdrop is immediately removed from the DOM when the popover is closed, so there is nothing to animate.

```css
html {
font-family: Arial, Helvetica, sans-serif;
}

[popover] {
font-size: 1.2rem;
padding: 10px;
animation: fade-out 0.7s ease-out;
}

[popover]:popover-open {
animation: fade-in 0.7s ease-out;
}

[popover]:popover-open::backdrop {
estelle marked this conversation as resolved.
Show resolved Hide resolved
animation: backdrop-fade-in 0.7s ease-out forwards;
}

/* Animation keyframes */

@keyframes fade-in {
0% {
opacity: 0;
transform: scaleX(0);
}

100% {
opacity: 1;
transform: scaleX(1);
}
}

@keyframes fade-out {
0% {
opacity: 1;
transform: scaleX(1);
/* display needed on the closing animation to keep the popover
visible until the animation ends */
display: block;
}

100% {
opacity: 0;
transform: scaleX(0);
display: none;
Copy link
Member

Choose a reason for hiding this comment

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

The display none is not actually required as that is the browser default value for a closed popover.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yup, but as mentioned previously, I think it is easier to understand the keyframes if you are more explicit and leave the start and end value in. So I'd like to leave this one as-is.

Copy link
Member

Choose a reason for hiding this comment

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

we should add a note about it then.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Note added

}
}

@keyframes backdrop-fade-in {
0% {
background-color: rgb(0 0 0 / 0);
}

100% {
background-color: rgb(0 0 0 / 0.25);
Copy link
Member

@estelle estelle Nov 13, 2023

Choose a reason for hiding this comment

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

this looks like it should make everything inert, including the toggle for the popover. Consider changing the color or lightening it (for both the transition and the animation example)

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've fixed this example differently, as I'd rather not mess with the styling. I've changed all instances to talk about displaying, not toggling. I've made sure all the examples use auto popovers, not manual, so the popover can be light-dismissed (by clicking outside it and pressing the Esc key). And I've changed the label of the button to "Show the popover".

You can still dismiss the popover by clicking the toggle button again, as it is a popover toggle by default. But now, even if people think the contents behind the popover are inert, it doesn't matter because that state can easily be escaped from.

}
}
```

estelle marked this conversation as resolved.
Show resolved Hide resolved
#### Result

The code renders as follows:

{{ EmbedLiveSample("A popover keyframe animation", "100%", "200") }}
Loading