图片方面的自适应处理------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 href="http://voormedia.com/blog/2012/11/responsive-background-images-with-fixed-or-fluid-aspect-ratios">Responsive background images with fixed or fluid aspect ratios</a>,文章中介绍了如何解决背景图像的固定和流体的纵横比例。接下来我们一起来看看Rolf Timmermans是如何实现的。</p>
<h3>

固定纵横比例</h3>

<p>在保持背景图片的纵横比例,关键之处是是让背景图片垂直居中。而其中主要是基于宽度的百分比来设置内距<code>padding</code>的百分比值。这种技术早前在<a href="http://alistapart.com/article/creating-intrinsic-ratios-for-video">创建视频纵横比例</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 href="http://voormedia.com/blog/2012/11/responsive-background-images-with-fixed-or-fluid-aspect-ratios">Responsive background images with fixed or fluid aspect ratios</a>一文。</p>

<p>上面两种方案主要是根据背景图片的纵横比例来实现图像的自适应效果。但在<a href="http://twitter.com/necolas">Necolas</a>在<a href="http://nicolasgallagher.com/flexible-css-cover-images/">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 href="http://louisremi.github.io/jquery.backgroundSize.js/demo/">backgroundSize.js</a>、<a href="http://srobbin.com/jquery-plugins/backstretch/">BACKSTRETCH</a>、<a href="http://johnpatrickgiven.com/jquery/background-resize/">jQuery Easy Background Resize</a>等插件。<a href="http://kimili.com/about/">Michael Bester</a>在<a href="http://kimili.com/journal/the-flexible-scalable-background-image-redux">The Flexible Scalable Background Image, Redux</a>一文中也做过这方面的介绍。</p>

<h2>

方案三:Object-fit</h2>

<p><a href="http://www.w3cplus.com/css3/css3-object-fit-and-object-position-properties.html">Object-fit</a>是CSS3的一个新属性,到目前为止仅在Chrome32+版本上可以正常运行。这个属性可以说就是为自适图片尺寸而生,特别适合于响应式设计中图片以及其他富媒体的自适尺寸的处理。</p>

<p>使用<code>Object-fit</code>属性有一个受限条件,需要在样式中显示的设置图片的尺寸。然后通过其属性值<code>fill</code>、<code>cover</code>或<code>contain</code>值来控制图像显录的纵横比例。在此并不建议使用,不过当作兴趣爱好,可以深入了解他。如果你对此属性感兴趣,可以阅读《<a href="http://www.w3cplus.com/css3/css3-object-fit-and-object-position-properties.html">CSS3 Object-fit和Object-position</a>》一文,文中详细介绍了<code>object-fit</code>属性的具体使用。</p>

<h2>

其他方案</h2>

<p>除了上述的几种方案之外,其实还有其他的一些解决方案,比如<a href="http://www.zhangxinxu.com/">@张鑫旭</a>在其博客《<a href="http://www.zhangxinxu.com/wordpress/2012/02/responsive-images-introduce/">热门:响应图片(Responsive Images)技术简介</a>》一文中就介绍了如何使用“Cookie+Server”、“使用<code>noscript</code>标签创建”等其他方法。<a href="http://andyshora.com/css-image-container-padding-hack.html#author">Andy Shora</a>在《<a href="http://andyshora.com/css-image-container-padding-hack.html">Sizing Fluid Image Containers with a Little CSS Padding Hack</a>》还介绍了一种老方案——<strong>内距和绝对定位实现图片自适应</strong>。当然除了这些还有其他的。<a href="http://mobile.smashingmagazine.com/author/sherri-alexander">Sherri Alexander</a>特意为解决响应式设计的图片问题,在《<a href="http://mobile.smashingmagazine.com/2013/07/08/choosing-a-responsive-image-solution/">Choosing A Responsive Image Solution</a>》一文中搜集了很多个JavaScript解决方案。感兴趣的同学,可以仔细研究研究。</p>

<h2>

扩展阅读</h2>

<ul><li><a href="http://nicolasgallagher.com/flexible-css-cover-images/">Flexible CSS cover images</a></li>
<li><a href="http://alistapart.com/article/fluid-images/">Fluid Images</a></li>
<li><a href="http://demosthenes.info/blog/586/CSS-Fluid-Image-Techniques-for-Responsive-Site-Design">CSS Fluid Image Techniques for Responsive Site Design</a></li>
<li><a href="http://unstoppablerobotninja.com/entry/fluid-images">FLUID IMAGES</a></li>
<li><a href="http://voormedia.com/blog/2012/11/responsive-background-images-with-fixed-or-fluid-aspect-ratios">Responsive background images with fixed or fluid aspect ratios</a></li>
<li><a href="http://www.vanseodesign.com/css/flexible-images/">How To Create Flexible Images And Media In CSS Layouts</a></li>
<li><a href="http://realityonweb.com/web-standards/different-ways-of-making-images-flexible-in-responsive-web-design/">Different ways of making images flexible in responsive web design</a></li>
<li><a href="http://24ways.org/2011/adaptive-images-for-responsive-designs/">Adaptive Images for Responsive Designs</a></li>
<li><a href="http://alistapart.com/article/responsive-images-how-they-almost-worked-and-what-we-need">Responsive Images: How they Almost Worked and What We Need</a></li>
<li><a href="http://www.zhangxinxu.com/wordpress/2012/02/responsive-images-introduce/">热门:响应图片(Responsive Images)技术简介</a></li>
<li><a href="http://demo.solemone.de/overflow-image-with-vertical-centering-for-responsive-web-design/">Overflow Image with vertical centering for Responsive Web Design</a></li>
<li><a href="http://andyshora.com/css-image-container-padding-hack.html">Sizing Fluid Image Containers with a Little CSS Padding Hack</a></li>
<li><a href="http://kimili.com/journal/the-flexible-scalable-background-image-redux">The Flexible Scalable Background Image, Redux</a></li>
<li><a href="http://mobile.smashingmagazine.com/2013/07/08/choosing-a-responsive-image-solution/">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 href="http://www.w3cplus.com/css/flexible-images.html">http://www.w3cplus.com/css/flexible-images.html</a></p>

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,347评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,435评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,509评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,611评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,837评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,987评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,730评论 0 267
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,194评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,525评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,664评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,334评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,944评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,764评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,997评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,389评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,554评论 2 349

推荐阅读更多精彩内容

  • 选择qi:是表达式 标签选择器 类选择器 属性选择器 继承属性: color,font,text-align,li...
    love2013阅读 2,304评论 0 11
  • 选择qi:是表达式 标签选择器 类选择器 属性选择器 继承属性: color,font,text-align,li...
    wzhiq896阅读 1,732评论 0 2
  • 1、垂直对齐 如果你用CSS,则你会有困惑:我该怎么垂直对齐容器中的元素?现在,利用CSS3的Transform,...
    kiddings阅读 3,153评论 0 11
  • 1、属性选择器:id选择器 # 通过id 来选择类名选择器 . 通过类名来选择属性选择器 ...
    Yuann阅读 1,621评论 0 7
  • 近来因为工作上的摩擦,总和同事争得面红耳赤,虽然事情终得解决,但是过程却不免有些难堪。在消极情绪的带动下,士气低落...
    寻覔阅读 641评论 3 6