Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

[css-display] Interaction gotchas when delaying the effect of display: none #8389

Open
jakearchibald opened this issue Feb 1, 2023 · 19 comments

Comments

@jakearchibald
Copy link
Contributor

jakearchibald commented Feb 1, 2023

TL;DR: This is a follow-on from #6429 (comment), which proposes making display animatable, to aid in creating "transition-out" animations.

This issue proposes:

  • Adding an inert property to CSS, and explaining the inert HTML attribute on top of that.
  • Making elements that are animating to display: none inert for the duration of the animation.

Let's say the JavaScript developer on a project creates a dialog/form, and when the form is submitted, the form is hidden via display: none, and the result of the form is used somehow in the app.

Then, at some later point, the CSS developer adds a transition which extends the interactive life of the element beyond what the JavaScript developer expected (the JavaScript developer and CSS developer may be the same person, but their mindset may be different when working with styles vs script).

This can be done already today, by overriding the default display: none on <dialog> elements (https://jsbin.com/xumitir/edit?html,css,js,output), but animating display: none, as proposed in #6429 (comment), creates an even more attractive, less-hacky way to do this.

By doing this, the CSS developer has created a significant change to the behaviour of the app. The user can now provide more than one submission to the form, since its lifetime in the app has been extended. This user action might be intentional (clicking the 'wrong' thing, then quickly clicking the right thing) or unintentional (double clicking).

Additionally, the element exists for longer in the accessibility tree, even though the intention is that it's 'gone'. This would result in unexpected behaviour for screen reader users.

These issues wasn't a possibility when the JavaScript developer created the form, so it's possible that these new interactions will be badly handled. The solution is to cater for interactions with the form beyond its previous lifecycle, or to prevent further interactions and AT visibility of the form using inert.

I think this is worth thinking about for two reasons:

  • It's difficult to catch bugs resulting from this in development. My experience is developers rarely correctly cater for the extended lifetime of interactive elements during transitions-away.
  • The issue is introduced by CSS, and the only way to fix it is in JS (pointer-events: none is an incomplete fix).

Potential solutions:

Education

We tell developers about this problem, and how to solve it in JavaScript. However, I have low confidence that we'd reach everyone, and even when it comes to folks we'd reach, would they remember to avoid these bugs?

Allow inert to be set in CSS

.hide {
  transition: opacity 200ms, display 200ms;
  display: none;
  opacity: 0;
  inert: yes;
}

The current HTML inert attribute could be explained by a UA style:

[inert] {
  inert: yes;
}

I know there was opposition to this in the past, since it relates to behaviour rather than style, but it feels like display: none and particularly transitions on display: none already have a significant impact on behaviour. Showing an element changes the behaviour of the page, and if that's done in CSS, it seems reasonable to be able to express modality via CSS.

Open question: Should it be possible for a child of an inert element to become un-inert? This is possible with pointer-events.

This means that the interactivity issue created by CSS can be solved with CSS. But, it requires the developer to remember to set it, so:

Make elements transitioning to display:none inert by default

.hide {
  transition: opacity 200ms, display 200ms;
  display: none;
  opacity: 0;
}

During the transition above, inert could behave as yes. This would avoid the situation described at the start of this post, where the CSS developer introduced a behaviour the JS developer hadn't catered for.

If the developer wants the element to be interactive during the transition, they can override this default:

.hide {
  transition: opacity 200ms, display 200ms;
  display: none;
  opacity: 0;
  inert: no;
}
@Loirooriol
Copy link
Contributor

For reference, #7021 rejected exposing inertness as a CSS property.

@jakearchibald
Copy link
Contributor Author

jakearchibald commented Feb 1, 2023

"Will not add an inertness property for now.", so I guess I'm asking "…how about now?" 😁

cc @emilio @annevk, in case the above is compelling enough for them to change their mind.

@josepharhar
Copy link
Contributor

During the transition above, inert could behave as yes.

Is there a way to express this with a user-agent style or something?

If the developer wants the element to be interactive during the transition, they can override this default:

If this isn't an important use case, then could we just make dialogs and popovers inert while transitioning to display:none without adding a new CSS property for inert?

@chrishtr chrishtr added Agenda+ and removed Agenda+ labels Feb 6, 2023
@chrishtr
Copy link
Contributor

chrishtr commented Feb 7, 2023

Re inert: for reference, it was last discussed in issue #7021, and the reasons it was not implemented in CSS were:

  • Need more experience with the inert attribute's use cases
  • The semantics would be atypical as they relate to inheritance and no ability to override an ancestor.

However, the discussion in the issue indicated it wouldn't be very hard for the existing browser engines to add a CSS version (and in fact they use cascade / CSS infrastructure under the hood to implement the attribute already).

During the transition above, inert could behave as yes.

Is there a way to express this with a user-agent style or something?

I'm not sure there is a simple way to express this. If there is, it would be nice to help authors avoid exit animation bugs.

If the developer wants the element to be interactive during the transition, they can override this default:

If this isn't an important use case, then could we just make dialogs and popovers inert while transitioning to display:none without adding a new CSS property for inert?

One option could be to make all top layer elements inert during a transition in or out of the top layer (and spec it along with the proposed top-layer property, see #8189). And then add inert to allow developers to opt into inert during other animations.

chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Feb 7, 2023
This isn't part of the landed spec [1], and will be replaced by
a combination of these five CSSWG issues:

- w3c/csswg-drafts#4441
- w3c/csswg-drafts#6429
- w3c/csswg-drafts#8174
- w3c/csswg-drafts#8189
- w3c/csswg-drafts#8389

After this CL, you will no longer be able to animate your
popover like this:

```
  [popover] {
    opacity: 0;
    transition: opacity 0.2s;
  }
  [popover]:open {
    opacity: 1;
  }
```

Instead you'll need to use CSS animations or (eventually) transitions
and you'll have to explicitly declare the `display` and `top-layer`
properties:

```
  transition: opacity 0.2s, display 0.2s, top-layer 0.2s;
```

[1] https://html.spec.whatwg.org/multipage/popover.html

Bug: 1307772,1413556
Change-Id: I4877dd69a06f2624bdb463b065b2e2b66cbf1154
@nt1m
Copy link
Member

nt1m commented Feb 7, 2023

How inert currently works corresponds roughly to this, so it's not as simple as @jakearchibald mentions. This is what allows modal dialogs to be interactive while the whole document is inert.

:root:has(dialog:-internal-active-modal-dialog, :fullscreen) {
  inert: true; // inherits down to true to all descendants until false is set
}

dialog:not([inert]):-internal-active-modal-dialog, :fullscreen:not([inert]) {
  inert: false; // inherits down false to all descendants
}

[inert] {
  inert: true;
}

I'm reluctant to make this a CSS property since it limits what functionality we could apply to the inert attribute, since it'd be constrained by the CSS cascade.

@nt1m
Copy link
Member

nt1m commented Feb 7, 2023

(to be clear none of these UA styles currently exist in WebKit, they're expressed from style adjuster: https://searchfox.org/wubkat/rev/90549aec61bacbaee7383e1fb2623cf34edc9273/Source/WebCore/style/StyleAdjuster.cpp#569-581)

@jakearchibald
Copy link
Contributor Author

During the transition above, inert could behave as yes.

Is there a way to express this with a user-agent style or something?

@flackr you had some thoughts around this, but I can't remember what they were

chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Feb 10, 2023
This isn't part of the landed spec [1], and will be replaced by
a combination of these five CSSWG issues:

- w3c/csswg-drafts#4441
- w3c/csswg-drafts#6429
- w3c/csswg-drafts#8174
- w3c/csswg-drafts#8189
- w3c/csswg-drafts#8389

After this CL, you will no longer be able to animate your
popover like this:

```
  [popover] {
    opacity: 0;
    transition: opacity 0.2s;
  }
  [popover]:open {
    opacity: 1;
  }
```

Instead you'll need to use CSS animations or (eventually) transitions
and you'll have to explicitly declare the `display` and `top-layer`
properties:

```
  transition: opacity 0.2s, display 0.2s, top-layer 0.2s;
```

[1] https://html.spec.whatwg.org/multipage/popover.html

Bug: 1307772,1413556
Change-Id: I4877dd69a06f2624bdb463b065b2e2b66cbf1154
@davwheat
Copy link

davwheat commented Feb 12, 2023

If this were to be added, it would be helpful to have a pseudoclass (:inert, I assume?) for this to allow styles that currently select [inert] to be updated to handle both the HTML attribute and CSS property.

@Loirooriol
Copy link
Contributor

We can have either an :inert selector or an inert property, but not both. Or if we have both, :inert shouldn't take the inert property into account, since otherwise it would be circular: :not(:inert) { inert: yes }.

chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Feb 13, 2023
This isn't part of the landed spec [1], and will be replaced by
a combination of these five CSSWG issues:

- w3c/csswg-drafts#4441
- w3c/csswg-drafts#6429
- w3c/csswg-drafts#8174
- w3c/csswg-drafts#8189
- w3c/csswg-drafts#8389

After this CL, you will no longer be able to animate your
popover like this:

```
  [popover] {
    opacity: 0;
    transition: opacity 0.2s;
  }
  [popover]:open {
    opacity: 1;
  }
```

Instead you'll need to use CSS animations or (eventually) transitions
and you'll have to explicitly declare the `display` and `top-layer`
properties:

```
  transition: opacity 0.2s, display 0.2s, top-layer 0.2s;
```

[1] https://html.spec.whatwg.org/multipage/popover.html

Bug: 1307772,1413556
Change-Id: I4877dd69a06f2624bdb463b065b2e2b66cbf1154
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Feb 14, 2023
This isn't part of the landed spec [1], and will be replaced by
a combination of these five CSSWG issues:

- w3c/csswg-drafts#4441
- w3c/csswg-drafts#6429
- w3c/csswg-drafts#8174
- w3c/csswg-drafts#8189
- w3c/csswg-drafts#8389

After this CL, you will no longer be able to animate your
popover like this:

```
  [popover] {
    opacity: 0;
    transition: opacity 0.2s;
  }
  [popover]:open {
    opacity: 1;
  }
```

Instead you'll need to use CSS animations or (eventually) transitions
and you'll have to explicitly declare the `display` and `top-layer`
properties:

```
  transition: opacity 0.2s, display 0.2s, top-layer 0.2s;
```

[1] https://html.spec.whatwg.org/multipage/popover.html

Bug: 1307772,1413556
Change-Id: I4877dd69a06f2624bdb463b065b2e2b66cbf1154
@flackr
Copy link
Contributor

flackr commented Feb 14, 2023

@flackr you had some thoughts around this, but I can't remember what they were

I was thinking we could use the base value of the display property. This is the value generated for the property in the absense of animations and is used as the base value when compositing animations in web-animations-1. It would be none during these dismiss cases and immediately would become block in the show cases so it would do the right thing in simple cases.

The main downsides I can think of are:

  • There are cases where the base value may not be relevant, e.g. if the animation has fill: forwards the base value will never take effect until the animation is removed. Similarly if the animation has infinite duration.
  • This is a bit of a new concept - the base style isn't usually something developers need to think about.

@flackr
Copy link
Contributor

flackr commented Feb 15, 2023

The other option would be to define and use the animation end state, though I'd be concerned that working that out may require a style calc with non-local information. E.g. ancestor animations on variables affecting the local animation. The base style is something we already have and usually is the end state.

chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Feb 17, 2023
This isn't part of the landed spec [1], and will be replaced by
a combination of these five CSSWG issues:

- w3c/csswg-drafts#4441
- w3c/csswg-drafts#6429
- w3c/csswg-drafts#8174
- w3c/csswg-drafts#8189
- w3c/csswg-drafts#8389

After this CL, you will no longer be able to animate your
popover like this:

```
  [popover] {
    opacity: 0;
    transition: opacity 0.2s;
  }
  [popover]:open {
    opacity: 1;
  }
```

Instead you'll need to use CSS animations or (eventually) transitions
and you'll have to explicitly declare the `display` and `top-layer`
properties:

```
  transition: opacity 0.2s, display 0.2s, top-layer 0.2s;
```

[1] https://html.spec.whatwg.org/multipage/popover.html

Bug: 1307772,1413556
Change-Id: I4877dd69a06f2624bdb463b065b2e2b66cbf1154
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Feb 17, 2023
This isn't part of the landed spec [1], and will be replaced by
a combination of these five CSSWG issues:

- w3c/csswg-drafts#4441
- w3c/csswg-drafts#6429
- w3c/csswg-drafts#8174
- w3c/csswg-drafts#8189
- w3c/csswg-drafts#8389

After this CL, you will no longer be able to animate your
popover like this:

```
  [popover] {
    opacity: 0;
    transition: opacity 0.2s;
  }
  [popover]:open {
    opacity: 1;
  }
```

Instead you'll need to use CSS animations or (eventually) transitions
and you'll have to explicitly declare the `display` and `top-layer`
properties:

```
  transition: opacity 0.2s, display 0.2s, top-layer 0.2s;
```

[1] https://html.spec.whatwg.org/multipage/popover.html

Bug: 1307772,1413556
Change-Id: I4877dd69a06f2624bdb463b065b2e2b66cbf1154
aarongable pushed a commit to chromium/chromium that referenced this issue Feb 17, 2023
This isn't part of the landed spec [1], and will be replaced by
a combination of these five CSSWG issues:

- w3c/csswg-drafts#4441
- w3c/csswg-drafts#6429
- w3c/csswg-drafts#8174
- w3c/csswg-drafts#8189
- w3c/csswg-drafts#8389

After this CL, you will no longer be able to animate your
popover like this:

```
  [popover] {
    opacity: 0;
    transition: opacity 0.2s;
  }
  [popover]:open {
    opacity: 1;
  }
```

Instead you'll need to use CSS animations or (eventually) transitions
and you'll have to explicitly declare the `display` and `top-layer`
properties:

```
  transition: opacity 0.2s, display 0.2s, top-layer 0.2s;
```

[1] https://html.spec.whatwg.org/multipage/popover.html

Bug: 1307772,1413556
Change-Id: I4877dd69a06f2624bdb463b065b2e2b66cbf1154
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4225730
Reviewed-by: David Baron <[email protected]>
Commit-Queue: David Baron <[email protected]>
Commit-Queue: Mason Freed <[email protected]>
Auto-Submit: Mason Freed <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1107048}
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Feb 17, 2023
This isn't part of the landed spec [1], and will be replaced by
a combination of these five CSSWG issues:

- w3c/csswg-drafts#4441
- w3c/csswg-drafts#6429
- w3c/csswg-drafts#8174
- w3c/csswg-drafts#8189
- w3c/csswg-drafts#8389

After this CL, you will no longer be able to animate your
popover like this:

```
  [popover] {
    opacity: 0;
    transition: opacity 0.2s;
  }
  [popover]:open {
    opacity: 1;
  }
```

Instead you'll need to use CSS animations or (eventually) transitions
and you'll have to explicitly declare the `display` and `top-layer`
properties:

```
  transition: opacity 0.2s, display 0.2s, top-layer 0.2s;
```

[1] https://html.spec.whatwg.org/multipage/popover.html

Bug: 1307772,1413556
Change-Id: I4877dd69a06f2624bdb463b065b2e2b66cbf1154
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4225730
Reviewed-by: David Baron <[email protected]>
Commit-Queue: David Baron <[email protected]>
Commit-Queue: Mason Freed <[email protected]>
Auto-Submit: Mason Freed <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1107048}
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Feb 17, 2023
This isn't part of the landed spec [1], and will be replaced by
a combination of these five CSSWG issues:

- w3c/csswg-drafts#4441
- w3c/csswg-drafts#6429
- w3c/csswg-drafts#8174
- w3c/csswg-drafts#8189
- w3c/csswg-drafts#8389

After this CL, you will no longer be able to animate your
popover like this:

```
  [popover] {
    opacity: 0;
    transition: opacity 0.2s;
  }
  [popover]:open {
    opacity: 1;
  }
```

Instead you'll need to use CSS animations or (eventually) transitions
and you'll have to explicitly declare the `display` and `top-layer`
properties:

```
  transition: opacity 0.2s, display 0.2s, top-layer 0.2s;
```

[1] https://html.spec.whatwg.org/multipage/popover.html

Bug: 1307772,1413556
Change-Id: I4877dd69a06f2624bdb463b065b2e2b66cbf1154
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4225730
Reviewed-by: David Baron <[email protected]>
Commit-Queue: David Baron <[email protected]>
Commit-Queue: Mason Freed <[email protected]>
Auto-Submit: Mason Freed <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1107048}
moz-v2v-gh pushed a commit to mozilla/gecko-dev that referenced this issue Mar 1, 2023
…over animation stuff, a=testonly

