響應式圖片實戰

響應式圖片實戰

說到響應式網站,咱們都知道彈性佈局、彈性圖片、媒體查詢,更多指的是佈局的方式,好比說使用max-width: 100%,這樣讓圖片的寬度隨着容器的大小而改變,響應式設計讓網站能兼容各類屏幕設備,可是在咱們流量這麼昂貴的時代,讓一個小屏幕的手機去加載一張爲大屏幕PC設計的幾百K的圖片,雖然這張圖片會看起來很是的清晰,可是瘋漲的流量消耗確定會讓用戶很是的苦惱,並且咱們也須要加載更長的時間才能把頁面加載出來。html

咱們開發的目的不是挑戰用戶的耐心和金錢,而是讓用戶在使用的過程當中有更好的感覺,在這種狀況下加載與 用戶設備相匹配的小圖片,即快速,又不會影響用戶的體驗,幫用戶節省了成本,一樣的,你在PC端加載一張小圖片也不會影響用戶的體驗,幫用戶節省了成本,一樣的你在PC端加載一張小圖片,雖然速度很快可是放大後模糊的效果會讓用戶以爲網站很Low很不專業,並且PC大部分使用的wifi,咱們不須要去接受太多的流量,那麼如何解決剛纔說的這些問題呢?響應式圖片的概念也就隨之產生了,響應式圖片,不只僅是指圖片的排版和佈局,更多的還指能夠根據設備大小而加載不一樣的圖片,雖然這個過程增長了一點點UI設計師的工做量,不過那會大大改善用戶的體驗,那麼想要響應式圖片如何來實現呢?jquery

1、JS或者服務端硬編碼

這種方式的原理其實就是跟蹤windowresize事件,而後修改一下圖片的路徑,咱們準備三張圖片,1-480.png、1-800.png、1-1600.png,分別對應三種大小設備屏幕,而後:git

$(function(){
function makeImageResponsive() {
var width = $(window).width();
var img = $('.container img');
var imgUrlPrefix = 'http://sandbox.runjs.cn/uploads/rs/496/pkutja85/';
if (width <= 480) {
img.attr('src',imgUrlPrefix + '1-480.png');
} else if (width <= 800) {
img.attr('src',imgUrlPrefix + '1-800.png');
} else {
img.attr('src',imgUrlPrefix + '1-1600.png');
}
}

$(window).on('resize load', makeImageResponsive);
});

在線查看源碼github

這種形式還有一種變種的方式, 就是把屏幕信息寫入Cookie中,取圖片的時候在服務器端決定返回哪一張圖片,這樣的話就不須要咱們來寫腳本了,咱們經過Cookie和在服務器端進行控制就能夠達到目的,兼容性也比較好。web

2、srcset 方法

經過js或者服務器端返回確實能夠達到響應式圖片這樣一個目的,兼容性也很是的好,可是須要咱們編碼實現響應式的邏輯,在修改的時候也不是很方便,這屬於命令式的實現,那麼有沒有聲明式的實現呢?瀏覽器

也就是說咱們把這幾個圖片地址聲明在HTML中,由瀏覽器來決定如何加載,這樣的話更加的靈活,把展現的邏輯從js腳本或者從服務器端硬編碼分離出來,這樣也下降的耦合,由於展示和咱們的業務邏輯是分開的。緩存

那麼具體有沒有呢?答案是有的。服務器

通過了多年的努力和爭辯,咱們如今有了一些符合標準的標記,這些標記其實都通過了不少的修改、討論,最後決定了這樣幾種,這些標記是來解決響應式圖片的問題的。這些標記以下:網絡

  • srcset
  • srcset 配合 sizes
  • picture
  • svg

這些新元素和新屬性讓咱們能夠編寫多個可替換的圖片,讓每一個客戶端使用最適合的那一個,這些已經進入了官方的規範,下面咱們分別來使用這些標記。app

咱們新建一個以下的頁面:

html, * {
margin: 0;
padding: 0;
}
.content {
width: 100%;
marign: 0 auto;
}
.content img {
display: block;
width: 100%;
max-width: 100%;
}

