A link that receives pointer-events after animating isn't clickable in Safari
Asked Answered
J

1

3

I'm animating text with CSS where elements appear one after the other. Try it out first to see what I mean:

.wrapper {
  pointer-events: none; /* remove pointer events from elements before they animate */
}

.text {
  position: absolute;
}

/* The first element starts off visible and fades out after 2s */
.first {
  opacity: 1;
  animation: fade 500ms reverse forwards 2000ms;
}

/* The second element starts off hidden and fades in after 3s */
.second {
  opacity: 0;
  animation: fade 500ms forwards 3000ms;
}

@keyframes fade {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
    pointer-events: all; /* add pointer events to elements after they finish animating */
  }
}
<div class="wrapper">
  <h1 class="text first">Wait 2 seconds...</h1>
  <h1 class="text second">Now <a href="https://example.com">click</a></h1>
<div>

As you can see in the snippet, the second element has a link. By default, it would be clickable throughout the animation, even while its opacity is still 0.

I want the link to become clickable only when it appears, so I'm setting pointer-events: none; on the parent element, and pointer-events: all; on children after they finished animating (in @keyframes).

This works great in Chrome and Firefox, but it doesn't in Safari: the link doesn't become clickable at the end of the animation. The parent's pointer-event: none; rule somehow doesn't get overridden by the more specific pointer-events: all; rule that should apply to the element itself at the end of the animation.

(you can reproduce the issue or fork it in this CodeSandbox)

Here are my questions:

  • Is this a Safari bug? I went through Webkit's issue tracker but couldn't find anything that seems related (there are plenty of other pointer-events bugs though).
  • Is there a way to make this work in Safari without resorting to JavaScript?

Thanks in advance!

Edit

I found a solution for Safari by using visibility: hidden; instead of disabling pointer-events, posted below.

Something else I noticed is that when I test my code with Playwright (a test automation tool that can spin up a headless webkit browser), I can't reproduce the pointer-events bug, so I wonder if this is only an issue with Safari and not webkit itself. I'm still interested in knowing whether this is a known behavior!

Jerry answered 11/4, 2021 at 15:3 Comment(0)
J
0

Here's the solution I went for that also works on Safari:

.text {
  position: absolute;
}

/* The first element starts off visible and fades out after 2s */
.first {
  opacity: 1;
  visibility: visible;
  animation: fade 500ms reverse forwards 2000ms;
}

/* The second element starts off hidden and fades in after 3s */
.second {
  opacity: 0;
  visibility: hidden;
  animation: fade 500ms forwards 3000ms;
}

@keyframes fade {
  from {
    opacity: 0; /* We still need opacity to animate on */
    visibility: hidden;
  }
  to {
    opacity: 1;
    visibility: visible;
  }
}
<div>
  <h1 class="text first">Wait 2 seconds...</h1>
  <h1 class="text second">Now <a href="https://example.com">click</a></h1>
<div>

Instead of disabling pointer-events, we can use visibility: hidden; to ensure that the link isn't clickable before it should be.

Jerry answered 12/4, 2021 at 8:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.