Automatic update from web-platform-tests
Rip out all of the beautiful bespoke Popover animation stuff

This isn't part of the landed spec [1], and will be replaced by
a combination of these five CSSWG issues:

- w3c/csswg-drafts#4441
- w3c/csswg-drafts#6429
- w3c/csswg-drafts#8174
- w3c/csswg-drafts#8189
- w3c/csswg-drafts#8389

After this CL, you will no longer be able to animate your
popover like this:

```
  [popover] {
    opacity: 0;
    transition: opacity 0.2s;
  }
  [popover]:open {
    opacity: 1;
  }
```

Instead you'll need to use CSS animations or (eventually) transitions
and you'll have to explicitly declare the `display` and `top-layer`
properties:

```
  transition: opacity 0.2s, display 0.2s, top-layer 0.2s;
```

[1] https://html.spec.whatwg.org/multipage/popover.html

Bug: 1307772,1413556
Change-Id: I4877dd69a06f2624bdb463b065b2e2b66cbf1154
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4225730
Reviewed-by: David Baron <[email protected]>
Commit-Queue: David Baron <[email protected]>
Commit-Queue: Mason Freed <[email protected]>
Auto-Submit: Mason Freed <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1107048}

--

wpt-commits: 635df2dae0185211850d336ed6320ec35e4f4f3f
wpt-pr: 38392
jamienicol pushed a commit to jamienicol/gecko that referenced this issue Mar 1, 2023
…over animation stuff, a=testonly

