CSS3图片翻转切换案例及其中重要属性解析
无意中发现CSS3的方案, http://www.webhek.com/css-flip/ 赶紧学习并总结如下
先上代码(多数照搬自上述链接,有很大兼容问题,小心使用)
HTML:
div class="flip-container">
div class="flipper">
div class="front">here is content : AAdiv>
div class="back">here is content : BBdiv>
div>
div>
CSS:
.flip-container { margin: 30px; display: inline-block; border: 1px solid #aaa; -webkit-perspective: 500; -moz-perspective: 500; -ms-perspective: 500; perspective: 500; -ms-transform: perspective(500px); -moz-transform: perspective(500px); /*重要*/ transform-style: preserve-3d; /*重要*/ } .flipper { position: relative; width: 200px; height: 200px; transition: 0.6s; transform-style: preserve-3d; /*重要*/ } /* 触发翻转 */ .flip-container:hover .flipper{ transform: rotateY(180deg); } .front ,.back{ position: absolute; left: 0; top: 0; backface-visibility: hidden; /*重要*/ width: 100%; height: 100%; } .front { transform: rotateY(0deg); z-index: 2; background: red; } .back { transform: rotateY(-180deg); background: green; }
- 在最外层的容器元素上设置整个动画区域的透视(perspective)属性。
- 当外层容器元素遇到鼠标悬停事件时,内部存放卡片的容器旋转180度。这里也是控制旋转速度的地方。如果将旋转值设置为-180deg,是反向旋转。
- 表示卡片正面和背面的元素都要绝对定位,这样它们才能在相同的位置相互遮挡。它们的背面可视性(backface-visibility)属性设置为隐藏,这样每个卡片的背面在翻转时都是看不见的。
- 将卡片的正面设置为一个比背面要高的z-index值,这样保证卡片的正面在最上面。
- 将背面卡片旋转180度,这样让它扮演背面的角色。
照搬结束,其中CSS中注释了重要的需要特别注意。
perspective 属性定义 3D 元素距视图的距离,以像素计。直观现象就是内层的元素在翻转时会溢出外层边框,如果不写,或者属性值为0,则只在外层边框内变化。
且属性值需要特别注意和需要翻转的元素的宽高相适应,太少溢出很夸张,太多了和设为0的区别不大。区别效果如下图所示
transform-style: preserve-3d; transform-style 属性规定如何在 3D 空间中呈现被嵌套的元素(照抄自w3cschool)。
flip-container 和 flipper 都需要设置,flip-container不设置会导致溢出的3D效果缺少,flipper 不设置则容器翻转后,我们看到的还是front的背面,backface-visibility: hidden不能体现效果。
比较坑的是transform-style即使在IE11中都是不支持的。
所以还有一个兼容IE的方案,就是不翻转容器,而是同时翻转front和back,幸好IE还是支持backface-visibility: hidden的,所以翻转效果和上一个方案一致。
HTML如下:
div class="flip-container">
div class="front">here is content : AAdiv>
div class="back">here is content : BBdiv>
div>
由于直接翻转front和back,flipper就显得多余了,去掉了flipper。
CSS代码如下(经过多方试验,尽量支持各个浏览器,并降级处理了不支持CSS3翻转的浏览器,保留了切换效果)
.flip-container { -webkit-perspective: 500; -moz-perspective: 500; -ms-perspective: 500; perspective: 500; -ms-transform: perspective(500px); -moz-transform: perspective(500px); -moz-transform-style: preserve-3d; -ms-transform-style: preserve-3d; margin: 30px; display: inline-block; border: 1px solid #aaa; position: relative; } /*由于内层绝对定位导致高度缺少,这里显式设置了宽高*/ .flip-container, .front, .back { width: 200px; height: 200px; } .flip-container:hover .front { -webkit-transform: rotateY(180deg); -moz-transform: rotateY(180deg); -o-transform: rotateY(180deg); -ms-transform: rotateY(180deg); transform: rotateY(180deg); } .flip-container:hover .back { -webkit-transform: rotateY(0deg); -moz-transform: rotateY(0deg); -o-transform: rotateY(0deg); -ms-transform: rotateY(0deg); transform: rotateY(0deg); z-index: 3; /* 降级处理不支持CSS3的浏览器,只是简单的将back上升盖住front */ } .front, .back { -webkit-backface-visibility: hidden; -moz-backface-visibility: hidden; -ms-backface-visibility: hidden; backface-visibility: hidden; -webkit-transition: 0.6s; -moz-transition: 0.6s; -o-transition: 0.6s; -ms-transition: 0.6s; transition: 0.6s; position: absolute; top: 0px; left: 0px; } .front { background: red; z-index: 2; } .back { background: green; -webkit-transform: rotateY(-180deg); -moz-transform: rotateY(-180deg); -o-transform: rotateY(-180deg); -ms-transform: rotateY(-180deg); transform: rotateY(-180deg); }
以上也许有许多不必要的兼容代码,水平有限了,欢迎交流更简练的写法。
还有一个小TIPS,在其他情况使用hover触发元素翻转时应如下使用,固定宽高的父元素触发,子元素翻转
.outer { width: 200px; height: 200px; } .inner { transition: 0.6s; } .outer:hover .inner{ transform: rotateY(180deg); }
如下直接对元素hover触发翻转会有很大的使用问题,因为元素翻转过程中,元素区域变小,光标就脱离元素了,于是元素还原,又触发hover变小,造成不顺畅
.inner { width: 200px; height: 200px;
transition: 0.6s; } .inner:hover{ transform: rotateY(180deg); }