Safari中含transform-style:preserve-3d的div内元素CSS hover样式失效问题
解决Safari中transform-style:preserve-3d容器内hover样式失效问题
问题场景
我实现了一个视差滚动头部组件,其中的Unsplash社交图标配置了hover样式(鼠标悬停时变为橙色、光标变为指针),但该样式在Safari浏览器中完全不生效。移除容器上的transform-style: preserve-3d属性后,hover样式恢复正常,但会直接破坏视差滚动效果,而这个功能在Chrome浏览器中运行完全正常。
代码示例
<!doctype html> <html class="h-full"> <head> <script src="https://cdn.tailwindcss.com/3.3.1"></script> </head> <div class="h-screen"> <div class="flex h-full flex-col overflow-hidden overflow-y-auto bg-stone-900"> <div class="scrollbar-thin scrollbar-thumb-orange-400 scrollbar-track-none scrollbar-thumb-rounded-full w-full flex-1 overflow-x-hidden overflow-y-hidden overflow-y-scroll scroll-smooth bg-stone-900" style="perspective: 10px"> <div class="relative flex h-full items-center justify-center" style="transform-style: preserve-3d"> <div class="container m-1 lg:w-3/4" style="transform: translateZ(-5px) scale(1.5)"> <h2 class="font-bungee-hairline inline bg-stone-900 box-decoration-clone p-4 text-3xl font-bold leading-normal text-white hover:bg-red-800 sm:text-4xl md:text-6xl md:leading-tight">Travel &<br />Landscape<br />Photography</h2> <div class="mt-4 flex w-min bg-stone-900 px-6 py-4"> <a :href="links.unsplash" aria-label="Unsplash" target="_blank" ><svg class="mr-4 h-6 w-6 fill-white transition hover:cursor-pointer hover:fill-orange-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"> <path d="M448,230.17V480H0V230.17H141.13V355.09H306.87V230.17ZM306.87,32H141.13V156.91H306.87Z" /></svg ></a> </div> </div> <img class="absolute z-[-1] h-full w-full object-cover" src="https://images.unsplash.com/photo-1661173357770-619fcd1388af?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2340&q=80" alt="A Ginormous salt lake reflecting like a mirror in Turkey at sunset" style="transform: translateZ(-20px) scale(3)" /> </div> </div> </div> </div>
原因分析
这是Safari浏览器的已知渲染bug:当元素处于设置了transform-style: preserve-3d的容器下时,浏览器会将该容器内的元素放入独立的3D渲染层,导致鼠标交互事件(如hover)无法被正确识别和触发。
解决方案
方案1:给hover元素添加transform: translateZ(0)
给需要触发hover效果的元素(这里是<a>标签或<svg>)添加transform: translateZ(0)样式,强制浏览器将元素归入正确的渲染层,既不会破坏原有的视差效果,又能让hover样式正常生效。
修改后的图标代码:
<a :href="links.unsplash" aria-label="Unsplash" target="_blank" style="transform: translateZ(0)"> <svg class="mr-4 h-6 w-6 fill-white transition hover:cursor-pointer hover:fill-orange-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"> <path d="M448,230.17V480H0V230.17H141.13V355.09H306.87V230.17ZM306.87,32H141.13V156.91H306.87Z" /> </svg> </a>
如果用Tailwind CSS,可以直接在class里添加transform translate-z-0。
方案2:替换preserve-3d实现视差
如果方案1无效,可以尝试移除父容器的perspective和transform-style: preserve-3d,直接给需要实现视差的元素设置perspective属性,同样能达到视差效果,同时规避Safari的bug。
修改后的关键代码:
<!-- 移除父容器的perspective和transform-style: preserve-3d --> <div class="scrollbar-thin scrollbar-thumb-orange-400 scrollbar-track-none scrollbar-thumb-rounded-full w-full flex-1 overflow-x-hidden overflow-y-hidden overflow-y-scroll scroll-smooth bg-stone-900"> <div class="relative flex h-full items-center justify-center"> <!-- 给文本容器添加perspective --> <div class="container m-1 lg:w-3/4" style="transform: perspective(10px) translateZ(-5px) scale(1.5)"> <!-- 文本内容不变 --> </div> <!-- 给图片添加perspective --> <img class="absolute z-[-1] h-full w-full object-cover" src="..." alt="..." style="transform: perspective(10px) translateZ(-20px) scale(3)" /> </div> </div>
验证效果
修改后在Safari浏览器中测试,hover样式应该能正常触发,同时视差滚动效果保持不变。
内容的提问来源于stack exchange,提问作者Aydin Hassan
相关产品推荐
相关产品推荐