Automatic update from web-platform-tests
Rip out all of the beautiful bespoke Popover animation stuff

This isn't part of the landed spec [1], and will be replaced by
a combination of these five CSSWG issues:

- w3c/csswg-drafts#4441
- w3c/csswg-drafts#6429
- w3c/csswg-drafts#8174
- w3c/csswg-drafts#8189
- w3c/csswg-drafts#8389

After this CL, you will no longer be able to animate your
popover like this:

```
  [popover] {
    opacity: 0;
    transition: opacity 0.2s;
  }
  [popover]:open {
    opacity: 1;
  }
```

Instead you'll need to use CSS animations or (eventually) transitions
and you'll have to explicitly declare the `display` and `top-layer`
properties:

```
  transition: opacity 0.2s, display 0.2s, top-layer 0.2s;
```

[1] https://html.spec.whatwg.org/multipage/popover.html

Bug: 1307772,1413556
Change-Id: I4877dd69a06f2624bdb463b065b2e2b66cbf1154
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4225730
Reviewed-by: David Baron <[email protected]>
Commit-Queue: David Baron <[email protected]>
Commit-Queue: Mason Freed <[email protected]>
Auto-Submit: Mason Freed <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1107048}

--

wpt-commits: 635df2dae0185211850d336ed6320ec35e4f4f3f
wpt-pr: 38392
moz-v2v-gh pushed a commit to mozilla/gecko-dev that referenced this issue Mar 2, 2023
…over animation stuff, a=testonly

