纯CSS3透明水晶盒
相信大家有看过这个例子:3D盒子,在书《CSS3 实战》上第282页有个综合实战“设计动态立体盒子”的例子,实现方式跟它一样,我的盒子也是以它为原型来设计的,不过在实现方面有做修改、优化,以及增添了一些细节,下面是我的盒子Firefox截图:
- 透明化了盒子,通透性强了,因为透明了,所以背部的三个面也就要做出来了,所以总共6个面,比原作多3个;
- 投影镜像,让盒子的立体感更强烈;
- 边角线的处理,让盒子面与面之间过渡和谐。
你可以点击这里下载 源代码(只是写了moz下的效果,webkit的就没写了)
盒子的HTML结构很简单,如下:
1 2 3 4 5 6 7 8 | <div> <div>前</div> <div>后</div> <div>左</div> <div>右</div> <div>上</div> <div>下</div> </div> |
一个大盒子包住“前、后、左、右、上、下”6个面,因为定位产生层高的关系,所以它的顺序其实是“后、下、左、前、上、右”,下面的div就会自然的叠在上面,就可以不写z-index了。
一、框架定位
初始化盒子面,顶好宽高、定位、背景色等属性,然后把变换原点设定在右上角。
盒子面一个个做,先从简单的入手,前后左右难度系数是一样的,一个斜切SKEW效果就可以实现,然后就是再分开定位:“前、后面”用 skew(0deg,20deg); Y轴正向斜切,“左、右面”用skew(0deg,-20deg); Y轴负向斜切,然后再定位对齐,基本的框就出来 了。
然后就是鸡肋“上、下面”,它需要旋转后斜切才能完成,所以难度系数也就上升了,这里我说 “旋转后斜切”,而不是 “斜切后旋转”,是有区别的,我的写法如下:
-moz-transform:rotate(-40deg) skew(30deg,20deg);
如果这样写:
-moz-transform:skew(30deg,20deg) rotate(-40deg);
那跟预期的效果不一样,确定了的斜切效果会因为后面的旋转而变形。
不知道你有没有亲手做过那个盒子,我在做的时候发现,为什么它顶部的“盒子盖”比侧面的“盒子壁”多嵌套了一层DIV,用来分离transform变换效果,我尝试着只用一个DIV去实现,结果证明,只要先写rotate再skew就可以保持skew的斜切效果,从而html结构跟css代码也就简洁了很多。
二、边框线
如果你看了代码,没有头晕的话,会不会有这么一个疑惑,为什么不用border来写边框线?
如果用border来写的话,border的宽度会跟width重叠,导致盒子占据的空间为200+1+1=202px,很恶心的数字,而且border也不贴着边界,如图:
所以用这样一种做法来实现边框效果:box-shadow/text-shadow ;
一般我们是用border来给元素描边,前几天逛论坛的时候,看到这样一种做法:给文字描边。
一般思维会想到text-shadow这个属性,但是它是投影,跟描边还是有区别的,text-shadow写法如下:
text-shadow:2px 0px 0px #f00;
投影效果如图:
具体的投影资料可以参考我这篇文章:CSS3阴影;
上面是在没有羽化的情况下向右偏移,然而text-shadow可以多重投影,那么如果向上下左右四个方向同时投影,会怎么样呢?
text-shadow:2px 0px 0px #f00,0px -2px 0px #f00,-2px 0px 0px #f00,0px 2px 0px #f00;
投影效果如图:
就变成适应文字形状的描边效果了,当初因为border不能满足文字的描边需求,才想出这样的法子来实现描边,那现在反推,既然border不能用来描边了,那就用box-shadow投影描边的方法来实现边框。
做出来的效果如下:
我给底部写了个投影:
-webkit-box-shadow:-1px 1px 2px rgba(50,50,50,0.1);
少许的向前向右偏移,基本的造型效果就已经出来了,但是这样还不行,盒子的透明是透明了,但是感觉朦朦胧胧的,应该加强透明的处理,要不然体现不出通透性(可以跟第一个图对比下)。
三、通透性
每个面受光不同,所以透明度也应该有所区别,我把上,前,右对着浏览者的透明度调低于后面,然后拉出半透明到透明的渐变叠加到基本的盒子颜色上,产生层次,我都是很淡的过渡色叠加,渐变写法如下:
background:-moz-linear-gradient(-45deg, rgba(255,255,255,0.3),rgba(255,255,255,0.2) 40%,rgba(255,255,255,0.2) 70%,rgba(255,255,255,0.1));
由左上到右下拉斜线渐变,从0% 0.3到40% 0.2,70% 0.2到100% 0.1;颜色很淡,如果把系数调大调深的话,渐变色就会很明显,由于里面各个面的渐变各不同,就不一一解释,相信看了源文件就会明白的了,我也是跟着自己感觉拉的渐变,没有很专业的光线投射研究,如果有错的地方你看出来了还望指出。
当调整出各个面的颜色之后,发现“前上右”面与面之间有边线分割,看起来很整齐,但是后面我原本没有画边线,结果‘左’跟‘后’有点混,所以还是12条边线一一画出,妥当些,前面的边线透明度为0.6,侧面的0.4,后面的0.2,突出层次。
四、投影
原本想用reflect来实现投影的,但是效果不理想,投影会夹杂着原图层的背景色,做不出来半透明到透明的效果来,而且reflect是webkit独 有的,firefox没有,另想它法,然而不可能为了投影效果添加新标签,得不偿失,在抛弃IE的情况下自然而然的会想到伪类,上面边框渐变 已经用了after,所以这里的投影我用before来做,同时,伪类做投影还有个好处:伪类层是相对于原图层的,所以修改原图层位置变形状态的时候,伪类层也会相对的修改。定位在对应的面正下方,向着用户的只有前跟右,所以就做了两个投影,如图:
普通状态盒子是闭合的,如“前”面所示,伪类层也跟着原图层一样进行了斜切变换,然后我设置了鼠标滑过就“打开”的效果,仅仅是这样一行代码:
.box .box_right:hover{-moz-transform:skew(0deg, 0deg);}
让不用去修改伪类投影层,它自动的就适应了原图层,恢复了变换状态。
还有一个点,就是投影是由上至下呈半透明至透明的渐变,对于背景色这个很容易就可以实现,但是边框呢?
我还没处理边框的状态是这样的:
下面的投影是“平”,所以边框线的渐变投影务必做出来,那怎么才能实现边框的纵向渐变,网上有很多关于渐变边框的做法,不过都是横向的利用多重边框的特性来制作,纵向的没有,我尝试用border来写,给border-color写个渐变,结果根本读不出来,单单调节border的透明度也只是做到单色透明,不能渐变透明,观察之后,想出了个“烂点子”,我上面说了,投影是由上至下呈半透明至透明的渐变,那么把两个不透明的东西叠加在一起会怎么样?
比如一个透明度为0.3的层叠在另外一个透明度为0.3的层上面,那就会在交界的地方产生一个透明度为0.6的区域,如图:
说到这样你应该懂了吧,我写了这么一句修改面的宽度:
.under .box_before:before{ width:201px;}
让两个面半透明面重叠,这样中间重叠区域就会变深,做出了“伪边框”的效果,至于到透明部分,0 + 0 = 0,所以透明的区域依然透明,从而实现了边框纵向渐变的效果。
五、内容
我原本只是想做个盒子,既然做出来了,当然要跟实际项目联系一下,如果允许的话我也想运用到真正的项目上去,将盒子作为载体模块,在上面发布文章,甚至我想把他弄成可以旋转的做图片墙。
挂上文字后效果如下:
html代码如下:
<div class="inBox"> <div class="conBox"> <h3>中秋节要来啦</h3> <p>中秋节要来啦,龙祝大家中秋有月饼吃...哈根达斯冰皮的...</p> </div> </div>
之所以要在inBox里面套一个conBox,conBox用来设定内边距padding,这样做是因为inBox设定了width,如果width跟padding混在一起叠加,会使容器的宽度变形,所以一般分开为妙;至于h3写个title,是因为我在写gotrip的时候,h1,h2,h3标题没有统一分级,使用混乱,而css是这样写的,比如:.inBox h1{ };
当时写了一批之后有同事提出需要将h1改成h3,如果我一开始就这样写.inBox .title{ },那他说修改的时候我也就只需要修改html标签,我不用动css的,吃一堑长一智,这里写下来跟大家分享。当然有时候也不必太过强求,毕竟 起类名是一件很伤脑细胞的事 哈。
个人博客原文地址:纯CSS3透明水晶盒