解决 border-radius 元素在应用了 transform 的子元素 时overflow:hidden 失效的问题
受大家启迪,于是最近深入研究了一下Css3中的一些属性。之中也是碰到了个不为我知的问题,在这里特此总结并与大家分享。
问题重现:在父元素上应用了 border-radius 的圆角属性、加上 overflow:hidden属性 、并且子元素填充整个父元素。于是看到的效果是:子元素超出父元素圆角的部分被隐藏掉,形成一个圆角头像容器的结构。代码如下:
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>test</title> <style> html,body{ width: 100%; height: 100%; } #father { width: 200px; height: 200px; overflow: hidden; border-radius: 50%; background-color: #ccc; } #child { background-color: red; width: 100%; height: 100%; -webkit-transition:all 0.5s ease; transition:all 0.5s ease; } </style> </head> <body> <div id="father"> <div id="child"></div> </div> </body> </html>
效果如下:
想着使用translate3d实现对半圆的动画效果,于是乎问题就显现了。
问题描述:对 #child
应用一个 transform
变化,使用 translate3d
对其进行横向偏移。会发现 #child
溢出了 #father
的圆角范围。 overfow:hidden
失效。
代码如下:
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>test</title> <style> html,body{ width: 100%; height: 100%; } #father { width: 200px; height: 200px; overflow: hidden; border-radius: 50%; background-color: #ccc; } #child { background-color: red; width: 100%; height: 100%; -webkit-transition:all 0.5s ease; transition:all 0.5s ease; } /*使用 translate3d 让子元素沿x正轴偏移100px*/ #child.add-translate { -webkit-transform:translate3d(100px,0,0); transform:translate3d(100px,0,0); } </style> </head> <body> <div id="father"> <div id="child" class="add-translate"></div> </div> </body> </html>
显示如下:
解决方案:
1:使用webkit-mask-image 覆盖圆角溢出部分。(文章后面会提供关于webkit-mask-image的相关介绍)
-webkit-mask-image 可以使用图片、Gradient 渐变或者 SVG mask 作为元素的 mask 遮罩。在 WebKit 的兼容性还算可以。
(图片来源于 CSS遮罩 – w3cplus )
回到刚才的问题。在这里使用一个纯黑色的 1px png 图像。应用 mask 遮罩解决该问题。在#father 上应用 add-mask-image类名后,#child触发 transform 动画后就不会出现溢出的问题了。代码如下:
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>test</title> <style> html,body{ width: 100%; height: 100%; } #father { width: 200px; height: 200px; overflow: hidden; border-radius: 50%; background-color: #ccc; } #child { background-color: red; width: 100%; height: 100%; -webkit-transition:all 0.5s ease; transition:all 0.5s ease; } /*使用 translate3d 让子元素沿x正轴偏移100px*/ #child.add-translate { -webkit-transform:translate3d(100px,0,0); transform:translate3d(100px,0,0); } /*使用 -webkit-mask-image 遮罩*/ #father.add-mask-image{ -webkit-mask-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAA5JREFUeNpiYGBgAAgwAAAEAAGbA+oJAAAAAElFTkSuQmCC); } </style> </head> <body> <div id="father" class="add-mask-image"> <div id="child" class="add-translate"></div> </div> </body> </html>
效果如下:
该问题在Stackoverflow的讨论:
webkit-overflow-issue-on-border-radius-and-transform
how-to-make-css3-rounded-corners-hide-overflow-in-chrome-opera
有关-webkit-mask-image的简单介绍:
http://ued.ctrip.com/webkitcss/prop/mask-image.html
2:父元素加上 transform 属性。
子元素在使用了 transform 属性后致使它改变了原有的默认维度,而这时的父元素无任何改变,仍为2d维度(css默认都为2d维度)。因此导致了子元素使用translate3d属 性后出现溢出的情况。接下来只要在原有的父元素样式中加上 transform 属性将父元素改变维度即可。(可以使用translate3d 或 rotate 解决)
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>test</title> <style> html,body{ width: 100%; height: 100%; } #father { width: 200px; height: 200px; overflow: hidden; border-radius: 50%; background-color: #ccc; transform:translate3d(0,0,0);/*父元素使用transform:translate3d 属性*/ -webkit-transform:translate3d(0,0,0); } #child { background-color: red; width: 100%; height: 100%; -webkit-transition:all 0.5s ease; transition:all 0.5s ease; } /*使用 translate3d 让子元素沿x正轴偏移100px*/ #child.add-translate { -webkit-transform:translate3d(100px,0,0); transform:translate3d(100px,0,0); } </style> </head> <body> <div id="father"> <div id="child" class="add-translate"></div> </div> </body> </html>
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>test</title> <style> html,body{ width: 100%; height: 100%; } #father { width: 200px; height: 200px; overflow: hidden; border-radius: 50%; background-color: #ccc; -webkit-transform:rotate(0deg);/*父元素使用transform:rotate 属性*/ transform: rotate(0deg); } #child { background-color: red; width: 100%; height: 100%; -webkit-transition:all 0.5s ease; transition:all 0.5s ease; } /*使用 translate3d 让子元素沿x正轴偏移100px*/ #child.add-translate { -webkit-transform:translate3d(100px,0,0); transform:translate3d(100px,0,0); } </style> </head> <body> <div id="father"> <div id="child" class="add-translate"></div> </div> </body> </html>
效果:同解决方案一中实现的效果如出一辙,在这里就不贴图了,有兴趣的朋友可以亲自证明一下。
transform的介绍:
三:补充内容(待注意)
1:关于感谢:
a:首先非常感谢大家对 Lying 的启迪。如有需要,留下你们的评论,随时提供服务。
b:感谢前文作者。Lying 在借鉴的原文章上增加了一些自个的见解。有时间咋们见个面呗
2:关于文章内容:
a:没有对浏览器做兼容测试。(搬砖中写的一篇文章)
b:Stackoverflow 上许多友人都说这是 google 的一个bug,因此在这里不能保证解决方案的第二条阐述的正确与否。但这条肯定是可以解决问题的 (chrome中亲测有效)
c:相信还会有其它的解决方案。(简单的看了 Stackoverflow 提供的一些方案,因此在这里没有列出,大家也可以查看文中提供的链接了解了解)
3:关于对Css 3 见解:
a:Css 3 的确是很值得学习的,今后 Lying 也会同大家一起一直保持着学习的积极性和善于分享的心。