Automatic update from web-platform-tests
Rip out all of the beautiful bespoke Popover animation stuff

This isn't part of the landed spec [1], and will be replaced by
a combination of these five CSSWG issues:

- w3c/csswg-drafts#4441
- w3c/csswg-drafts#6429
- w3c/csswg-drafts#8174
- w3c/csswg-drafts#8189
- w3c/csswg-drafts#8389

After this CL, you will no longer be able to animate your
popover like this:

```
  [popover] {
    opacity: 0;
    transition: opacity 0.2s;
  }
  [popover]:open {
    opacity: 1;
  }
```

Instead you'll need to use CSS animations or (eventually) transitions
and you'll have to explicitly declare the `display` and `top-layer`
properties:

```
  transition: opacity 0.2s, display 0.2s, top-layer 0.2s;
```

[1] https://html.spec.whatwg.org/multipage/popover.html

Bug: 1307772,1413556
Change-Id: I4877dd69a06f2624bdb463b065b2e2b66cbf1154
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4225730
Reviewed-by: David Baron <[email protected]>
Commit-Queue: David Baron <[email protected]>
Commit-Queue: Mason Freed <[email protected]>
Auto-Submit: Mason Freed <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1107048}

--

wpt-commits: 635df2dae0185211850d336ed6320ec35e4f4f3f
wpt-pr: 38392
@chrishtr
Copy link
Contributor

