起點中文網 3D 書封之最佳實踐

起點中文網 3D 書封之最佳實踐

32 人贊了文章

本文作者:楊曄

原創聲明: 本文為閱文前端團隊 YFE 成員出品,請尊重原創,轉載請聯繫微信公眾號 ( id: yuewen_YFE ) 獲取授權,並註明作者、出處和鏈接。

前言

官網,一個作為網站第一入口的頁面,直接影響著用戶進入站點的第一印象。但縱覽國內的所有文學類、小說類網站,大多都以推內容為主。在書本的視覺表現上都千篇一律 —— 一張簡單的書封面,或是帶有外邊框的書封面,又或者是帶有投影的書封面。其實到目前為止至少我見過的此類網站,都只是一張單調的運營平面圖片。今天所要介紹的就是在2016年起點中文網改版中對整體視覺進行優化的一個環節 —— 可被運營的《批量3D書封面》。《起點中文網》作為文學類網站的領導者,此次改版我們希望能以「創新的面貌"給用戶帶來眼前一亮,在不影響業務的前提下,我們做出了在書本上優化視覺的嘗試,趕緊來看一下是如何實現的吧!體驗鏈接:qidian.com

索引

  1. HTML 結構的思路 - 1分鐘閱讀
  2. 透視與 3D空間 - 2分鐘閱讀
  3. 書封旋轉的具體實現 - 4分鐘閱讀
  4. 兼容性 - 6分鐘閱讀

普通書封 與 3D 書封

一、HTML 結構的思路

也許你曾經在搜索引擎中找到過類似的 3D 書本效果,並且他可能還帶有很炫的翻書特效:

但以上這個例子,開發者用了 2 組 ul 和多個 li(至少5個以上),並且帶有各種 beforeafter 偽元素來實現層疊的紙張和翻書效果。這可能適合某個運營專題類網頁的創意特效,讓人覺得挺炫酷。但這顯然是不適合放在官網作為內容維護,我們並不希望它是由那麼多 HTML 標籤來實現,一方面不好維護,另一方面我們還需要考慮對老瀏覽器進行優雅降級。

以下是起點中文網 3D 書封的結構:

<!-- 書封容器 --><div class="book-cover"> <!-- 鏈接 --> <a class="link" href="//book.qidian.com/info/1004608738" target="_blank"> <img src="//qidian.qpic.cn/qdbimg/349573/1004608738/90" alt="聖墟"> </a> <!-- 陰影 --> <span></span> <!-- 灰色部分紙張厚度填充 --> ::after</div>

二、透視與 3D 空間

在我們說 CSS 思路之前,先讓我們來熟悉一下這個單詞:perspective。字典中的解釋:遠景、透視圖,透視的等含義。

也就是說,無論你如何的用 CSS3 的 transform,如果不給父級元素加透視屬性,它始終是一張方方正正的平面 2 D圖。而一旦某個容器被加上了這個 perspective 透視屬性,你就會打開一個 3D空間概念,如下圖:

3D 書封的實現是利用了 CSS3 中的旋轉(rotate),所以先讓我們來直觀地看一下 CSS3 種 3D 旋轉的動圖:

你會發現,3D 旋轉和 2D 旋轉不同之處就是,它有 3 個軸 的方向,即上圖中的 xyz 軸,並且每一軸都有對應的正負極。

而以上的 HTML 結構中的書封容器、陰影、和 after 紙張偽元素,他們都加上了 transform: perspective

這裡值得提一下 perspective 的特點:

如果一個最上層父容器加上 transform: perspective,子元素會全部按照父級元素的視角來透視,雖然旋轉值都是 45deg,但是每個旋轉的角度在父元素的透視下都不一樣,如下圖第一排,但如果是各自加上 transform: perspective,表示自己獨立成一個透視視角,如下圖:

因此,我們在實現 3D 書封時更適合用第二種,給各元素獨立加上透視屬性。

三、書封旋轉的具體實現

我們需要先來拆解一下最終的實現效果:

圖中 3 個元素:

1. 往 Y 軸負極旋轉的書封

2. 往 Y 軸正極旋轉的紙張厚度

3. 旋轉變形過的 box-shadow 陰影

要實現 3D 書封並且要兼顧良好的兼容性,我們必須區分兩類瀏覽器陣營:

1. chrome、火狐、IE10-IE11、或其他 webkit 內核瀏覽器

2. IE7-IE9

對於第一類瀏覽器,我們使用 :root{ } 方法來讓其渲染,第二類瀏覽器則不會執行透視和 CSS3 的代碼,保持原來的平面風格。(代碼+注釋解說)

