相信大家有看過這個例子:3D盒子,在書《CSS3 實戰》上第282頁有個綜合實戰“設計動態立體盒子”的例子,實現方式跟它一樣,我的盒子也是以它為原型來設計的,不過在實現方面有做修改、優化,以及增添了一些細節,下面是我的盒子Firefox截圖:
你可以點擊這裡下載 源代碼(只是寫了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的,吃一塹長一智,這裡寫下來跟大家分享。當然有時候也不必太過強求,畢竟 起類名是一件很傷腦細胞的事 哈。