chrishtr commented Mar 7, 2023

was thinking we could use the base value of the display property. This is the value generated for the property in the absense of animations and is used as the base value when compositing animations in web-animations-1. It would be none during these dismiss cases and immediately would become block in the show cases so it would do the right thing in simple cases.

Proposed initial resolution: apply the behavior @flackr suggests above regarding the base value. If there is enough developer demand in the future, consider adding inert at that time.

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed [css-display] Interaction gotchas when delaying the effect of `display: none` , and agreed to the following:

  • RESOLVED: inertness is determined by the base computed style for 'display', resulting in animations to 'none' being considered inert
The full IRC log of that discussion <fantasai> flackr: Using display to animate from block to none
<fantasai> flackr: this has effect that during animation, the element can still be interacted with and is in the a11y tree
<fantasai> flackr: it has problems with e.g. form submission, coudl accidentally submit twice because animating out
<fantasai> flackr: proposed resolution is that we look at the base value of the display property, i.e. the value before animation is apply
<fantasai> flackr: when animating to none, base value woudl be none
<fantasai> flackr: use that to determine whether the element should be in the a11y tree
<fantasai> flackr: and also effectively make it inert while it's none
<fantasai> flackr: longer-term, we might want to have inert be a CSS property, and this would be part of auto behavior for inert
<PaulG> +1 (from APA_
<TabAtkins> +1 frome me
<fantasai> flackr: but this would be for doing the right thing in the simple cases
<masonf> +1
<fantasai> +1 to "make it work like expected without author fussing"
<bramus> +1
<emilio> +1 as long as there are tests for this
<fantasai> flackr: [re-explains proposal]
<fantasai> Rossen: There was some work that was already happening around inert, curious if your proposal has any tracking with that work
<emilio> q+
<fantasai> Rossen: I'm sure inert as CSS property was considered and debated at some point in the past, I'm not sure where we ended up, but would be good to have a tracking issue or at least track that discussion
<chrishtr> Link to prior discussion: https://github.com//issues/8389#issuecomment-1419970151
<fantasai> chrishtr: Link to pros and cons
<fantasai> chrishtr: my understanding from previous discussion was that no one had strong opinions, and the door was open to adding it in the future
<fantasai> Rossen: that answers my question
<fantasai> chrishtr: We can do this thing for now, so by default it does the right thing
<fantasai> chrishtr: and if there's significant developer need, we can add 'inert' in the future without too much trouble
<astearns> ack emilio
<fantasai> flackr: yes, this is designed to be forwards-compatible with that
<fantasai> emilio: I was thinking about this, inert has this feature where some elements that escape inert-ness
<fantasai> emilio: e.g. modal dialog that's now 'display: none', that will not be inert
<fantasai> emilio: but 'display: none' would prevent modal dialog from showing
<flackr> qq+
<fantasai> emilio: this looks almost like inert, but with that thing where we may not want subtrees to escape inertness?
<fantasai> chrishtr: if you have [scenario]
<astearns> ack flackr
<Zakim> flackr, you wanted to react to emilio
<fantasai> flackr: the auto behavior is based on the computed base style of 'display', which even for the descendant would be 'none'
<fantasai> emilio: not really, display is not inherited
<fantasai> flackr: but it's within an element with a computed base display style of 'none'
<TabAtkins> display may not be inherited, but display-none-ness *basically* is
<masonf> modal dialog inside a display:none subtree is already display:none.
<fantasai> emilio: the way inert is implemented, at least in WebKit and Gecko, basically it's an internal inherited bit in the computed style representation
<fantasai> emilio: there are things that can flip that for a subtree
<fantasai> emilio: when you have fullscreen element, everything is inert except fullscreen element subtree
<oriol> Blink also uses that approach
<fantasai> emilio: this inert, we don't want it to be overridden by anything inside the subtree
<fantasai> flackr: even if overridden, this proposal would fix the common cases
<fantasai> flackr: but if we did allow overriding, you would have these edge cases where the things animating to 'display: none' would not include modal dialog
<fantasai> emilio: this proposal helps a lot for ?? cases
<fantasai> emilio: just an edge case that might be better to explicitly point out?
<fantasai> emilio: "inert, but actually force inertness for the entire subtree"
<fantasai> flackr: sounds like something we could consider if we add a CSS property for inertness
<fantasai> flackr: I think there are use cases for opting subtree
<fantasai> emilio: if we add inert, it would be similar to visibility, can set it differently inside a subtree
<fantasai> emilio: might have use cases for inert unable to flip within the subtree
<fantasai> emilio: probably the spec should call out this edge case, and define the behavior explicitly
<astearns> ack fantasai
<fantasai> emilio: if you have fullscreen element inside, define that behavior
<emilio> fantasai: for visibility: hidden you can flip back to visible, but visibility: collapse into a flex item doesn't allow you to do that
<fantasai> astearns: ready to resolve?
<emilio> ... so visibility has that behavior as well
<fantasai> s/.../fantasai:/
<fantasai> flackr: inertness is determined by the base computed style for 'display', resulting in animations to 'none' being considered inert
<fantasai> astearns: can make that claim generally, not just during animations?
<fantasai> flackr: base computed style is all styles before animations
<fantasai> astearns: any other comments or concerns?
<fantasai> RESOLVED: inertness is determined by the base computed style for 'display', resulting in animations to 'none' being considered inert
<fantasai> astearns: +1 to having tests for this

@josepharhar
Copy link
Contributor

I have started implementing this in chromium, here is a WPT: web-platform-tests/wpt#39023

aarongable pushed a commit to chromium/chromium that referenced this issue Mar 16, 2023
w3c/csswg-drafts#8389

Bug: 1422736
Change-Id: Ica770040e6932b00fdd0c3a2051c9aee745e4b2b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4342420
Commit-Queue: Joey Arhar <[email protected]>
Reviewed-by: Robert Flack <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1118269}
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Mar 16, 2023
w3c/csswg-drafts#8389

