领先技术

响应式网站上的有效图像处理

Dino Esposito

Dino Esposito响应式 Web 设计 (RWD) 可通过一个可变的自适应 Web 布局提供独特的 Web 体验,这无疑是改变现实世界物流的里程碑之一。

作为 Web 开发人员,您必须准备好同时接受事物的正反面。一方面,RWD 实际上是一个标准。它正在成为所有网站的必备技术。另一方面,RWD 是一个还在发展的方法,仍在定义和重新定义最佳做法。本文旨在提供 RWD 最新技术的快照,着重探讨最重要的方面:整体性能和特定图像处理。

RWD 性能

RWD 的主要目的是使用户能在设备上轻松愉快地使用内容,无论设备的大小和形状如何。目前为止还没有什么问题,但您该怎么做呢?

RWD 需要完全不同的项目审批和开发方法。客户查看静态模型并给予批准时的规范可见检查点是一个定义少得多的步骤。您可能会呈现线框而不是静态模型。总而言之,响应式站点很容易出售给客户,但很难解释为什么它最终比传统的非响应式站点贵。

数年经验有助于整合一些做法和框架,例如新兴的 Twitter Bootstrap 可帮助响应式站点的实现。但性能如何呢?

目前,性能是 RWD 的弱点。从功能强大的桌面浏览器进行查看时,响应式站点运行良好。然而,通过诸如智能手机的小型设备来使用响应式站点时,其性能却开始下降。RWD 对于各种网站类型并不是都很高效。与包含很多表单且需要交互的站点(如旅行预定网站)相比,新闻和视频门户更容易进行调整,以便使内容可在较小屏幕上使用。对于包含很多表单且需要交互的站点,屏幕大小是更为重要的因素。

在潜在用户开始 RWD 实现之前,要询问的一个关键问题是其业务在多大程度上依赖于各种设备的功能。如果设备用于业务用途,如搜索或购买产品或服务,那么您不能只根据普通屏幕的宽度和方向来区分内容。已重新调整大小的桌面浏览器窗口和智能手机可能可以使用相同布局来显示内容,但它们在不同的硬件上运行,并具有截然不同的计算能力。如果业务依赖于选择的设备,则在做出任何决定之前应仔细考虑这些差异。

“一个网站”的启示

“一个网站”的启示是 RWD 的基础:其中有一套独特的内容页面、一个后端逻辑、一个 URL 和一个品牌。有两种方法可以用来处理这一类型的 RWD 站点开发。不考虑设备,为每个视图提供相同的 HTML 标记,并为设备制作一组不同的 CSS 文件。将每个 CSS 文件绑定到当窗口大小更改时浏览器在运行时计算的媒体查询表达式。应用的 CSS 可能发生动态更改,这将改变内容的外观。这种方法广泛地依赖于 CSS3 媒体查询(bit.ly/1oVBf89 定义的万维网联盟 (W3C) 标准)。如何定义要应用于两个不同的屏幕大小的两个 CSS 文件如下所示:

<link type="text/css"
  rel="stylesheet"
  href="view480.css"
  media="only screen and (max-width: 480px)">
<link type="text/css"
  rel="stylesheet"
  href="view800.css"
  media="only screen and (max-width: 800px)">

开发响应式站点的另一个选择包括使用 CSS3 媒体查询和 JavaScript 代码来适当地调整文档对象模型 (DOM)。这种方法的功能更加强大,因为它可以用来更好地对布局进行控制。它还增加了下载特定于屏幕大小的附加内容的机会。要检测屏幕大小的更改,您可以使用窗口调整大小事件或 matchMedia 事件。matchMedia 事件是媒体查询的 JavaScript 实现。当浏览器在指定媒体查询中检测到更改时,将触发对代码的调用:

if (window.matchMedia) {
  mq800px = window.matchMedia("(min-width: 800px)"),
  mqPortr = window.matchMedia("(orientation: portrait)");
  mq800px.addListener(mq800px_handler);
  mqPortr.addListener(mqPortr_handler);
}

当浏览器检测到方向为纵向或最小宽度为 800 像素时,代码将调用您的处理程序。您可以在同一站点中使用 JavaScript 和 CSS 媒体查询。它们适用于单个 HTML 视图或页面。

因此,RWD 后面的关键模式就是一组包含多个视图的内容,无论您使用 CSS 还是一些临时的 JavaScript 来进行调整。如果您采用 CSS 方法,则您可以执行的操作取决于您使用 CSS 在 Web 页面中可以执行的操作。您可以移动并重新定位元素,可以在不同大小的容器内重排内容,使内容块水平或垂直浮动。您还可以仅隐藏不需要的内容。

如果使用 JavaScript,您可以执行上述所有操作以及以下操作。您可以对视图布局做更复杂的更改,从头创建 DOM 子树,或者从远程终结点下载新内容。使用 CSS 时,DOM 是最大可能。使用 JavaScript 时,它只能达到设计的最大可能。

当在桌面浏览器上浏览站点时,RWD 解决方案的大小不是问题。甚至在大多数平板电脑上这也不是个问题。它们往往功能强大,足以运行任何所需的 JavaScript,并且经常通过可靠的 Wi-Fi 连接使用。但在智能手机上使用 3G 连接浏览 RWD 站点就存在问题。出现问题时,不是因为标记和 JavaScript 代码的数量太多,而是相关事件及其对线程的影响使内容停滞不前。RWD 问题最大的方面是图像。

