標籤:

CSS等比例縮放的盒子

原文:《你不知道的 CSS》之等比例縮放的盒子

你肯定已經知道,對於一個 img 元素而言,你可以單獨地修改它的 width 或者 height 屬性來設置它的大小,同時圖片的比例還能夠保持不變。

如下圖所示,最上面是原始大小的圖片,下面兩張則分別是設置了 width: 50%height: 50% 屬性後的樣子。

可以看到把寬度設置為了原來的一半的同時,圖片的高度並不是保持原來的大小,而是相應的也變成了原來的一半,使得圖片仍能夠保持原有的比例。同理把高度設成原來的一半也如此。

作為對照,我們看看單獨修改其他元素的寬和高會產生什麼樣的效果:

上圖最左邊的藍色矩形是原始的 div 元素,之後兩個分別是對其設置了 width: 50%height: 50% 屬性後的樣子。可見與 img 元素不同,單獨設置 div 元素的寬度(高度)時,對應的高度(寬度)並不會改變,從而導致元素的比例發生變化。這一結果相信每個稍微對前端有些了解的同學都能猜到。但是究竟是什麼導致了同樣的屬性用於 img 和 div 後會產生不同的結果呢?

img 在元素分類中屬於 replaced (被替換的)元素。replaced 元素表示這個元素內容的顯示不是由 CSS 控制的。換句話說,對於 img 元素而言,圖片的內容並不是由 CSS 定義的,而是通過其 src 屬性指向的資源決定的。很多 replaced 元素來都會有自己的固有尺寸(Intrinsic dimension),img 也不例外1。當 img 的高度改變後,瀏覽器會計算出其縮放比例,而當元素的寬度是 auto(即默認值)時,瀏覽器則以原始寬度 * 縮放比例來作為元素的新寬度。從而使得 img 元素的比例始終保持一致。

然而這都並不是這篇文章討論的重點。(那位同學請不要說髒話,不文明

重點是什麼?重點就是題目:實現等比例縮放的盒子。

在響應式設計逐漸成為主流的今天,流式布局這個詞即使放在一兩年前也絕算不得是個新鮮辭彙。下面是一個布局實例:

上圖中每個藍色的矩形分別對應一個 div 元素,每個元素的寬度占窗口寬度的四分之一(圖示中為了演示方便給每個元素加了邊距效果)。如果不做額外處理,當窗口寬度變小時上圖的頁面會變為如下所示:

可見每個元素的寬度進行了縮放,但高度並沒有變化,看起來並不是很協調。所以有些場景下我們需要實現當窗口寬度縮放時,使得元素寬度自適應的同時,保證每個元素的寬高比例不變

很多同學在我話還沒講完時,就已經紛紛掏出 JavaScript 大鎚著手實現了起來。然而這個系列文章的標題是《你不知道的 CSS》,自然不會介紹 CSS 實現不了這種打自己臉的需求,而且就此例而言,使用 JavaScript 實現效果並不好,綁定 onresize 事件後在拖拽時某些星座的朋友會察覺出來些許卡頓(你試試便知),而且在 JavaScript 載入完成前是看不出效果的。

其實用 CSS 可以很容易地實現這樣的效果,用的屬性也是我們每個工作日和周末(如果加班的話)都會用到的:padding-bottompadding-bottom 有一個讓人很容易忽略的特性是當它的值是百分比形式時,百分比的基數是其所在元素的父元素的寬度而不是高度(同 padding-leftpadding-right 一樣)。這樣解決方案也就非常明顯了:

  1. 將元素的 height 設成 0,使得元素的高度等於 padding-bottom
  2. 合理設置 padding-bottom 的值。比如每個元素的 width25%,現在想讓元素的高度始終保持為其寬度的兩倍,則 padding-bottom 的值應該設置為 50%

結果如下圖所示:

相應的代碼可以參見:jsfiddle.net/luin/25BbH

然而至此,這篇文章還沒完。肯定會有很多同學疑惑既然 height 被設成了 0,那麼如果元素的 overflowhidden,裡面的文字會不會因為超出了元素高度而被隱藏呢?

答案是不會。根據 CSS 2.1 規範2,overflow 只會對處於 padding edge 外面的內容生效,即只有超出了 padding 區域的內容才會被 overflow 屬性隱藏掉。

  1. 其實有一點例外的情況是當 img 的圖片是 svg 時,它是沒有固有尺寸的。 ?
  2. w3.org/TR/CSS2/visufx.h ?

推薦閱讀:

現在說全景會不會有點遲=。=
一些編寫css的建議
CSS 中 font-size 定義的字體框(em box)大小,具體是怎麼實現的?
CSS實現兼容性的漸變背景(gradient)效果
類似angularJS里的路由,有沒有類似的前端路由框架,我想實現左側導航不刷新,只刷新右側內容的界面?

TAG:CSS |