Bug: 1422736
Change-Id: Ica770040e6932b00fdd0c3a2051c9aee745e4b2b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4342420
Commit-Queue: Joey Arhar <[email protected]>
Reviewed-by: Robert Flack <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1118269}
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Mar 16, 2023
w3c/csswg-drafts#8389

Bug: 1422736
Change-Id: Ica770040e6932b00fdd0c3a2051c9aee745e4b2b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4342420
Commit-Queue: Joey Arhar <[email protected]>
Reviewed-by: Robert Flack <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1118269}
cookiecrook pushed a commit to cookiecrook/wpt that referenced this issue Mar 21, 2023
w3c/csswg-drafts#8389

Bug: 1422736
Change-Id: Ica770040e6932b00fdd0c3a2051c9aee745e4b2b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4342420
Commit-Queue: Joey Arhar <[email protected]>
Reviewed-by: Robert Flack <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1118269}
marcoscaceres pushed a commit to web-platform-tests/wpt that referenced this issue Mar 28, 2023
This isn't part of the landed spec [1], and will be replaced by
a combination of these five CSSWG issues:

- w3c/csswg-drafts#4441
- w3c/csswg-drafts#6429
- w3c/csswg-drafts#8174
- w3c/csswg-drafts#8189
- w3c/csswg-drafts#8389

