iOS Safari中点击SVG元素时CSS :hover动画不生效问题
iOS Safari中SVG下拉菜单过渡动画失效的解决方案
问题核心原因
你猜的没错,问题根源就是iOS Safari对非交互元素的:hover支持存在限制。默认情况下,只有<a>、<button>这类原生可点击元素才能触发:hover状态;而你代码里的<g class="has-dropdown">只是普通图形容器,不属于交互元素范畴,所以点击时无法触发hover状态。长按能唤起菜单后动画生效,是因为长按行为会被Safari模拟为hover触发。
解决方案
针对这个问题,我们需要把触发hover的<g>元素转为可交互元素,同时优化CSS过渡逻辑:
1. 给触发容器添加交互属性
给<g id="training" class="has-dropdown">添加tabindex="0"和pointer-events: auto,让Safari识别它为可交互元素:
<g id="training" class="has-dropdown" tabindex="0"> <!-- 内部path和text元素 --> </g>
2. 优化CSS过渡逻辑
- 只对
opacity属性做过渡(visibility和height无法被平滑过渡,会干扰动画效果) - 统一过渡属性写法,现代Safari已支持标准
transition,无需额外前缀 - 调整hover状态触发逻辑,避免触发元素直接隐藏导致hover状态丢失
修改后的核心CSS:
.has-dropdown { pointer-events: auto; cursor: pointer; } .sub-menu { opacity: 0; visibility: hidden; height: 0; pointer-events: none; transition: opacity 2s ease-in-out; /* 仅过渡opacity */ } .sub-menu > g { opacity: 0; transition: opacity 2s ease-in-out; } .has-dropdown:hover + .sub-menu, .has-dropdown:focus + .sub-menu { /* 增加:focus支持键盘交互 */ opacity: 1; visibility: visible; height: auto; pointer-events: auto; } .has-dropdown:hover + .sub-menu > g, .has-dropdown:focus + .sub-menu > g { opacity: 1; } /* 用opacity过渡替代直接隐藏,避免hover状态丢失 */ .has-dropdown:hover { opacity: 0.9; }
3. 完整修改后的SVG代码
<?xml version="1.0" encoding="UTF-8"?> <svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 306.12 409.2"> <defs> <style type="text/css"> @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@500;600'); .font-md { font-family: 'Poppins'; font-size: 10px; font-weight: 500; } :root { --yellow: #f6b034; } .training { fill: var(--yellow); } .has-dropdown { pointer-events: auto; cursor: pointer; } .sub-menu { opacity: 0; visibility: hidden; height: 0; pointer-events: none; transition: opacity 2s ease-in-out; } .sub-menu > g { opacity: 0; transition: opacity 2s ease-in-out; } .has-dropdown:hover + .sub-menu, .has-dropdown:focus + .sub-menu { opacity: 1; visibility: visible; height: auto; pointer-events: auto; } .has-dropdown:hover + .sub-menu > g, .has-dropdown:focus + .sub-menu > g { opacity: 1; } .has-dropdown:hover { opacity: 0.9; } .sub-menu:hover { opacity: 1; visibility: visible; height: auto; pointer-events: auto; } .sub-menu:hover > g { opacity: 1; } </style> </defs> <g id="training" class="has-dropdown" tabindex="0"> <path class="training" d="m0,256c0-27.61,22.39-50,50-50,27.61,0,50,22.38,50,49.99,0-.21.02-.42.02-.63v29.39c0,11.06,8.45,20.15,19.25,21.15.02,0,.04.09,0,.09-.04,0-62.38,0-69.27,0,0,0,0,0,0,0s0,0,0,0h-.62c.1,0,.21,0,.31,0C22.22,305.82,0,283.51,0,256Z"/> <text class="font-md" transform="translate(31 285)">Training</text> </g> <g id="training-sub-menu" class="sub-menu"> <path class="training" d="m0,256c0-27.61,22.39-50,50-50,27.61,0,50,22.38,50,49.99,0-.21.02-.42.02-.63v29.39c0,11.06,8.45,20.15,19.25,21.15.02,0,.04.09,0,.09-.04,0-62.38,0-69.27,0,0,0,0,0,0,0s0,0,0,0h-.62c.1,0,.21,0,.31,0C22.22,305.82,0,283.51,0,256Z"/> <g id="text"> <text class="font-md sub-menu-item" transform="translate(31 285)"> <a href="https://google.com" target="_parent">Google</a> </text> <text class="font-md sub-menu-item" transform="translate(31 265)"> <a href="https://google.com" target="_parent">Google</a> </text> <text class="font-md sub-menu-item" transform="translate(31 245)"> <a href="https://google.com" target="_parent">Google</a> </text> </g> </g> </svg>
关键改动说明
- 给
.has-dropdown添加tabindex="0"和pointer-events: auto,让iOS Safari识别它为可交互元素,从而正常触发:hover状态 - 移除了对
visibility和height的过渡,仅保留opacity的过渡(这两个属性不支持平滑过渡,会导致动画失效) - 增加了
:focus状态支持,兼顾键盘交互场景 - 调整触发元素的隐藏逻辑,改用
opacity过渡替代直接隐藏,避免hover状态突然丢失导致动画中断
内容的提问来源于stack exchange,提问作者jylesy
相关产品推荐
相关产品推荐