<div class="content">
<img class="image" src="http://sandbox.runjs.cn/uploads/rs/496/pkutja85/1-480.png" alt="這裏是圖片" />
</div>

這個頁面很簡單,就是載入了一副 480x480 的圖像

srcsetimg 標籤中的一個屬性,這個屬性裏面是能夠以逗號隔開的一個或者多個字符串列表,這些字符串用來表明一系列可能使用的圖片,每一個字符串的格式以下:

<img class="iamge" src="img/1-480.png"
srcset="img/1-480.png 480w, img/1-800.png 800w, img/1-1600.png 1600w" />

480w、800w、1600w就是尺寸描述符,通常是w結尾,也就是width的意思,以上聲明瞭三張不一樣規格的圖片,對於支持srcset的瀏覽器會怎麼作呢?

在線預覽查看源碼

從效果上看瀏覽器會自動感知,這個感知包含一系列因素如屏幕大小、網速、dpr等,而後去選中一張合適的圖片進行加載。咱們先把界面變小,以下面所示:

咱們能夠看到,當咱們加載到最大的圖片後,而後再把屏幕縮小後,加載的圖片卻並無改變,這是什麼樣的一個邏輯 呢?

這個邏輯就是:瀏覽器會根據屏幕的寬度和咱們聲明的圖片的尺寸描述符去決定應該使用哪張圖片,可是呢,由於咱們瀏覽器已經在大的分辨率下加載了大的圖片,那麼瀏覽器會默認你的圖片已經放在緩存中了,使用大的圖片不會再有網絡的消耗,那麼固然是使用更大的圖片更好的了,因此在咱們再縮小屏幕的時候瀏覽器不會再去使用小圖片了,這是瀏覽器的一個默認的行爲。

3、sizes 解決 srcset坑

上面使用srcset讓咱們的開發變的很是的簡單,只須要聲明一下將幾個圖片和它的寬度,就可讓瀏覽器自動的去選擇,那麼若是咱們只設置srcset的話,會有一個小小的坑,咱們試的把這個content它的寬度設置成 50%。看一下頁面的效果,我仍是把dpr設置爲 1,這樣的話他會精確到像素,讓咱們看得更加的清晰。

設置成 50% 以後這個圖片只是佔了 50% 的寬度來顯示,可是當咱們去加寬這個寬度的時候,能夠看到,當咱們到 480 的時候,圖片就會改變,但其實這個圖片真實的寬度只有 480/2,也就是隻有 240,只在 240 的時候這個寬度就改變了,這時候咱們就會會發現這個圖片,它的這個自動的加載變得不是那麼智能了,那麼咱們圖片的容器變小,可是圖片仍是按照百分之百的寬度邏輯進行縮放,這是什麼樣什麼樣一個緣由呢?這是由於呢其實,srcset 這一個屬性還須要配合一個屬性來使用,就是剛纔說到的sizes

sizes屬性有兩個值:第一個是媒體條件;第二個是源圖尺寸值,在特定媒體條件下,此值決定了圖片的寬度。

<img srcset="360.jpg 360w,
768.jpg 768w,
1200.jpg 1200w,
1920.jpg 1920w"
sizes="
(max-width: 360px) 100vw,
(max-width: 768px) 90vw,
(max-width: 1980px) 80vw,
768px"
src="360.jpg" alt="">

咱們來逐條讀這一個img標籤的信息

  • srcset,咱們給瀏覽器準備了四個質量的圖像,分別爲360 768 1200 1920
  • sizes,咱們來告訴瀏覽器,在不一樣的環境下圖像的寬度
  • 當視口不大於360時,圖像顯示寬度爲100vw,當視口不大於768的時候,圖像顯示寬度爲90vw,以此類推。
  • 最後一個src做爲默認圖像url引入,而且是自然的回退方案,當瀏覽器不認以上屬性的時候,直接讀取src渲染。

這樣說不夠直觀,咱們看個demo