/* *SASS代碼:demo 只列出關鍵屬性,其餘個性樣式以及 CSS3 前綴不做一一列出 *///兩類瀏覽器通用代碼.book-cover { //其他元素需要用 absolute 來調整位置,所以這裡必須用 relative position: relative; //3d 運營圖寬度需要 52px(具體原因看下方) width: 52px; height: 91px; //a標籤鏈接 .link { position: relative; //最上層鏈接 z-index: 3; } //運營圖 img { width: 60px; height: 87px; }}//第一類瀏覽器代碼(書封旋轉、紙張可見、陰影可見):root { .book-cover { //加透視 60px(圖片原始寬度),Y軸負值旋轉 10 transform: perspective(60px) rotateY(-10deg); /* 白色書頁填充 */ &:after { position: absolute; //第二層元素 z-index: 2; top: 2%; left: 100%; //白色書頁的厚度 width: 10%; //白色書頁的高度(註:不能超過 img 的高度,否則紙張會比封面長,與現實世界的透視視角不符) height: 92%; content: ; //Y軸正值旋轉 30 度(註:始終和你的書封反向軸旋轉,否則會出現紙張還原度不真實) transform: perspective(60px) rotateY(30deg); //你需要加上一點背景和內陰影,讓紙張顯得有點質感,而不是純純的白色 background-color: #EFEFEF; box-shadow: inset 0 0 5px #333; } /* 投影 */ span { position: absolute; //底層元素 z-index: 1; //位置信息,可根據當時實際情況微調 top: 84%; left: 7px; //盡量設置偏小,讓旋轉變形出箭頭三角狀 width: 20px; height: 10px; content: ; //反覆調試的結果,按照接近設計稿為準 box-shadow: 25px 0 5px 5px #ADADAD; //透視和旋轉角度需反覆調試,按照接近設計稿為準,也可嘗試用 transformskew 來調整 transform: perspective(74px) rotateX(-70deg) rotateY(-5deg); } img { //(原始運營圖寬度是 60,但在 3d 旋轉時需要改小,這是因為書封旋轉後太寬會遮住紙張) width: 52px; } }}

四、兼容性

介於國內瀏覽器分布的情況,一旦你做出比較創新的布局就很容易帶來一系列的兼容性問題,當然 3D 書封也不例外,而某些瀏覽器用戶數量還是比較多的,我們並無法完全拋棄。在項目迭代的過程中,我們發現了一些怪異問題,總結如下:

  • 火狐運營圖出現鋸齒
  • 使用 :root{} 後,IE9 也執行了代碼,但是 IE9 並不能做到 3D 旋轉,導致陰影外露,圖片寬度也變成了 52px
  • 我們這次改版是兼容所有 Mac 設備的,在 Safari 下出現了一個奇特的穿透問題。我們從簡到繁,先從第一條開始分析。

1、火狐瀏覽器中出現鋸齒

先來看一下火狐下的情況

一開始覺得有點費解,火狐雖然不是 Webkit 內核,但基本在渲染上也是接近 Chrome 的瀏覽器,為什麼會出現那麼難看的鋸齒?經過一番研究,發現火狐只要是進行過透視渲染的元素,都會出現鋸齒,比如這個翻開效果也會:

思考: 問題出在 img 標籤上,能否在 CSS 上加一些樣式修復掉這個問題?我們嘗試了給 img 加上了邊框,border: 1px solid #FFF ;(經實踐,必須是淡色,深色依然有鋸齒)。效果如下:

似乎鋸齒問題解決了,但是 border 會增加寬高各兩個像素,並且你無法保證始終讓 border 的顏色和運營圖的邊緣一樣,不管怎樣都會露出邊框線。這時候我們想到了另外一個更適合的屬性:outline。(IE8+支持)

outline 是輪廓屬性,不會影響寬高,但是如果你依然用淡色邊框色,在某些背景不是白色的容器上,依然會出現鋸齒,所以我們這裡如果用 transparent 邊框透明色就能完美地解決問題。

//運營圖img { width: 60px; height: 87px; //處理火狐鋸齒 outline: 1px solid transparent;}

2、IE9 不支持旋轉,導致陰影外露和寬度不正確的問題

剛剛有提到,我們使用了 :root{} 方法區分了兩類瀏覽器陣營,但是 IE9 是一個中間地帶,他支持 :root{},但 transform 對他無效,同時他又支持 box-shadow,所以在 IE9 下 3D 書封是長這樣的:

經過數據調研,我們的 IE9 用戶並不多,但是作為一個開發者這樣的效果顯然是無法接受的。可是 IE9 並沒有單獨的 CSS hack。所以我們只能針對IE9的一些特定屬性來對露出的一些元素進行優化:

  • 陰影:-ms- 是 IE 的 CSS3 前綴,同時 IE9 又支持 scale 縮放,所以我們用 -ms-transform: scale(0) 就可以將陰影設置成看不見,而 ie10 和 ie11 不受影響。
  • 書封寬度問題:width 就沒有那麼理想的方案了,hack 寫法加 「9」 都會影響其他 IE 瀏覽器,所以我們選擇的方案是用 js 重新改變 CSS 寬度為 60。經測試,如果用 IE9 查看官網的話,由於官網數據比較多,在渲染出所有圖片後,這個重新改變尺寸的 JS 行為用戶其實是無感知的(IE9 本身渲染頁面性能就比較差,在用戶還沒看到頁面之前 JS 就已經將圖片寬度改好了)

3、Safari 中奇特的層級穿透問題(無視 z-index)

先來看一下這個奇特的問題吧,書封穿透了一個 fixed 元素,而陰影又穿透了書封 >_<,這……看起來似乎很難搞定啊!

剛開始我在遇到這個「bug」的時候完全不能理解,Safari 雖然是獨立引擎,但他至少也是 apple WebKit,為什麼會出現這種怪異的現象?不管問題是如何產生的,這種還原度依然是無法接受的,上來我先按照處理 IE6 那些年的經驗,給父級元素來個 overflow:hidden 看看,如下圖:

果然問題可以解決!但是某些頁面中的情況比較複雜,不能用 overflow:hidden 怎麼辦?比如上圖,右下角投影也被裁切掉了,顯然這個方法治標不治本。

我拋棄了 overflow:hidden 方法,嘗試用 z-index 來控制層級,試圖把 fixed 元素蓋住它,但被 Safari 完全忽視,經過一番瘋狂的胡亂無效調試,我決定要從根源了解問題,了解現象是如何產生的,最後得出以下幾個結論:

  • Safari 的 3D 變形 transform 會忽略 z-index,哪怕你被穿透的元素提高到 9999 還是無效。
  • Safari 出現的這個現象並不能稱之為 bug,其實是以真實世界來渲染頁面元素的。

為了能讓讀者更直觀的理解以上2 點,我畫了兩張示意圖:

我們現在遇到的這個穿透問題是這樣的:

而其實我們所希望的是這樣的:

這時,讓我們來看一個 Demo:fangyexu.com/tool-CSS3I。 原來,我們在做 3D 旋轉變換時,一直都在關注 X 和 Y 軸,在此 Demo 中有一個 translateZ 屬性,是可以控制透視元素的遠近(模擬真實視角遠近)的屬性。而其他瀏覽器如果你用上了 z-index,他會按照 z-index 層級來安排元素的層級,但 Safari,剛有提到它是按照真實世界來渲染的,所以 z-index 在這裡完全無效,必須通過 translateZ 來控制。知道以上原理,兼容性的代碼就很容易實現了。

首先,先解決陰影穿透書封:span(陰影)穿透了 a 和 img 標籤(書封),那我們嘗試 在a 標籤上加上 transfor:translateZ(50px),書封右下角問題解決,如下圖:

剩下的定位 fixed 元素想要蓋住書封就更容易了,給 fixed 元素加上屬性 transfor:translateZ(10px),還原度和 chrome 瀏覽器終於保持一致了。

五、寫在最後

在前幾年,想必每個攻城獅幾乎都被 IE6 的各種怪異 BUG 給虐過,隨著技術發展 IE6 終於退出了歷史舞台,各大領先行業的網站幾乎都開始不支持 IE7 和 IE8。原以為可以擺脫那些煩人的兼容性問題,但是按照目前的形勢看來,瀏覽器的標準還是沒有得到很好的統一,包括 CSS3 布局中的一些比較流行的 flex 和其他自適應布局在移動端上的兼容性依然不是很好,良好的兼容性是我們開發者永恆的話題,我們必須不斷的學習和積累、經常地進行問題總結,才能更好的應對技術高速發展的現狀。

如果你也遇到一些奇葩兼容性問題,歡迎進行留言貢獻討論,讓我們共同進步,謝謝。

原文地址:

起點中文網 3D 書封之最佳實踐?

mp.weixin.qq.com


推薦閱讀:

用css做一個陰陽太極
2018-7-25 css10-背景和精靈圖
CSS選擇器、層疊、繼承的那些事
如何編寫易於拓展與維護的 CSS 代碼
大前端應用開發與架構設計-使用CSS美化Web站點(一)

TAG:CSS | 前端開發 | CSS3 |