After this CL, you will no longer be able to animate your
popover like this:

```
  [popover] {
    opacity: 0;
    transition: opacity 0.2s;
  }
  [popover]:open {
    opacity: 1;
  }
```

Instead you'll need to use CSS animations or (eventually) transitions
and you'll have to explicitly declare the `display` and `top-layer`
properties:

```
  transition: opacity 0.2s, display 0.2s, top-layer 0.2s;
```

[1] https://html.spec.whatwg.org/multipage/popover.html

Bug: 1307772,1413556
Change-Id: I4877dd69a06f2624bdb463b065b2e2b66cbf1154
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4225730
Reviewed-by: David Baron <[email protected]>
Commit-Queue: David Baron <[email protected]>
Commit-Queue: Mason Freed <[email protected]>
Auto-Submit: Mason Freed <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1107048}
marcoscaceres pushed a commit to web-platform-tests/wpt that referenced this issue Mar 28, 2023
w3c/csswg-drafts#8389

Bug: 1422736
Change-Id: Ica770040e6932b00fdd0c3a2051c9aee745e4b2b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4342420
Commit-Queue: Joey Arhar <[email protected]>
Reviewed-by: Robert Flack <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1118269}
cookiecrook pushed a commit to cookiecrook/wpt that referenced this issue Mar 29, 2023
w3c/csswg-drafts#8389

Bug: 1422736
Change-Id: Ica770040e6932b00fdd0c3a2051c9aee745e4b2b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4342420
Commit-Queue: Joey Arhar <[email protected]>
Reviewed-by: Robert Flack <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1118269}
moz-v2v-gh pushed a commit to mozilla/gecko-dev that referenced this issue Mar 30, 2023
…ly inert, a=testonly

Automatic update from web-platform-tests
Make animations to display:none also apply inert

w3c/csswg-drafts#8389

Bug: 1422736
Change-Id: Ica770040e6932b00fdd0c3a2051c9aee745e4b2b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4342420
Commit-Queue: Joey Arhar <[email protected]>
Reviewed-by: Robert Flack <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1118269}

--

wpt-commits: 286d2ea3aa0cd9630d5402474c989cfa29c7bc7b
wpt-pr: 39023
cookiecrook pushed a commit to cookiecrook/wpt that referenced this issue Apr 8, 2023
w3c/csswg-drafts#8389

Bug: 1422736
Change-Id: Ica770040e6932b00fdd0c3a2051c9aee745e4b2b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4342420
Commit-Queue: Joey Arhar <[email protected]>
Reviewed-by: Robert Flack <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1118269}
@kizu
Copy link
Member

kizu commented Jun 15, 2023

I want to bring an issue I encountered while playing with the display transition.

The issue is: the inert behavior makes it impossible to implement an affordance period for tooltips on hover. Here is a CodePen that demonstrated the issue following issue — https://codepen.io/kizu/pen/rNQBvKm?editors=1100

Note: it seems that there could've been some change in Chrome Canary that broke the display transitions in one of the latest build, so I couldn't reproduce them at all in the above CodePen or in other demos, so here is a screen recording showing the behavior when it was working:

A.screen.recording.of.the.CodePen.in.action_.we.re.able.to.hover.out.of.the.element.with.a.transition.in.progress.when.it.is.an.element.with.visibility.transition.but.are.not.able.to.do.so.for.an.element.with.a.display.transition.mp4

