原文:http://net.tutsplus.com/tutorials/html-css-techniques/build-a-kickbutt-css-only-3d-slideshow/
作者:Will Moyer
譯者:蔣宇捷(http://blog.csdn.net/hfahe)
友情提示:本文難度為中等,閱讀完需要45分鐘,理解需要一定的基礎。


[**下載**源文件](http://nettuts.s3.amazonaws.com/893_css3D/source_files/source_files.zip)
[**示例**在線觀看**](http://nettuts.s3.amazonaws.com/893_css3D/source_files/index.html)**
?譯者注:觀看示例請使用最新版的Safari(5.0.3以上版本)或Chrome(10.0.648以上版本),Chrome需打開about:flags,開啟“GPU加速合成”-使用圖形處理器 (GPU) 硬件啟用網頁的 3D CSS 和更高性能的合成。
?在這個教程里,我將要向你展示如何只使用HTML和CSS創建立體的幻燈片。完全不需要Javascript!開啟Safari,我們出發了!
**原理**
?在我們開始構造幻燈片之前,理解實現方法非常重要。我們將要使用CSS3新的屬性-3D變換。你可能看過其他教程,教你使用這些變換在3D空間內創建動畫物體。通常創建幻燈片時,我們依賴于Javascript以觸發這些變換。Javascript可以檢測到鼠標點擊事件,然后更改某個HTML元素的屬性(通常是添加一個類),更改的元素會擁有一個新的CSS類型。
?這個教程不一樣的地方在于,我們使用CSS代替Javascript來觸發點擊事件和更改元素的樣式。Jeffrey Way最近撰寫的[快速](http://net.tutsplus.com/tutorials/html-css-techniques/quick-tip-mimic-a-click-event-with-css/)[技巧](http://net.tutsplus.com/tutorials/html-css-techniques/quick-tip-mimic-a-click-event-with-css/)一文,描述了一種使用CSS的:target偽類來模仿點擊事件的方法。這里我們將使用到:focus偽類和HTML5的標簽<figcaption>,但是原理是一樣的。這個方法不一定比使用Javascript更佳,但是用到了HTML最新標簽的特性,是一個簡潔的選擇。
**準備:快速開始**
?讓我們從創建一個index.html和style.css開始。我們還需要創建一個名為images的文件夾。我們的3D物體將會是一個六面體,四面是940像素寬、400像素高,另外兩面是400像素寬、400像素高。我在源文件中包含了6幅圖像,把它們或者你自己的文件放在images文件夾下。
**第一步:**HTML**頁面**
?下面是我們基礎的HTML代碼。我們將所有的的元素和我們的幻燈片放在一個名為container的容器里。自然還需要創建一個名為slideshow的div元素。
~~~
<!DOCTYPE HTML><html lang="en-US"><head> <meta charset="UTF-8"> <title>CSS 3D Slideshow</title> <link rel="stylesheet" type="text/css" href="style.css"/></head><body> <div id="container"> <div id="slideshow"> </div> </div></body></html>?
~~~
????? 在slideshow里為六幅圖像創建如下代碼:
~~~
<figure id="box"><img src="images/face1.jpg"/><img src="images/face2.jpg"/><img src="images/face3.jpg"/><img src="images/face4.jpg"/><img src="images/face5.jpg"/><img src="images/face6.jpg"/></figure>?
~~~
?請注意到我們的圖像(3D物體的六面)放在一個id為box的<figure>標簽內。這個就是我們在幻燈片動起來時需要旋轉的元素。
**訣竅**
?現在允許我們只使用CSS來檢測事件點擊的秘訣來了。我們使用另外6個<figure>標簽來包圍box。每一個<figure>為我們3D物體描繪一個不同的旋轉方式。屬性tabindex允許這些元素接收偽元素:focus。每一個<figure>內部也需要一個<figcaption>元素。這些<figcaption>標題將為我們的按鈕服務。當我們點擊按鈕時,這些標題將會觸發父元素<figure>來接收:focus。這樣我們可以在box上使用6個不同的CSS轉換。以上可能聽起來有點復雜,但是一旦我們看到CSS就會很容易明白。現在,只需要使用6個<figure>包圍box,同時給每一個定義一個不同的tabindex和id。然后為每一個<figure>包含一個<figcaption>元素。
**最后的**HTML
?Index.html最后看起來就像這樣:
~~~
<!DOCTYPE HTML><html lang="en-US"><head> <meta charset="UTF-8"> <title>CSS 3D Slideshow</title> <link rel="stylesheet" type="text/css" href="style.css"/></head><body> <div id="container"> <div id="slideshow"> <figure tabindex=1 id="fig1"> <figcaption>Side 1</figcaption> <figure tabindex=2 id="fig2"> <figcaption>Side 2</figcaption> <figure tabindex=3 id="fig3"> <figcaption>Side 3</figcaption> <figure tabindex=4 id="fig4"> <figcaption>Side 4</figcaption> <figure tabindex=5 id="fig5"> <figcaption>Side 5</figcaption> <figure tabindex=6 id="fig6"> <figcaption>Side 6</figcaption> <figure id="box"> <img src="images/face1.jpg"/> <img src="images/face2.jpg"/> <img src="images/face3.jpg"/> <img src="images/face4.jpg"/> <img src="images/face5.jpg"/> <img src="images/face6.jpg"/> </figure> </figure> </figure> </figure> </figure> </figure> </figure> </div> <!-- End Slideshow --> </div> <!-- End Container --></body></html>?
~~~
**第二步:基本的**CSS
?首先,讓我們打開style.css并粘貼進一些初始的代碼(移除:focus會導致的outline非常重要)。
~~~
/* RESET */html, body, div, span, applet, object, iframe,h1, h2, h3, h4, h5, h6, p, blockquote, pre,a, abbr, acronym, address, big, cite, code,del, dfn, em, font, img, ins, kbd, q, s, samp,small, strike, strong, sub, sup, tt, var,b, u, i, center,dl, dt, dd, ol, ul, li,fieldset, form, label, legend,table, caption, tbody, tfoot, thead, tr, th, td { margin: 0; padding: 0; border: 0; outline: 0; font-size: 100%; vertical-align: baseline; background: transparent;}body { line-height: 1;}ol, ul { list-style: none;}blockquote, q { quotes: none;}blockquote:before, blockquote:after,q:before, q:after { content: ''; content: none;}:focus { outline: 0;}/* HTML5 tags */header, section, footer,aside, nav, article { display: block;}?
~~~
?現在,我們給頁面一個漂亮的漸變背景。
~~~
html { width: 100%; height: 100%; background-color: #FFFFFF; background-image: -moz-linear-gradient(top, #FFFFFF, #b3b3b3); background-image: -webkit-gradient(linear,left top,left bottom,color-stop(0, #FFFFFF),color-stop(1, #b3b3b3)); filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#FFFFFF', EndColorStr='#b3b3b3'); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#FFFFFF', EndColorStr='#b3b3b3')";}?
~~~
?Background-image屬性帶上了Mozilla和Webkit的前綴。如果你想要一個支持IE的版本,filter和-ms-filter屬性將為IE6、7、8創建漸變(我在常用的站點[www.css3please.com](http://www.css3please.com/)上構建了這些代碼)。
????? 現在,讓我們為我們的container、slideshow和盒子加上一些樣式。
~~~
#container { width: 960px; margin: 0 auto;}#slideshow { width: 900px; margin: 50px auto 0 auto; padding: 50px 0 0 0;}figure { display: inline;}#box { position: relative; display: block; width: 900px; height: 400px;}?
~~~
?我們的container,寬度為960像素,通過margin: 0 auto來實現居中。Slideshow div會有900像素寬,居中放置,距離頁面頂部50像素。我們還為它在頂部設置50個像素的padding邊距。Padding所在區域將會包含我們slideshow的按鈕-?<figcaption>元素,一旦我們為它們指定了位置。
?實際上包含我們slideshow的元素-box,被設置為和我們圖片一樣的大小。將它的position屬性設置為relative非常重要,因為我們將要把它的一些子元素設置為絕對定位。我們另外的<figure>元素將會被設置為display:inline,但是box元素需要設置為display:block。
?現在,設置我們6幅圖像的樣式。
~~~
#box img { position: absolute; top: 0; left: 0;}?
~~~
?我們將所有的圖像定義為絕對定位,它們將會在box的左上角上一副一副的疊在一起。(top和left缺省都是0,為了更加清晰我們還是進行了定義)現在,我們的slideshow看起來像是這樣。

????? 讓我們為?<figcaption>按鈕添加一些樣式。
~~~
figcaption { display: inline-block; width: 70px; height: 35px; background: rgba(0,0,0,0.6); border: 1px solid rgba(0,0,0,0.7); -moz-border-radius: 20px; -webkit-border-radius: 20px; border-radius: 20px; text-align: center; line-height: 35px; color: #ffffff; text-shadow: 1px 1px 1px #000000; cursor: pointer; position: relative; top: -50px; left: 150px; margin: 0 30px 0 0; -moz-transition: all 0.1s linear; -o-transition: all 0.1s linear; -webkit-transition: all 0.1s linear; transition: all 0.1s linear;}?
~~~
?以上樣式的第一段相當富有美感,它使按鈕半透明、具有圓角、文字居中同時還有陰影。它還使鼠標指針變為手型,用戶知道可以點擊。
**“確保按鈕在6個<figure>元素的邊界之外。否則,點擊按鈕實際上是在最里面<figure>?上注冊了一個點擊事件,而不是對應到按鈕的那一個。”**
?最后一點代碼添加變換。因為我們將要為<figcaptions>的鼠標hover狀態添加樣式。
~~~
figcaption:hover { background: rgba(0,0,0,0.8);}?
~~~
?我們定義好的按鈕看起來像如下一樣:

**第三步:**3D**容器**
?第一件要完成的事情是告訴瀏覽器我們需要一個3D空間。我們通過在父元素slideshow上使用perspective屬性來完成(加上-webkit前綴)。
~~~
#slideshow { width: 900px; margin: 50px auto 0 auto; padding: 50px 0 0 0; -webkit-perspective: 800; /* triggers a 3D space */}?
~~~
?Perspective屬性的值決定3D物體透視范圍大小,值越大3D效果越夸張。
?我們還需要將3D空間貫穿到所有的子元素上。我們將通過為所有的<figures>添加transform-style: preserve-3d屬性來實現(我們又一次使用了webkit前綴)。
~~~
figure { display: inline; -webkit-transform-style: preserve-3d; /* maintains 3D space */}?
~~~
?好吧,開始轉換每一面來創建3D盒子的時候到了。我們將通過nth-child偽類來選定每一幅圖像,但是為每一幅<img>指定一個id也是同樣可行的。確保你在樣式表的當前樣式下面添加這些代碼。
?如下是代碼,我會在下面解釋它。
~~~
#box img:nth-child(1) { -webkit-transform: rotateX(0deg) translateZ(200px);}#box img:nth-child(2) { -webkit-transform: rotateX(180deg) translateZ(200px);}#box img:nth-child(3) { -webkit-transform: rotateX(90deg) translateZ(200px);}#box img:nth-child(4) { -webkit-transform: rotateX(-90deg) translateZ(200px);}#box img:nth-child(5) { -webkit-transform: rotateY(-90deg) translateZ(200px);}#box img:nth-child(6) { -webkit-transform: rotateY(90deg) translateZ(700px);}?
~~~
?好了,下面是我們要做的事情。第一副圖像完全不旋轉,但是它將會在z軸上朝觀看者靠攏200個像素。

????? 第二副圖像沿x軸旋轉180度,使它遠離觀看者。然后它將在z軸上遠離觀看者200像素。

“請注意轉換的順序很要緊-旋轉改變物體的基點然后沿著新的軸進行轉化。”
?我們第三和第四幅圖分別沿x軸向下和向上旋轉。它們都將沿新的z軸方向轉換200個像素。


?記住,我們的盒子是900像素寬、400像素高和400像素高。940像素*400像素的四面都互相隔著400像素。這就是為什么我們將它們都朝相反的方向轉換200個像素的原因。我們將會將400像素*400像素的兩端相對的轉換900個像素。
?第五和第六幅圖現在在盒子的左側,并不在中間。因此,我們第五和第六幅圖將采用不同的轉換。第五幅圖將要沿y軸旋轉負90度來面朝左側,然后沿新的z軸轉換200像素。這將把它放置在3D物體的左側。第六幅圖沿y軸旋轉90度來右側,然后沿新的z軸轉換700像素。這將把它放置在3D物體的右側。


?對于查看我們已完成效果的最佳方式就是查看當前圖像的排列。如果你在Safari里預覽幻燈片你將看到如下效果:

?讓我們隱藏前面的一面-當其他圖像的位置都正確后我們再恢復它的顯示。
~~~
#box img:nth-child(1) { -webkit-transform: rotateX(0deg) translateZ(200px); display: none; /* temporarily hide */} ?
~~~
?現在我們可以看到盒子的內部。

?現在,移除我們第一副圖像上的display:none。你將會發現盒子和它原來的大小相比靠觀看者越近的部分看起來越大。最前面的一面看起來尤其的巨大和伸長。
?要糾正這個問題我們必須要將整個3D物體超觀看者相反的方向移動200像素。為box的樣式添加-webkit-transform:translateZ(-200px)。當我們在它之上時還需要添加transition屬性。
~~~
#box { position: relative; display: block; width: 900px; height: 400px; -webkit-transform: translateZ(-200px); /* Pushes 3D object back into place */ -webkit-transition: -webkit-transform 1s; /* Enables transitions for transforms */}?
~~~
?完成這些設置后,我們將要開始讓我們的盒子動起來。
**第四步:動畫**
?粘貼我們樣式的最后一段。它將添加動畫效果,我將在下面解釋更多細節。
~~~
#fig1:focus #box { -webkit-transform: translateZ(-200px) rotateY(0deg);}#fig2:focus #box { -webkit-transform: translateZ(-200px) rotateX(-180deg);}#fig3:focus #box { -webkit-transform: translateZ(-200px) rotateX(-90deg);}#fig4:focus #box { -webkit-transform: translateZ(-200px) rotateX(90deg);}#fig5:focus #box { -webkit-transform: translateZ(-450px) rotateY(90deg);}#fig6:focus #box { -webkit-transform: translateZ(-450px) rotateY(-90deg);}?
~~~
?當我們?<figure>元素的每一面接收偽類:focus,我們旋轉box以顯示對應的那一面。注意box的旋轉都與在每一面上使用的旋轉相反。例如,第四幅圖像沿x軸旋轉負90度,要達到這樣的效果,我們必須要將整個3D物體沿x軸旋轉90度。這個轉換確保3D物體我們將要看到的那一面總是沿著正確的距離離去。
?這就是它了!在Safari里查看幻燈片,保證一切工作正常。

**最后的**CSS
?最后style.css里的樣式看起來會是這樣:
~~~
/* RESET */html, body, div, span, applet, object, iframe,h1, h2, h3, h4, h5, h6, p, blockquote, pre,a, abbr, acronym, address, big, cite, code,del, dfn, em, font, img, ins, kbd, q, s, samp,small, strike, strong, sub, sup, tt, var,b, u, i, center,dl, dt, dd, ol, ul, li,fieldset, form, label, legend,table, caption, tbody, tfoot, thead, tr, th, td { margin: 0; padding: 0; border: 0; outline: 0; font-size: 100%; vertical-align: baseline; background: transparent;}body { line-height: 1;}ol, ul { list-style: none;}blockquote, q { quotes: none;}blockquote:before, blockquote:after,q:before, q:after { content: ''; content: none;}:focus { outline: 0;}/* HTML5 tags */header, section, footer,aside, nav, article { display: block;}html { width: 100%; height: 100%; background-color: #FFFFFF; background-image: -moz-linear-gradient(top, #FFFFFF, #b3b3b3); background-image: -webkit-gradient(linear,left top,left bottom,color-stop(0, #FFFFFF),color-stop(1, #b3b3b3)); filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#FFFFFF', EndColorStr='#b3b3b3'); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#FFFFFF', EndColorStr='#b3b3b3')";}#container { width: 960px; margin: 0 auto;}#slideshow { width: 900px; margin: 50px auto 0 auto; padding: 50px 0 0 0; -webkit-perspective: 800; /* triggers a 3D space */}figure { display: inline; -webkit-transform-style: preserve-3d; /* maintains 3D space */}#box { position: relative; display: block; width: 900px; height: 400px; -webkit-transform: translateZ(-200px); /* Pushes 3D object back into place */ -webkit-transition: -webkit-transform 1s; /* Enables transitions for transforms */}#box img { position: absolute; top: 0; left: 0;}figcaption { display: inline-block; width: 70px; height: 35px; background: rgba(0,0,0,0.6); border: 1px solid rgba(0,0,0,0.7); -moz-border-radius: 20px; -webkit-border-radius: 20px; border-radius: 20px; text-align: center; line-height: 35px; color: #ffffff; text-shadow: 1px 1px 1px #000000; cursor: pointer; position: relative; top: -50px; left: 150px; margin: 0 30px 0 0; -moz-transition: all 0.1s linear; -o-transition: all 0.1s linear; -webkit-transition: all 0.1s linear; transition: all 0.1s linear;}figcaption:hover { background: rgba(0,0,0,0.8);}#box img:nth-child(1) { -webkit-transform: rotateX(0deg) translateZ(200px);}#box img:nth-child(2) { -webkit-transform: rotateX(180deg) translateZ(200px);}#box img:nth-child(3) { -webkit-transform: rotateX(90deg) translateZ(200px);}#box img:nth-child(4) { -webkit-transform: rotateX(-90deg) translateZ(200px);}#box img:nth-child(5) { -webkit-transform: rotateY(-90deg) translateZ(200px);}#box img:nth-child(6) { -webkit-transform: rotateY(90deg) translateZ(700px);}#fig1:focus #box { -webkit-transform: translateZ(-200px) rotateY(0deg);}#fig2:focus #box { -webkit-transform: translateZ(-200px) rotateX(-180deg);}#fig3:focus #box { -webkit-transform: translateZ(-200px) rotateX(-90deg);}#fig4:focus #box { -webkit-transform: translateZ(-200px) rotateX(90deg);}#fig5:focus #box { -webkit-transform: translateZ(-450px) rotateY(90deg);}#fig6:focus #box { -webkit-transform: translateZ(-450px) rotateY(-90deg);}?
~~~
**最后的思考**
?可能沒有方法證明使用許多嵌套的<figure>和<figcaption>元素作為按鈕是當前CSS3的推薦方式。這個試驗也并沒考慮到HTML內容、CSS樣式和JS行為的區別。既然這些轉換現在只能在Safari中表示,這個幻燈片并沒有可能在客戶端的項目中應用。但是這個試驗的意義在于展示和推動HTML5和CSS3新特性的應用。
?如果你對于讓這個幻燈片支持更多的瀏覽器感興趣,這里有一些有益的提示:
- 使用Modernizr(Modernizr 是一個利用 JS 和 CSS 來檢測瀏覽器所支持功能的小工具)。我是認真的。
- 只有Safari支持3D轉換,但是你可以使用2D轉換創建一個支持更多瀏覽器的酷炫幻燈。
- Opacity透明度屬性可以創建一個強大的淡入淡出幻燈,幾乎支持全部的瀏覽器(在IE上可以使用filter)。
- 絕對定位的<figcaption>按鈕在Firefox下會產生截斷。我知道這非常神奇。確保你使用的是相對定位。
?我希望朋友們喜歡這個教程。我渴望你們的回復,感謝你們閱讀本文!
- 前言
- AutoPager的簡單實現
- 利用CSS3特性巧妙實現漂亮的DIV箭頭
- IE9在Win7下任務欄新特性簡介
- 瀏覽器九宮格的簡單實現
- Raphael js庫簡介
- 使用CSS3構建Ajax加載動畫
- 用CSS3創建動畫價格表
- 用CSS3實現瀏覽器的縮放功能
- 用純CSS3實現QQ LOGO
- 用CSS3創建旋轉載入器
- 使用Javascript開發移動應用程序
- 用HTML5創建超酷圖像灰度漸變效果
- 使用CSS3創建文字顏色漸變(CSS3 Text Gradient)
- 僅用CSS創建立體旋轉幻燈片
- 如何創建跨瀏覽器的HTML5表單
- 用CSS3實現動畫進度條
- HTML5 Guitar Tab Player
- 奇妙的HTML5 Canvas動畫實例
- 談HTML5和CSS3的國際化支持
- 實現跨瀏覽器的HTML5占位符
- 前端開發必備工具:WhatFont Bookmarklet-方便的查詢網頁上的字體
- 使用HTML5和CSS3來創建幻燈片
- HTML5之美
- 如何使用HTML5創建在線精美簡歷
- 以小見大、由淺入深-談如何面試Javascript工程師
- 快速入門:HTML5強大的Details元素
- 用CSS3實現圖像風格
- HTML5視頻字幕與WebVTT
- 用純CSS3實現Path華麗動畫
- 用3個步驟實現響應式網頁設計
- 遇見CSS3濾鏡
- 關于CSS3濾鏡的碎念
- 用純CSS3繪制萌系漫畫人物動態頭像
- CSS3新的鼠標樣式介紹
- 用HTML5獻上愛的3D玫瑰
- 對HTML5 Device API相關規范的解惑
- 如何使用HTML5實現拍照上傳應用
- 2012第一季度國外HTML5移動開發趨勢
- HTML5新特性:范圍樣式
- 百度開發者大會-《用HTML5新特性開發移動App》PPT分享
- Chrome 19對于HTML5最新支持的動態:電池狀態API,全屏API,震動API,語音API
- 遇見Javascript類型數組(Typed Array)
- 用HTML5 Audio API開發游戲音樂
- 用HTML5實現人臉識別
- 用Javascript實現人臉美容
- Chrome 20對于HTML5最新支持的動態:顏色輸入,網絡信息API,CSS著色器
- 用HTML5實現手機搖一搖的功能
- 用HTML5實現iPad應用無限平滑滾動
- 用非響應式設計構建跨端Web App
- 了解SVG
- HTML5圖像適配介紹
- HTML5安全:內容安全策略(CSP)簡介
- HTML5安全:CORS(跨域資源共享)簡介
- 用CSS3 Region和3D變換實現書籍翻頁效果
- 談談移動App的思維誤區
- Chrome新特性:文件夾拖拽支持
- 《關注HTML5安全》
- HTML5安全風險詳析之一:CORS攻擊
- HTML5安全風險詳析之二:Web Storage攻擊
- HTML5圖像適配最新進展:響應式圖片規范草案
- HTML5移動Web App相關標準狀態及路線圖
- HTML5安全風險詳析之三:WebSQL攻擊
- Chrome引入WebRTC支持視頻聊天App
- HTML5安全風險詳析之四:Web Worker攻擊
- HTML5安全風險詳析之五:劫持攻擊
- HTML5安全風險詳析之六:API攻擊
- HTML5安全攻防詳析之七:新標簽攻擊
- 在iOS Safari中播放離線音頻
- 使用WebRTC實現遠程屏幕共享
- Firefox、Android、iOS遇見WebRTC
- HTML5光線傳感器簡介
- HTML5安全攻防詳析之八:Web Socket攻擊
- HTML5安全攻防詳析之完結篇:HTML5對安全的改進
- 激動人心!在網頁上通過語音輸入文字 - HTML5 Web Speech API介紹
- Web滾動性能優化實戰
- 用CSS3設計響應式導航菜單
- 用HTML5構建高性能視差網站
- 漫談@supports與CSS3條件規則
- HTML5下載屬性簡介
- 如何開發優秀的HTML5游戲?-迪斯尼《尋找奧茲之路》游戲技術詳解(一)
- 如何開發優秀的HTML5游戲?-迪斯尼《尋找奧茲之路》游戲技術詳解(二)
- 趨勢:Chrome為打包應用提供強大新特性
- 從HTML5移動應用現狀談發展趨勢
- 基于HTML5的Web跨設備超聲波通信方案