处理图像

旧的 img 元素引用图像。图像将完全下载,并按宽度和高度属性指定的值显示。如果您需要一个适用于桌面的大背景图像或多个适合轮播的大图像,则您不能只使用 CSS 来调整宽度和高度。这对下载大小没有任何影响。通过 CSS 也无法隐藏图像,因为图像已下载。

在等待新的 HTML 元素可用时,您可以使用几个技巧。但是,新的 HTML 元素受浏览器广泛支持仍尚需时日。我们进行了一些试验,但尚未迎来黄金时期。方向似乎是让某个元素的结构在视频元素的 HTML5 结构上闪烁,如下所示:

<picture>
  <source media="(min-width: 400px)" srcset="foo-sm.jpg, foo-sm-2x.jpg 2x">
  <source media="(min-width: 800px)" srcset="foo-md.jpg, foo-md-2x.jpg 2x">
  <img src="foo.jpg">
</picture>

当使用图片而不是 img 时,将为同一逻辑图像提供大量选择。您可为每个媒体查询方案提供一组图像,并且您还可以在每个方案中提供多个图像以满足不同的像素密度要求。在该示例中,当屏幕宽度至少为 800 像素时,如果发生给定媒体查询,浏览器可以选择适当大小的常规图像,或适合更高密度的定制大副本,或者为满足艺术指导的要求并提供其他图像或原始图像的裁剪图像。嵌入的 img 元素表示回退,且在逻辑上等同于目前所使用的内容。您可以使用 bit.ly/1aVEoxb 提供的 JavaScript 填充代码来试验这一方法。

另一个方法是使用服务器端逻辑,如 HTTP 处理程序。处理程序将接收请求并确定下载哪个图像。坦白地讲,这种方法可能是一个挑战。服务器端逻辑需要一些线索以选择最合适的图像。这些线索只能来自于浏览器,且应放入 HTTP 请求,无论是通过查询字符串还是标头。在页面加载时下载图像要求完成一些脚本工作。这是可行的,但需要技巧。

在等待图片元素时,要成为标准且可用于所有浏览器的 RWD 规范的图像大小和其他方面(目前只有 Chrome 和 Opera 提供一些支持)将停止并反映您尝试解决的问题。

只要用户使用桌面浏览器,图像的大小就不是什么大问题。只需将 img 指向最大大小。如果调整过浏览器窗口的大小,也会调整同一大图像的大小。此时,它不再对性能产生影响。您要更改小窗口上的图像以专注于特定方面。在这种情况下,有一招就是通过 CSS 而不是普通的 img 元素来将图像引用为 div 集的背景。这样做的好处是媒体查询将只选择您所需的图像。您可能会在桌面上下载多个图像,但这也许可以忽略不计。如果用户尝试打印此页面,背景图像可能会出现其他问题。

当 RWD 站点在移动设备上进行显示时,使用背景图像会有所帮助。图像一定是适当大小。无论采用哪种方式,当您计划在非桌面设备上查看站点时,您需要解决 RWD 中图像的使用问题。

如何检测您所使用的设备类型?检测设备并不是致命错误。可靠地检测设备很困难,如果您自己执行这一操作将会搞得一团糟。您可以针对某些形式的客户端设备检测,使用常用的 Modernizr 插件 (bit.ly/1tfJhtf)。通过这种方式,您可以编程方式修改 DOM 以尝试获取特定图像。这一方法合理,但无法随着设备数量的变化而进行调整,可能会在某些时候变得不可靠。设备检测是一件严肃的事情,需要专业知识。

WURFL Image Tailor 简述

处理图像的一个新的有趣方法是无线通用资源文件 (WURFL) Image Tailor (WIT) 组件。由完整的 WURFL 引擎(Facebook 使用的同一设备检测引擎)支持,WIT 对用户代理执行快速服务器端分析。它决定了请求设备的外观造型,并充当原始图像的已调整大小版本。WIT 是一项免费服务,只需修复图像 URL:

<img src="//wit.wurfl.io/[full-url-to-your-image]">

将完整图像 URL 附加到 WIT Web 站点 URL,以便从原始 Web 站点下载图像、调整图像大小,并将像素返回到请求站点。图像缓存在 WIT 端。这将请求数量保持在最低限度。一组受支持的参数可用于控制调整大小方面的内容,如剪切、尺寸和返回的格式。

WIT 有优缺点。优点是,它缓解了您处理同一图像的多个版本的压力。唯一需要的是对普通旧 img 元素中的 URL 版本略做修改。另外,您可以在数秒钟开始使用它。

缺点是,它可以充当代理,但不会具体解决您所关心的像素密度而不仅仅是大小的情况。无论如何,我们没有理由不试一试。您可以在 wurfl.io/#wit 找到 WIT。

在 RWD 上下文中处理图像的状况也在不断变化。RWD 和设备之间必须达成某种妥协以确保内容在各种设备上正常工作。


Dino Esposito 是《Microsoft .NET:Architecting Applications for the Enterprise》(Microsoft Press,2014 年)和《Programming ASP.NET MVC 5》(Microsoft Press,2014 年)的合著者。作为 JetBrains 的 Microsoft .NET Framework 和 Android 平台的技术推广人员,Esposito 经常在全球行业活动中发表演讲,并在 software2cents.wordpress.com 上以及 twitter.com/despos 上的推文中分享他对于软件的愿景。

衷心感谢以下技术专家对本文的审阅:Jon Arne Saeteras