The way developers usually apply the additional affordance for tooltips on hover is by adding an additional delay before the actual animation duration, allowing the following things:

  1. When there is a gap between the target and the tooltip, it makes it possible to move the cursor to the tooltip content without losing it.
  2. When the path from the tooltip target to the tooltip content lies diagonally, this additional delay allows users to not “lose” the tooltip if they manage to move the cursor through this delay.
  3. It adds just an additional affordance, smoothing small mouse cursor control issues, like when the cursor accidentally exits the target or the tooltip, not hiding the tooltip immediately.

These are in line with the https://www.w3.org/WAI/WCAG21/Understanding/content-on-hover-or-focus.html, both for the “Hoverable” and “Persistent” success criteria.

The problem right now is that the inert (and pointer-events: none — I'm not sure if the “inert” includes it?) behavior kicks in right away when the element gets the display: none, making the method of using the delay useless, as it becomes not possible to return the cursor to the tooltip.

Proposed solutions:

  1. Only make the tooltip inert and pointer-events: none during the duration, but not during the delay when transitioning the display to none.
  2. Keep the inert behavior as described in the issue, but still allow pointer-events both for the duration and the delay (this would make the usage for tooltips in line with how transition for visibility works).
  3. Allow developers to control the inert (and, if necessary poiner-events) during the transition, similar to how we can control the top layer transition via overlay — I think this is a very similar case, and exposing the control for the inert only as a part of a transition seems like an ok idea?
  4. Any other solution that could solve this use case.

@flackr
Copy link
Contributor

flackr commented Jun 16, 2023

The problem right now is that the inert (and pointer-events: none — I'm not sure if the “inert” includes it?)

inert forces the browser to act as if we have pointer-events: none currently per the html spec. This behavior was discussed in #6685.

Adding some thoughts to the different proposals:

Proposed solutions:

  1. Only make the tooltip inert and pointer-events: none during the duration, but not during the delay when transitioning the display to none.

Currently the way that we make the node inert is by determining that the base style (i.e. style without animations) is display: none. This would require more complicated logic. E.g. if the base style is display: none and at least one animation animating display is in the active phase?

  1. Keep the inert behavior as described in the issue, but still allow pointer-events both for the duration and the delay (this would make the usage for tooltips in line with how transition for visibility works).

I'm not sure I understand what you mean by "allow pointer-events"? Do you mean that the node would be inert but still hittable? I think this may be similar to my preferred behavior for inert #6685 (comment) but we would need to flesh out the details about how we still ensure that the elements within will not be interacted with.

  1. Allow developers to control the inert (and, if necessary poiner-events) during the transition, similar to how we can control the top layer transition via overlay — I think this is a very similar case, and exposing the control for the inert only as a part of a transition seems like an ok idea?

I think there's two options here:

  • Controlling inert via CSS was something we discussed as worth looking into if there were use cases - which this seems to be a good one for it. There have been previous concerns about this [css-ui] Should inertness be exposed as CSS property? #7021 but perhaps they can be worked out.
  • Alternately we could have similar logic to the overlay behavior as you mentioned where it can be transitioned but not set.

@kizu
Copy link
Member

kizu commented Jun 16, 2023

Do you mean that the node would be inert but still hittable?

Yes! I think, similar to the way disabled works on the buttons. Though, I wish we could control this on the disabled buttons as well, as there are cases when we want it to be disabled, but still catch some events (usually when we want to give some tooltip to a disabled button to hint over why is it disabled, or to track clicks on it, to see if the state is not conveyed well enough), which could be a good case for being able to control inert from CSS (in some limited ways).

I think both options can be good, but I'm afraid that exposing inertness is a much risky change overall, and those two could both exist at the same time; meaning if we allow transitioning inertness first, then if we'd later add an ability to control it more freely, it would be just an extension of the existing functionality.

@nt1m
Copy link
Member

nt1m commented Jun 16, 2023

I do want to remind why I think exposing inertness to CSS is a bad idea:

  • it is not presentational, but semantic.
  • inert behavior is not trivial to express when you take in account modal dialogs which override the root element's inertness when open. Allowing that to be expressed along with the inert attribute & modal dialogs, opens to more confusion (what takes precendence, CSS or HTML? can we override the inertness on the child, etc?)

@nt1m
Copy link
Member

nt1m commented Jun 16, 2023

I'd be open to tweaking the pointer events model, but it's work that is unlikely going to get done in implementations given the low gain from it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

10 participants