在iphone4(320)下,圖像寬度和咱們設置的100vw一致,可是爲何瀏覽器選擇了768的圖像而沒有選擇360的?由於4的dpr是2呀^_^,瀏覽器很智能的選擇了質量最合適的768.

再看一下6p(414),很聽話的按照咱們的設置,顯示了90vw。由於他的dpr更高,瀏覽器聰明的選擇了1200質量的圖像。

這裏咱們能夠欺騙一下瀏覽器:

360.jpg 1200w,
1200.jpg 9999w

咱們把360的圖像,騙瀏覽器說這是1200的,而後把本來1200的扔天上去

瀏覽器果真上當了,他把360的圖當成1200的來用了。這裏可能有些疑問,圖像的寬度爲何不是90vw了哪?由於瀏覽器被騙了可是本身殊不知道,他依然按照1200的圖像,去適配dpr。41490%(360/1200)約等於111.7。這種方式很智能,瀏覽器去根據你的sizes,從w列表裏選擇最適合的圖像來調用顯示。正由於他太智能了,在實際操做中可控性較差,有些咱們想精確控制的圖像顯示,有時候並不能如意。並且在作lazyload的時候要處理的東西也比較複雜。

4、picture標籤,可精確把控

通常來講對於僅僅是須要縮放的圖片,咱們在srcset屬性裏面列出圖片的地址、像寬度,用sizes屬性來告訴瀏覽器這個圖片在什麼樣的狀況下它的寬度顯示成怎麼樣,寫出這些就足夠了,可是有的時候咱們會但願除了縮放以外還經過其餘的方式進行圖片的自適應,這個時候咱們就要奪回一些咱們選擇圖片的一個控制權,所謂的奪回控制權就是說瀏覽器的選擇邏輯咱們要把它拿過來一些,咱們本身來控制,那麼picture屬性就該出場了,好比咱們有一個天安門的全景圖,寬寬的一個圖片:

他在大屏幕下顯示很是的效果很是的好,可是在小屏幕下這個全景圖顯示就顯得過小了,若是咱們能夠在手機上能放大,能展示出來一個更突出的一個裁切後的全景圖那樣就更好了,那麼若是咱們在一個srcset中的引入一個裁切後的版本,那麼咱們就沒法分辨他們什麼時候應該去選用什麼時候不該該去選用,而使用了picture咱們就能明確的表達出咱們的意圖,好比說咱們只在視口寬度超過 800 像素的時候加載寬的版本,比這個小的視口中咱們老是加載裁切後的版本。代碼以下:

<div class="content">
<picture>
<source media="(max-width:36em)"
srcset="http://www.fansimg.com/uploads2011/05/userid280713time20110508081514.jpg 768w"/>
<source srcset="http://www.fansimg.com/uploads2011/05/userid280713time20110508081514.jpg 1800w"/>
<img src="http://www.fansimg.com/uploads2011/05/userid280713time20110508081514.jpg" alt="這裏是圖片"/>
</picture>
</div>

效果以下

在線演示源碼

source 中除了能夠有媒體查詢以外,還能夠正對媒體查詢設置多組不一樣格式的文件,好比 source 中還有type屬性,能夠是image/svg+xml等格式文件:

<source type="image/svg+xml" srcset="logo.svg 480w, logo.svg 800w, logo.svg 1600w "/>
<source type="image/webp" srcset="logo.webp 480w, logo-m.webp 800w, logo-l.webp 1600w "/>

並且這個寫法的懶加載很是好處理,只須要在傳統的lazyload策略上稍加改進

  • data-src
  • data-srcset

在加載到的時候更換爲

  • src
  • srcset

就輕鬆解決了。

5、使用svg

svg是可縮放的矢量圖形,它是基於可擴展標記語言來生成的,svg圖像能夠用任何的文本編輯器來建立,可是通常人不多會去用文本編輯器來建立svg圖片,由於這個很是的麻煩,除非你就只須要幾條橫線幾個圓圈什麼的。

