💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
# 响应式图片 响应式 web 设计意味着,不仅我们的布局能基于设备特征变化,内容也能。比如,高分辨率 (2x) 显示屏上,就需要高分辨率图片保证清晰度。当浏览器宽 800px 时,一张 50% 宽度的图片或许很适合,但在一个局促的手机上,则会占用太多空间,另外,缩小图片来适应小屏幕时,耗费的带宽支出却是一样的。 ![](https://box.kancloud.cn/7dda509a28a7ad473a1bbf7731dc8216_1200x655.png) 其余时候,图片也许需要更大幅度的修改:更改比例,裁剪甚至更换整张图片。 ## 传统解决方案 固定宽度,像素完美的网站设计已经离我们远去了。在宽屏显示器,互联网电视,多尺寸的平板电脑和智能手机的今天,我们的设计必须应付一切可能,将宽由320px向7680px转变。 伴随这种多分辨率风景而至的,是需要拉伸或收缩图像,以适应这些不同的要求。这可以被理解为如下问题,矢量图形出现异常时,绝大多数具有特定像素的图像宽度并不改变。 所以,我们应该怎么做呢? 作为一般规则,你会在任何响应式网站中发现以下CSS样式: img{ max-width:100%; height:auto; } 此代码使用max-width:100%的设置,以确保图像永远不会超越其父容器的宽度。如果父容器的宽度收缩小于图像的宽度,图像将随之缩小。height:auto的设置可以确保当有这种情况发生时,图像将以自身的宽高比保留。 ![](https://box.kancloud.cn/5380b23d8a822b86e2b192ff1579eb9a_600x500.png) 这解决了一方面的问题,使我们能够在许多不同的情况下显示相同的图像。不过,这并不能让我们对不同的情况指定不同的图像。 ## 使用HTML5中的picture元素处理响应式图片 <picture>是HTML5一个新的元素。 如果<picture>元素与当前的<audio>和<video>元素协同合作将大大增强响应式图像的工作进程。它允许你放置多个source标签,以指定不同的图像文件名,进而根据不同的条件进行加载。 它可以让你根据以下条件加载完全不同的图像: * 媒体特性结果如:视口的当前高度(viewport height),宽度(width),方向(orientation)。 * 像素密度 反过来这也意味着您可以: * 加载适当大小图像的文件,使可用带宽得到充分利用。 * 加载不同裁剪并具有不同纵横比的图像,以适合于不同宽度的布局变化。 * 加载更高的像素密度,显示更高分辨率的图像。 ![](https://box.kancloud.cn/a7f0c858c63457b8a20be9c522ae98be_600x500.png) ## picture元素的工作原理 <picture>基本工作步骤如下: * 创建<picture></picture>标签。 * 在这些标签内创建一个你想用来执行任何一个特性的<source>元素。 * 添加一个media属性,用来包含你想要的特性,如视口的当前高度(viewport height),宽度(width),方向(orientation)等。 * 添加一个srcset属性与相应的图像文件名相匹配,进行加载。如果你想提供不同的像素密度,例如Retina显示屏,你可以添加额外的文件名到你的srcset属性中, * 添加一个回退的<img>元素。 可以看个简单的例子,用来检查视口是否小于768px,如果小于就加载一个较小的图像: <picture> <source srcset="person_small.jpg" media="(max-width: 768px)"> <source srcset="person_default.jpg"> <img srcset="person_default.jpg" alt="This is King"> </picture> 可以看到在屏幕<=768px的时候加载的是person_small.jpg ![](https://box.kancloud.cn/d3d89e0b27b7e91d78b3164dc5594ca2_500x750.jpg) 当屏幕>768px的时候,加载的是person_default.jpg ![](https://box.kancloud.cn/9c86b7d394abc93dc78031b13175a7a2_1152x1728.jpg) 当浏览器不支持picture元素的时候,使用img标记加载元素。 你可能会注意到,在media属性使用的语法与创建CSS媒体特性中使用的语法一样。您可以使用相同的特性,这意味着你可以查询max-width,min-width,max-height,min-height,orientation等属性。 同时,您也可以使用这些特性判断设备的方向,从而加载横向或纵向版本的图像,同时您也可以进行大小特性的混合。例如: <picture> <source srcset="smaller_landscape.jpg" media="(max-width: 40em) and (orientation: landscape)"> <source srcset="smaller_portrait.jpg" media="(max-width: 40em) and (orientation: portrait)"> <source srcset="default_landscape.jpg" media="(min-width: 40em) and (orientation: landscape)"> <source srcset="default_portrait.jpg" media="(min-width: 40em) and (orientation: portrait)"> <img srcset="default_landscape.jpg" alt="My default image"> </picture> 上面的代码实现了可以在一个小的景观设备上加载小的,景观裁剪图像的版本。在大的景观设备上加载大的相同的图像版本。 这样,在小尺寸的小型设备上,或在大尺寸的大型设备上,该设备可以自主进行图像主导从而加载不同图像剪裁的版本。 如果您想为更高密度的显示器提供不同分辨率的图像版本,可以通过在srcset属性中添加额外的文件名来实现。例如,让我们来看看屏幕像素密度为2x的Retina 代码处理片断: ## picture元素的兼容性 可以看到caniuse上picture元素的兼容性: ![](https://box.kancloud.cn/39294b8259feda908a227f651279ceb0_2172x628.png) 现在,Chrome,Firefox和Opera浏览器都已经实现了对<picture>元素的支持。在不久的将来,在其他浏览器也将得到广泛的支持。但现在这一时刻还没有来临。 与此同时,如果你现在就想使用<picture>元素可能还需要等待。你也可以使用[Picturefill2.0](http://scottjehl.github.io/picturefill/);Filament 成员提供的一个polyfill。 ![](https://box.kancloud.cn/c04170fea9e8eb10889dc1e22b0baa08_1866x1048.png) 通过下载并添加picturefill.js文件到您项目的头部就可以实现: <script src="picturefill.js"></script> 还有你可以通过异步加载脚本来增加效率,你可以参考Picturefill的文档。 有了这个脚本加载,除了少数的限制,<picture>元素将如我所讲的运行。 但是需要注意: Picturefill在其他的IE版本都可以正常工作,但是IE9却不能识别被包裹在picture标签中的source元素。为了解决这个问题,在video标签内包住你的源元素,这就会使他们在IE9中被识别,例如: ~~~ <picture> <!--[if IE 9]><video style="display: none;"><![endif]--> <source srcset="person_small.jpg" media="(max-width: 768px)"> <source srcset="person_default.jpg"> <!--[if IE 9]></video><![endif]--> <img srcset="person_default.jpg" alt="This is King"> </picture> ~~~ 和IE9一样,Android 2.3识别不了在picture元素中source元素。然而,在使用常规的img标签时,它就可以识别srcset属性。为了避免在Android 2.3及任何有相同问题的其他浏览器中出现此问题,确保在srcset属性中存在默认用于回退的img元素的文件名。 ## 参考资源 * [responsiveimages响应式图片](http://responsiveimages.org/demos/) * [picturefill](http://scottjehl.github.io/picturefill/) * [srcset demo](https://webkit.org/demos/srcset/)