Safari click event and active state cannot coexist

2019-08-18 07:43发布

I'm try to create a 3-state button:

  1. Off (default)
  2. On (hover/rollover)
  3. Down (active/click)

In both Safari desktop and Safari mobile, when the down state is added (via :active pseudo state) it kills the click event.

Why can't these two pieces play nice together?

Simple example demoing it here: https://jsfiddle.net/m7hev81t/1/

$('button').on('click',function(e){
	$('#log').html('clicked ' + new Date().getTime());
});
button {
  position:relative;
  background:transparent;
  border:none;
  height:50px;
  width:200px;
  cursor:pointer;
}

button .state { 
  position:absolute;
  width:100%;
  height:100%;
  display:none;
  top:0; left:0;
}

.state.off { background:green; display:block; }
.state.on { background:orange;}
.state.down { background:red; }

button:hover .state.off, button:hover .state.down {display:none;}
button:hover .state.on {display:block;}

button.has-down:active .state.on, button.has-down:active .state.off {display:none;}
button.has-down:active .state.down {display:block;}

#log {
  width:100%;
  border:1px solid grey;
  min-height:2em;
  margin-top:2em;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<p>
No down/click state.
</p>
<button>
<div class="state off">
off
</div>
<div class="state on">
on
</div>
<div class="state down">
down
</div>
</button>

<p>
Down/click state.
</p>
<button class="has-down">
<div class="state off">
off
</div>
<div class="state on">
on
</div>
<div class="state down">
down
</div>
</button>

<div id="log"/>

Thanks in advance for you input!

2条回答
2楼-- · 2019-08-18 08:21

I think the issue is that the states themselves are catching the click event. Then when the state is hidden, the click doesn't bubble up.

Adding this line of CSS makes it work:

button.has-down .state { pointer-events:none; }

Here's the fiddle: https://jsfiddle.net/m7hev81t/2/

And full example, where the second button now triggers the event.

$('button').on('click',function(e){
	$('#log').html('clicked ' + new Date().getTime());
});
button {
  position:relative;
  background:transparent;
  border:none;
  height:50px;
  width:200px;
  cursor:pointer;
}

button .state { 
  position:absolute;
  width:100%;
  height:100%;
  display:none;
  top:0; left:0;
}

.state.off { background:green; display:block; }
.state.on { background:orange;}
.state.down { background:red; }

button:hover .state.off, button:hover .state.down {display:none;}
button:hover .state.on {display:block;}

button.has-down .state { pointer-events:none; }
button.has-down:active .state.on, button.has-down:active .state.off {display:none;}
button.has-down:active .state.down {display:block;}

#log {
  width:100%;
  border:1px solid grey;
  min-height:2em;
  margin-top:2em;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<p>
No down/click state.
</p>
<button>
<div class="state off">
off
</div>
<div class="state on">
on
</div>
<div class="state down">
down
</div>
</button>

<p>
Down/click state.
</p>
<button class="has-down">
<div class="state off">
off
</div>
<div class="state on">
on
</div>
<div class="state down">
down
</div>
</button>

<div id="log"/>

查看更多
Fickle 薄情
3楼-- · 2019-08-18 08:27

MDN

On systems with multi-button mice, CSS3 specifies that the :active pseudo-class must only apply to the primary button; on right-handed mice, this is typically the leftmost button.

so I guess not everything "click" the element will fire :active,

on safari, finger or mouse pointed on element does not count, unless:

By default, Safari on iOS does not use the :active state unless there is a touchstart event handler on the relevant element or on the element.

查看更多
登录 后发表回答