假設我們有一個兩欄自適應的布局,在主內容中應用了一個圖片,其結構如下:
<div class="figure">
<div class="inner">

<p class="figcaption">Lo, the robot walks</p>
</div>
</div>
這是一個很常見的結構,其效果就是一張圖片,圖片下面有一個簡單的文本描述。在整個效果中,針對figure
內元素寫了一點樣式
//SCSS
.figure {
float: right;
margin: 0.5em 0;
margin-left: 1.9672131%; //12px/610px
width: 45.9016393%; // 280px/610px
.inner {
border: 10px solid hsla(333,50%,60%,.8);
border-radius: 10px;
}
img {
vertical-align: top;
}
p {
background-color: hsla(333,50%,60%,.8);
padding: 10px 10px 0; color: #fff; }
}
從上面的代碼中我們可以想像出我們要的效果,figure占整個容器.content寬度的"45.9016393%"
也就是"280px/610px"。雖然整個布局是自適應布局,但圖片依舊撐破容器:
這并不是我們想要我效果,我們真正想要達到的效果應該是這樣的,換句話說理想中要的將是下圖的效果:
那接下來,我們觀注的就是,如何讓我們的效果達到上圖所示的效果。
方案一:max-width
在介紹響應式設計的文章中,為了解決圖片的自適應問題,都會提到使用max-width
。Richard Rutter設計首先提出使用max-width的方案:
img { max-width: 100%; }
在上面的示例基礎上,我們為img添加max-width值為“100%”:
更重要的是,在現代瀏覽器中發展到可以自動調整圖像的比例,可以根據容器的大小縮放或者放大圖像,并且圖像的寬高比保持不變。
max-width:100%
除了可以應用于自適應元素容器上之外也可以應用于固定元素容器上。而且可以應用于視頻和其他富媒體上也具有同等的效果。img, embed, object, video { max-width: 100%; }
不幸的是,max-width屬性在IE7以及其以下版本并無法支持。
另外一點,在一些瀏覽器中僅指定圖片的寬度,可能會導致瀏覽器重新處理布局,調整頁面的時間周期會增加兩到三倍,雖然周期不到一毫秒,但是累積起來,尤其是頁面上有很多個這樣的元素的時候,還是或多或少會影響頁面的性能。為了解決這個問題,可以顯式的指定圖片的height值為auto
img { max-width: 100%; height: auto; }
方案二:background-image
在響應式設計中實現圖片自適應另一種方案可以采用background-image。因為在CSS3有一個background-size
屬性可以讓我們的背景圖片適應容器大小。
先簡單的來模擬一個效果,基于上例的基礎上,我們將模板結構做一下調整:
<div class="figure"> <div class="inner"> <div class="image-wrapper"></div> <p class="figcaption">Lo, the robot walks</p> </div> </div>
將圖片變成背景圖片應用于image-wrapper容器之上。
//SCSS
.figure {
float: right;
margin: 0.5em 0;
margin-left: 1.9672131%; //12px/610px
width: 45.9016393%; // 280px/610
.inner {
border: 10px solid hsla(333,50%,60%,.8);
border-radius: 10px;
}
.image-wrapper {
width: 100%;
background: url("http://w3cplus-cdn2.u.qiniudn.com/sites/default/files/blogs/2014/1401/flexible-image.jpg") no-repeat center;
min-height: 100px;
background-size: cover;
}
p {
background-color: hsla(333,50%,60%,.8);
padding: 10px 10px 0;
color: #fff;
}
}
可以清楚的看到,在<code>.image-wrapper</code>應用了背景圖片,并且配合了<code>background-size:cover</code>一起使用:
<code>
.image-wrapper {
width: 100%;
background: url("http://w3cplus-cdn2.u.qiniudn.com/sites/default/files/blogs/2014/1401/flexible-image.jpg") no-repeat center;
min-height: 100px;
background-size: cover;
}
</code>
不過這里讓你為難的是,在<code>.image-wrapper</code>容器中沒有任何內容,以至于無法撐開容器的高度,因此想正常的顯示出圖片,那必須給容器指一個準確的高度或一個最小高度,言外之意,我們寬度可以自適應,但比例不會根據圖片的寬高比例來定,另外圖片會進行截取,如示例所示:
<p>很顯然,這樣的效果不理想,不是我們所需要的效果。那有什么方法可以讓背景圖片根據自身的比例來自適應呢?</p>
<p>在響應式設計中,布局可以根據設備調整寬度。就算是用百分比調整寬度,也會自動按比例調整元素的高度。換句話說,其寬度比例保持不變來調整大小。如果我們要使背景圖片達到同等的效果,我們就必須得知道如何保持任何HTML元素的縱橫比例。</p>
<p>針對這個問題,Rolf Timmermans 寫了一篇文章<a >Responsive background images with fixed or fluid aspect ratios</a>,文章中介紹了如何解決背景圖像的固定和流體的縱橫比例。接下來我們一起來看看Rolf Timmermans是如何實現的。</p>
<h3>
固定縱橫比例</h3>
<p>在保持背景圖片的縱橫比例,關鍵之處是是讓背景圖片垂直居中。而其中主要是基于寬度的百分比來設置內距<code>padding</code>的百分比值。這種技術早前在<a >創建視頻縱橫比例</a>一文中有介紹,而這種技術也適用于其他的任何元素。</p>
<p>假設我們有一張700像素寬和467像素高的圖像。當寬度改變時,我們需要維護其縱橫向比例是“16:9”。下面有一個示例,我們使用像素為單位,當然也可以使用<code>em</code>為單位,但我們的結構和前面示例一樣:</p>
<pre>
<code><div class="figure">
<div class="inner">
<div class="image-wrapper"></div>
<p class="figcaption">Lo, the robot walks</p>
</div>
</div>
</code></pre>
<p>一般情況之下,我們知道圖片的尺寸大小,根據縱橫比例,我們可以通過下面的公式計算出內距<code>padding-top</code>或<code>padding-bottom</code>的百分比值:</p>
<pre>
<code>padding-top或padding-bottom = (背景圖片高度 / 背景圖片寬度) * 100%
</code></pre>
<p>根據這個公式,可以輕松計算出:</p>
<pre>
<code>padding-top(或padding-bottom) = 467 / 700 = 0.667142857 = 66.7142857%
</code></pre>
<p>如此一來,我們可以將前面的示例調整為:</p>
<code>//SCSS
.figure {
margin: .5em;
//背景圖像寬度必須寬度為700px
max-width: 700px; //圖片的寬度
.inner {
border: 10px solid hsla(333,50%,60%,.8);
border-radius: 10px;
}
.image-wrapper {
background: url("http://w3cplus-cdn2.u.qiniudn.com/sites/default/files/blogs/2014/1401/flexible-image.jpg") no-repeat center;
background-size: cover;
padding-top:66.7142857%; // 467px / 700px = 0.667142857
}
p {
background-color: hsla(333,50%,60%,.8);
padding: 10px 10px 0;
color: #fff;
}
}
</code></pre>
<p>效果如下:</p>
<h3>
自適應縱橫比例</h3>
<p>在固定縱橫比例的基礎之上,做進一步的調整。假設我們在寬屏的PC上顯示大的圖片,而在移動設備上,我們不想使用相同的縱橫比或圖像變得太小。當然我們也不想使用完全相同的高度或讓圖像變得太高。我們更希望當寬度變小時,其高度也變得更小。而我們也把這種稱為流體縱橫比例。</p>
<p>這種效果我們可以給元素設置一個高度,來減少<code>padding-top</code>或者<code>padding-bottom</code>的百分比值。假設我們的大圖尺寸是700像素寬度和267像素高,而我們決定顯示的圖片尺寸是在300像素寬度和167像素的高度。現在我們需要計算高度<code>height</code>和內距<code>padding-top</code>或<code>padding-bottom</code>的值:</p>
<p>上圖顯示了兩個維度之間的關系。斜線的坡度對應于內距<code>padding-top</code>或<code>padding-bottom</code>的屬性值。開始高度的值代表元素的高度<code>height</code>的屬性值。</p>
我們可以根據上圖所示的公式計算出背景圖像縱橫比例。基于固定縱橫比例的示例之上,將上面的示例修改成流體縱橫比例:
<code>.figure {
margin: .5em;
//背景圖像的寬度為700px
max-width: 700px;
.inner {
border: 10px solid hsla(333,50%,60%,.8);
border-radius: 10px;
}
.image-wrapper {
background: url("http://w3cplus-cdn2.u.qiniudn.com/sites/default/files/blogs/2014/1401/flexible-image.jpg") no-repeat center;
background-size: cover;
height: 92px;
padding-top:25%;
}
p {
background-color: hsla(333,50%,60%,.8);
padding: 10px 10px 0;
color: #fff;
}
}
</code>
<p>效果如下所示:</p>
<p><strong>注:由于示例圖片尺寸比例不夠標準,此處想要表達的意思是:假設原圖的比例是4:1(比如背景圖片尺寸是800px寬,200px高);自適應后比例為2:1,(背景圖片尺寸變為300px的寬和150px的高)。換句話說就是從4:1比例的800<em>200的圖片變成比例為2:1的300</em>150的圖片。</strong></p>
<p><strong>特別聲明:</strong>以上方法以及思咱來自于Rolf Timmermans的<a >Responsive background images with fixed or fluid aspect ratios</a>一文。</p>
<p>上面兩種方案主要是根據背景圖片的縱橫比例來實現圖像的自適應效果。但在<a >Necolas</a>在<a >Flexible CSS cover images</a>一文中提供另一種以縱橫比實現圖像自適應的效果。</p>
<p>他的特征同樣是依靠覆蓋背景圖像的縱橫比例來實現,假設我們的比例為:</p>
<p>覆蓋背景圖像的縱橫比例必須得滿足以下幾個條件:</p>
<ul><li>呈現一個固定的縱橫比例,除非特定的最大尺寸超過圖像寬度</li>
<li>支持不同的縱橫比例</li>
<li>支持最大高度<code>max-height</code>和最大寬度<code>max-width</code></li>
<li>支持不同的背景圖像</li>
<li>背景圖像填充整個容器</li>
<li>背景圖像居中顯示</li>
</ul><p>先來看一個簡單的模板:</p>
<pre>
<code><div class="CoverImage FlexEmbed FlexEmbed--3by1"></div>
</code></pre>
<p>對應的樣式代碼:</p>
<code>//SCSS
.CoverImage {
border: 5px solid green;
margin: .5em auto;
background: url("http://w3cplus-cdn2.u.qiniudn.com/sites/default/files/blogs/2014/1401/flexible-image.jpg") no-repeat center;
background-size: cover;
max-height: 700px;
max-width: 467px;
}
.FlexEmbed {
display: block;
overflow: hidden;
position: relative;
&:before {
content: "";
display: block;
width: 100%;
}
}
.FlexEmbed--3by1:before {
padding-bottom: 33.33333%;
}
.FlexEmbed--2by1:before {
padding-bottom: 50%;
}
.FlexEmbed--16by9:before {
padding-bottom: 56.25%;
}
.FlexEmbed--4by3:before {
padding-bottom: 75%;
}
</code>
<p>其效果如下:</p>
<p>使用背景圖像的方案存在一個問題,不管是固定縱橫比例還是流體縱橫比例,我們都離不開<code>background-size</code>屬性,而此值是CSS3的一個屬性,僅有現代瀏覽器支持。如果要兼容低版本的IE還需要另尋他法。比如說<a >backgroundSize.js</a>、<a >BACKSTRETCH</a>、<a >jQuery Easy Background Resize</a>等插件。<a >Michael Bester</a>在<a >The Flexible Scalable Background Image, Redux</a>一文中也做過這方面的介紹。</p>
<h2>
方案三:Object-fit</h2>
<p><a >Object-fit</a>是CSS3的一個新屬性,到目前為止僅在Chrome32+版本上可以正常運行。這個屬性可以說就是為自適圖片尺寸而生,特別適合于響應式設計中圖片以及其他富媒體的自適尺寸的處理。</p>
<p>使用<code>Object-fit</code>屬性有一個受限條件,需要在樣式中顯示的設置圖片的尺寸。然后通過其屬性值<code>fill</code>、<code>cover</code>或<code>contain</code>值來控制圖像顯錄的縱橫比例。在此并不建議使用,不過當作興趣愛好,可以深入了解他。如果你對此屬性感興趣,可以閱讀《<a >CSS3 Object-fit和Object-position</a>》一文,文中詳細介紹了<code>object-fit</code>屬性的具體使用。</p>
<h2>
其他方案</h2>
<p>除了上述的幾種方案之外,其實還有其他的一些解決方案,比如<a >@張鑫旭</a>在其博客《<a >熱門:響應圖片(Responsive Images)技術簡介</a>》一文中就介紹了如何使用“Cookie+Server”、“使用<code>noscript</code>標簽創建”等其他方法。<a >Andy Shora</a>在《<a >Sizing Fluid Image Containers with a Little CSS Padding Hack</a>》還介紹了一種老方案——<strong>內距和絕對定位實現圖片自適應</strong>。當然除了這些還有其他的。<a >Sherri Alexander</a>特意為解決響應式設計的圖片問題,在《<a >Choosing A Responsive Image Solution</a>》一文中搜集了很多個JavaScript解決方案。感興趣的同學,可以仔細研究研究。</p>
<h2>
擴展閱讀</h2>
<ul><li><a >Flexible CSS cover images</a></li>
<li><a >Fluid Images</a></li>
<li><a >CSS Fluid Image Techniques for Responsive Site Design</a></li>
<li><a >FLUID IMAGES</a></li>
<li><a >Responsive background images with fixed or fluid aspect ratios</a></li>
<li><a >How To Create Flexible Images And Media In CSS Layouts</a></li>
<li><a >Different ways of making images flexible in responsive web design</a></li>
<li><a >Adaptive Images for Responsive Designs</a></li>
<li><a >Responsive Images: How they Almost Worked and What We Need</a></li>
<li><a >熱門:響應圖片(Responsive Images)技術簡介</a></li>
<li><a >Overflow Image with vertical centering for Responsive Web Design</a></li>
<li><a >Sizing Fluid Image Containers with a Little CSS Padding Hack</a></li>
<li><a >The Flexible Scalable Background Image, Redux</a></li>
<li><a >Choosing A Responsive Image Solution</a></li>
</ul><h2>
總結</h2>
<p>上面介紹了使用不同方案來解決圖片自適應在Web頁面設計中的問題。不管哪種方案,都有自己的優勢與不足。拋開JavaScript的解決方案,不管是<code>max-width</code>、<code>background-image</code>還是<code>object-fit</code>都避免不了瀏覽器的兼容性問題,特別是<code>object-fit</code>尤為突出。在實際應用中,個人更趨向于方案二,因為其可以按照圖片縱橫向比例顯示,不過這種方案比較麻煩的是,需要使用背景圖片。</p>
<p>當然,大家可以根據自己的項目需求去考慮使用什么方案解決問題,在這里只是自己一點總結。如果您對自適應圖片的處理有更好的解決經驗,歡迎一起分享。</p>
<p>如需轉載,煩請注明出處:<a >http://www.w3cplus.com/css/flexible-images.html</a></p>