圖片方面的自適應處理------Flexible Images

假設我們有一個兩欄自適應的布局,在主內容中應用了一個圖片,其結構如下:

<div class="figure"> 
  <div class="inner"> 
   ![](http://upload-images.jianshu.io/upload_images/2244949-f80854741861cd7f.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 
    <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"。雖然整個布局是自適應布局,但圖片依舊撐破容器:


這并不是我們想要我效果,我們真正想要達到的效果應該是這樣的,換句話說理想中要的將是下圖的效果:
Flexible Images

那接下來,我們觀注的就是,如何讓我們的效果達到上圖所示的效果。

方案一: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>容器中沒有任何內容,以至于無法撐開容器的高度,因此想正常的顯示出圖片,那必須給容器指一個準確的高度或一個最小高度,言外之意,我們寬度可以自適應,但比例不會根據圖片的寬高比例來定,另外圖片會進行截取,如示例所示:


Flexible Images

<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>


Flexible Images

<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>


Flexible Images

<h3>

自適應縱橫比例</h3>

<p>在固定縱橫比例的基礎之上,做進一步的調整。假設我們在寬屏的PC上顯示大的圖片,而在移動設備上,我們不想使用相同的縱橫比或圖像變得太小。當然我們也不想使用完全相同的高度或讓圖像變得太高。我們更希望當寬度變小時,其高度也變得更小。而我們也把這種稱為流體縱橫比例。</p>


Flexible Images

<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>

Flexible Images

<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>

Flexible Images

<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>

Flexible Images

<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>

Flexible Images

<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>

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,825評論 6 546
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,814評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,980評論 0 384
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 64,064評論 1 319
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,779評論 6 414
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,109評論 1 330
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,099評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,287評論 0 291
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,799評論 1 338
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,515評論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,750評論 1 375
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,221評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,933評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,327評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,667評論 1 296
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,492評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,703評論 2 380

推薦閱讀更多精彩內容

  • 選擇qi:是表達式 標簽選擇器 類選擇器 屬性選擇器 繼承屬性: color,font,text-align,li...
    love2013閱讀 2,327評論 0 11
  • 選擇qi:是表達式 標簽選擇器 類選擇器 屬性選擇器 繼承屬性: color,font,text-align,li...
    wzhiq896閱讀 1,787評論 0 2
  • 1、垂直對齊 如果你用CSS,則你會有困惑:我該怎么垂直對齊容器中的元素?現在,利用CSS3的Transform,...
    kiddings閱讀 3,195評論 0 11
  • 1、屬性選擇器:id選擇器 # 通過id 來選擇類名選擇器 . 通過類名來選擇屬性選擇器 ...
    Yuann閱讀 1,655評論 0 7
  • 近來因為工作上的摩擦,總和同事爭得面紅耳赤,雖然事情終得解決,但是過程卻不免有些難堪。在消極情緒的帶動下,士氣低落...
    尋覔閱讀 660評論 3 6