什麼是矢量圖形?矢量圖形就是這些圖形在變化的時候它都不會失真和變形,這些圖形它不是基於像素的,而是基於一個繪製的規則,一旦咱們肯定了繪製的規則,好比說顏色、形狀、輪廓、大小、屏幕位置等等,肯定了這些規則,即便咱們發生了縮放也不會影響這些圖形的繪製,因此這些圖像固然也不會發生失真,可是這些矢量圖形的和位圖比起來其實有缺點的,最大的缺點的就是它很難去表現色彩層次豐富和逼真的圖像效果。好比讓咱們的一個照片變成一個矢量圖形,那麼這個這個矢量圖形確定要大了去了,要變的很是的很是的大,由於每一個像素他可能就要有一個繪製的規則,因此根據咱們的須要能夠去選擇你使用矢量圖形仍是要位圖,通常來講針對一些logo,簡單的圖標,好比說回收站、消息等等這樣一些圖標,咱們可使用svg這種矢量圖形。

說到矢量圖形,確定就要想怎麼樣去畫它了,剛纔說用文本編輯器確定不行的,這樣太麻煩了,那麼其實大部分支持矢量圖繪製的工具其實都支持繪製svg。

相比srcsetpicturepicture對於IE瀏覽器是徹底不兼容的,對於老的Safari瀏覽器和老的安卓瀏覽器也是不兼容的,對於srcset,比picture稍微好一點,對於老的IE和安卓瀏覽器也是不兼容的。而SVG兼容性就好的多了,除了IE8不支持外,其餘的瀏覽器幾乎都支持SVG。

6、使用第三方庫

因爲咱們的廣告的一看就是一個位圖的圖形,它的裏邊色彩比較豐富,因此咱們使用svg不太合適,使用位圖要實現響應式就要配合srcset或者picture,因爲兼容性的問題通常在使用srcset或者picture的時候通常會使用一個polyfill。

什麼是polyfill?它來自於一個家裝產品,這個家裝產品是一個刮牆的產品,中國人通常把這個產品的叫作膩子,就是刮牆的膩子,它能夠把牆的一些裂縫給填平,好比說咱們牆皮時間長了會出現一些裂縫,這個膩子能夠把它給填平,讓磚塊變得更平滑,在js的世界裏polyfill他的意思就是一個在瀏覽器上的一個膩子,就是填平瀏覽器上面的兼容性的一些東西,好比咱們使用picture,若是瀏覽器支持那就沒有問題,咱們正常的使用就能夠了,若是瀏覽器不支持那麼就須要使用一個替代的方案來解決,polyfill就是填平了這些瀏覽器的兼容性的一些坑。

常用解決兼容性的一個polyfill,polyfill實際上是一種想法,一種腳本,針對某些瀏覽器的兼容性就會有某些的polyfill出現,對於響應式圖片最有名的polyfill就是picturefill庫。

咱們只須要引入這個庫就好了(picturefill.min.js)

<div class="ad">
<div class="owl-carousel owl-theme">
<div class="item">
<picture>
<source srcset="img/ad001-l.png" media="(min-width:50em)">
<source srcset="img/ad001-m.png" media="(min-width:30em)">
<img src="img/ad001.png" alt="2015年度報告">
</picture>
</div>
<div class="item">
<picture>
<source srcset="img/ad002-l.png" media="(min-width:50em)">
<source srcset="img/ad002-m.png" media="(min-width:30em)">
<img src="img/ad002.png" alt="新年紅包">
</picture>
</div>
<div class="item">
<picture>
<source srcset="img/ad003-l.png" media="(min-width:50em)">
<source srcset="img/ad003-m.png" media="(min-width:30em)">
<img src="img/ad003.png" alt="新手祕籍">
</picture>
</div>
</div>
</div>

<script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="js/vendor/OwlCarousel2/owl.carousel.min.js"></script>
<script src="js/vendor/picturefill.min.js"></script>

在線查看源碼

更多代碼及完整響應式網頁案例請查到這裏GitHub查看。


參考文章

相關文章
相關標籤/搜索