CSS keyframes动画在iPhone端Safari失效其余浏览器正常如何解决
故障根因
这是iOS Safari两个独有的已知兼容问题导致的,和CSS前缀、animation写法无关:
- 非交互元素伪类触发限制:iOS Safari默认仅对
<a>、<button>这类原生可交互元素响应:hover、:active伪类,普通<li>这类非交互元素如果没有标记为可点击状态,触摸时不会触发hover相关样式。 - display切换动画失效bug:如果元素默认是
display: none状态,切换为可见状态的瞬间,iOS Safari不会触发子元素上绑定的CSS动画,这个bug在桌面端、安卓端所有浏览器都已修复,仅存在于iOS端自带Safari中。
另外你的HTML代码存在语法问题:包裹子菜单的第二个<li>标签缺失闭合标签,部分场景下也会导致Safari渲染异常。
修复步骤
- 解决伪类不触发问题
给所有.menu-primaire元素添加cursor: pointer样式,同时在对应HTML标签上添加空属性onclick="",不需要写任何JS逻辑,仅用于告知Safari该元素为可交互元素,允许触发hover状态。 - 替换子菜单显隐逻辑
放弃用display属性控制子菜单显隐,改用visibility + opacity + pointer-events组合实现显隐,从根源避开display切换导致的动画不触发bug。默认状态下子菜单设为不可见、不响应点击,hover时切换为可见状态。 - 补全样式定位基准
给父级.menu-primaire添加position: relative,作为子菜单绝对定位的定位基准,避免子菜单偏移位置错乱。 - 给动画加1ms的启动延迟
给每个子菜单项的动画延迟增加1ms的缓冲时间,保证元素可见状态切换完成后再启动动画,进一步提升兼容性。 - 修复HTML语法错误
补全第二个<li>缺失的闭合标签,避免Safari的容错解析导致DOM结构异常。
修正后代码
/* 补全子菜单默认隐藏状态 */ .head_liste__secondaire { visibility: hidden; opacity: 0; position: absolute; padding: 0; top: 70px; right: 34%; pointer-events: none; /* 隐藏时不响应点击 */ @media screen and (max-width: 768px) { right: 0; } } .menu-primaire { position: relative; /* 作为子菜单绝对定位的参照 */ cursor: pointer; /* 标记为可交互元素 */ transition: all 500ms; &:hover, &:active, &:focus { & .head_liste__secondaire { visibility: visible; opacity: 1; pointer-events: auto; top: 25px; @media screen and (max-width: 425px) { top: 70px; } } } } .menu-secondaire { -webkit-animation-name: menu; -moz-animation-name: menu; animation-name: menu; -webkit-animation-duration: 500ms; -moz-animation-duration: 500ms; animation-duration: 500ms; -webkit-animation-fill-mode: both; -moz-animation-fill-mode: both; animation-fill-mode: both; @for $i from 1 through 4 { &--#{$i} { -webkit-animation-delay: calc(100ms * #{$i} + 1ms); /* 加1ms缓冲延迟 */ -moz-animation-delay: calc(100ms * #{$i} + 1ms); animation-delay: calc(100ms * #{$i} + 1ms); } } } @-webkit-keyframes menu { 0% { -webkit-transform: translate3d(0,10px,0); opacity: 0; } 100% { -webkit-transform: translate3d(0,0,0); opacity: 1; } } @-moz-keyframes menu { 0% { -moz-transform: translate3d(0,10px,0); opacity: 0; } 100% { -moz-transform: translate3d(0,0,0); opacity: 1; } } @keyframes menu { 0% { transform: translate3d(0,10px,0); opacity: 0; } 100% { transform: translate3d(0,0,0); opacity: 1; } }
<nav> <ul class="head_liste"> <li class="head_liste__primaire menu-primaire" onclick=""><a href="#">Button 1</a></li> <li class="head_liste__primaire menu-primaire" onclick="">Button 2 <ul class="head_liste__secondaire"> <li class="menu-secondaire menu-secondaire--1"><a href="#">Button 1a</a></li> <li class="menu-secondaire menu-secondaire--2"><a href="#">Button 1b</a></li> <li class="menu-secondaire menu-secondaire--3"><a href="#">Button 1c</a></li> <li class="menu-secondaire menu-secondaire--4"><a href="#">Button 1d</a></li> </ul> </li> <!-- 补全之前缺失的闭合标签 --> <li class="head_liste__primaire menu-primaire" onclick=""><a href="#">Button 3</a></li> </ul> </nav>
注意:Mac端Safari的响应式设计模式、Xcode自带的iOS模拟器都无法100%复现真实iPhone设备上Safari的触摸交互、伪类触发逻辑,修复后如果需要验证效果,可以使用云真机平台测试,不需要额外购置实体设备。
内容的提问来源于stack exchange,提问作者Clem
相关产品推荐
相关产品推荐

