CSS transition transform在Safari中不生效如何修复
Safari下details展开标记旋转动画兼容修复
问题根因
Safari对原生<details>元素的open属性做了特殊渲染优化:当属性切换时,浏览器会直接合并伪元素的样式变更,跳过过渡动画的中间帧直接渲染最终状态。你之前尝试的添加浏览器前缀、修改过渡属性范围等方案,都是针对普通元素transform/transition失效的通用修复,无法解决这个原生组件的特殊渲染逻辑问题。
修复步骤
- 用CSS自定义属性中转旋转状态,同时补全transform、transition属性的webkit前缀,覆盖旧版Safari的属性支持
- 拦截summary的默认点击行为,手动控制details的open属性切换,通过强制重绘让Safari识别到状态前后的样式差异,触发过渡
- 补全标准语法下的默认标记隐藏规则,避免新版Safari显示默认箭头
完整修复代码
CSS部分
details { width: 50%; margin: 0 auto; background: #FDF4E3; margin-bottom: .5rem; border-radius: 5px; color: black; outline: 0; } summary { padding: 1rem; display: block; padding-left: 2.2rem; position: relative; cursor: pointer; -webkit-tap-highlight-color: transparent; list-style: none; } summary:before { content: ''; border-width: .4rem; border-style: solid; border-color: transparent transparent transparent #fff; position: absolute; top: 1.3rem; left: 1rem; /* 通过CSS变量控制旋转角度 */ --arrow-rotate: 0deg; -webkit-transform: rotate(var(--arrow-rotate)); transform: rotate(var(--arrow-rotate)); -webkit-transform-origin: .2rem 50%; transform-origin: .2rem 50%; /* 兼容带前缀和标准语法的过渡属性 */ -webkit-transition: 1s -webkit-transform ease; transition: 1s transform ease, 1s -webkit-transform ease; } details[open] summary { background: #F9D478; } details[open] > summary:before { --arrow-rotate: 90deg; } /* 隐藏所有浏览器默认的details标记 */ details summary::-webkit-details-marker { display: none; } details summary::marker { display: none; content: ''; } details p { padding: 1rem; margin: 0; }
JS部分
document.querySelectorAll('details').forEach(detailEl => { const summaryEl = detailEl.querySelector('summary'); summaryEl.addEventListener('click', (e) => { // 拦截默认的瞬间切换逻辑 e.preventDefault(); const isCurrentlyOpen = detailEl.hasAttribute('open'); if (isCurrentlyOpen) { // 收起状态:等待一帧后移除open属性,保证动画执行 requestAnimationFrame(() => { detailEl.removeAttribute('open'); }); } else { // 展开状态:先添加open属性,强制触发重绘让过渡生效 detailEl.setAttribute('open', ''); detailEl.offsetHeight; // 读取DOM属性强制浏览器重排重绘 } }); });
兼容兜底
如果需要兼容iOS12及以下不支持CSS自定义属性的极旧Safari版本,可以把summary:before实现的三角形箭头替换为summary内部的真实<span>子元素,动画逻辑完全一致,兼容性覆盖范围更广。
内容的提问来源于stack exchange,提问作者mahan
相关产品推荐
相关产品推荐

