使用媒体查询进行移动优化的背景而不是内联图像?

Posted

技术标签:

【中文标题】使用媒体查询进行移动优化的背景而不是内联图像?【英文标题】:Background instead of inline images for mobile optimization with media queries? 【发布时间】:2011-12-11 17:33:51 【问题描述】:

我已经通过媒体查询优化了我的网站。一切看起来都是我想要的样子,但是正在下载不必要的图像(因为它们被 css 隐藏了),从而减慢了页面加载时间。

对此最简单的解决方案似乎是用带有背景图像的 div 替换尽可能多的内联图像。然后我可以使用移动版本的媒体查询 css 隐藏 div。

我知道这有潜在的缺点,在这篇文章中有很好的概述: When to use IMG vs. CSS background-image?

因此,公司徽标、员工照片等将保留为内嵌图像。

我的方法有没有我没有考虑过的问题?我读过很多关于移动优化的文章,尤其是媒体查询,我还没有听说有人这样做,尽管这似乎是一个非常明显的解决方案,图像可以是内联或背景。

注意,我在 iPhone 和 android 上做了一些实验(我正在等待获得一些黑莓),我知道要停止下载背景图片,我需要将 display none 设置为 div 的父级,而不是带有背景图片本身的 div。

注意2,在理想的世界中,网站可能首先被构建为移动设备,但在这种情况下(通常在其他情况下),原始网站可以修改的程度是有限的。

谢谢

【问题讨论】:

在不透露太多信息的情况下,您能给我们介绍一下该网站的背景吗?它为哪些受众提供什么类型的内容?等等? 我对我的解决方案的任何潜在问题更感兴趣,因此我可以在将来将它应用(或不应用)到网站。移动网络使用量增长非常快,只要没有我不知道的问题,我就可以清楚地看到自己在各种网站上使用我的解决方案。我已经更新了我的问题,所以更清楚。谢谢 【参考方案1】:

如果我正确理解了您的问题,这似乎是 srcsetsizes 的完美用例。 This MDN article 是深入学习概念的好帖子,但我也会在这里总结一下。这是一个完整的、复杂的例子:

<img srcset="elva-fairy-320w.jpg 320w,
         elva-fairy-480w.jpg 480w,
         elva-fairy-800w.jpg 800w"
     sizes="(max-width: 320px) 280px,
        (max-width: 480px) 440px,
        800px"
     src="elva-fairy-800w.jpg" 
     >

这段代码说:

如果我的浏览器不支持srcset,则默认使用src 中的内容。不要遗漏这一点。 您好浏览器,在srcset 中,这里有 3 个文件,它们的自然宽度用逗号分隔。 嘿浏览器,sizes 这里是我希望我的图像根据媒体查询占用的空间宽度。使用第一个匹配的。

然后浏览器本身会根据用户的大小和屏幕分辨率计算出哪个是最好的图像,然后只下载我书中非常棒的那个。

【讨论】:

【参考方案2】:

很遗憾,您要解决的问题没有很好的答案。

首先,您可以选择将所有内容从 img 标签移动到 css 背景图像。正如您所注意到的,您必须小心这样做会丢失语义。

但即使您可以在不丢失语义价值的情况下移动到背景图像,它仍然不会 100% 可靠。去年夏天我写了一系列测试。上周我重新测试了它们,为我们的移动优先响应式网页设计一章做准备。测试位于http://www.cloudfour.com/examples/mediaqueries/image-test/。

不幸的是,Android 未能通过这些技术中的每一项。您可以通过 Blaze 的移动测试看到它下载了多个图像文件副本: www.blaze.io/mobile/result/?testid=111031_96_316

2011 年 11 月 3 日更新:我目前正在尝试协调我在 Blaze 上看到的结果与我亲自使用同一设备看到的结果之间的不一致。在我本地的 Nexus S 上,它通过了第五个 css 测试,该测试通过将 imgs 放在媒体查询中来限制它们。我查看了 apache 日志并确认该设备仅下载一个图像而不是两个用于测试 5。Blaze 正在运行 2.3.3。我的手机运行的是 2.3.6。

这适用于 Android 2.2、2.3 和 3.0。希望 4.0 将包含防止这种行为的 webkit 修复: bugs.webkit.org/show_bug.cgi?id=24223

顺便说一句,这似乎与您关于在 Android 上测试将父 div 设置为 display:none 的评论相冲突。如果您得到不同的结果,我很想听听。

如果您将它们保留为 img 标签,您有哪些选择?关于这个主题,我写了一个多部分的系列。该系列的第二部分深入介绍了不同的技术: http://www.cloudfour.com/responsive-imgs-part-2/

同样,没有一个解决方案很好。如果您想要一些简单且大部分时间都可以使用的东西,我会选择adaptive-images.com。或者通过 Sencha.io SRC 路由图像,直到我们对此问题有更好的解决方案。

顺便说一句,很抱歉有这么多实际上不是链接的链接。这是我对 *** 的第一个回复,它只允许我包含两个链接。

【讨论】:

基于cookie的解决方案的主要问题是第一次访问时不起作用,这是最重要的,尤其是对于没有大量常规访问者的小型企业网站。例如酒店... @mdi 我同意。很少有网站拥有与波士顿环球报相同的回访率。 遗憾的是,波士顿环球报的响应式图片 javascript 无法正常工作,因此移动设备目前每次访问都会获取大图片。【参考方案3】:

适应现有网站很糟糕,但我们必须做我必须做的事情。这是我在将博客的提要导入移动网站时解决它的方法。只有当它大于屏幕时,它才会将页面上的现有图像缩放到页面的宽度。

var $images = $("img[width]");
    $images.each(function() 
      try
          var $image = $(this);
          var currentWidth = Number($image.attr("width"));
          if(currentWidth > screen.width)
              $image.width("100%");
              $image.removeAttr("height");
           
      
      catch(e)
      /*alert("image scale fail\n"+e)*/
 );

通过将宽度设置为 100% 并删除任何高度属性,无论您是横向还是纵向,图像都会完美缩放以占据整个宽度。

很有可能,您常规网站上的图片已经过网络优化。通过加载较小的图像通常不会获得太多的性能提升。减少 HTTP 请求比引入更小的图像更能提高性能。它可能不是完美的解决方案,但肯定是维护最少的。如果您无法合理控制将在网站上使用哪些图像,这是一个非常合理的解决方案。如果不出意外,也许这会激发您的另一个想法。

【讨论】:

【参考方案4】:

我最近偶然发现了一个很棒的blog article,它解决了响应式图像的问题(即在较小的设备上提供较小的图像)。文章的 cmets 是最有趣的部分,我认为 Weston Ruter 提出的替换技术是一个很有前途的技术:

http://jsbin.com/ugodu3/13/edit#javascript,html,live (查看 cmets 中的其他迭代)。

它有很多警告(合并到现有网站可能很困难,但并非不可能,因为这会影响您的所有非绝对链接,不仅是 imgs),但我会尝试(与延迟加载合并) )在我的下一个项目中,这是一个响应式网站,我的设计师做得很重(他不想让它更轻)。请注意,如果您的服务器支持,您可以将其与按需调整图像大小的 php 脚本结合使用。

其他常见的响应式 img 解决方案是基于 cookie(查看 Filament Group Responsive images plugin)。

我更喜欢响应式图像而不是 css 背景,因为它们在语义上更正确,并且在 SEO 方面更易于解析。如果我同意我们不应该假设更大的屏幕 = 更多的带宽,我们缺乏解决这个问题的工具(navigator.connection 仅适用于 Android。)因此假设大多数移动用户的 2G/3G 连接很糟糕是最安全的方法。

【讨论】:

【参考方案5】:

好的,需要注意的重要一点是移动!= 低带宽!= 小屏幕和桌面!= 高带宽!= 大屏幕。

您可能想要的是根据客户端带宽和客户端屏幕大小做出决定。媒体查询仅对后者有帮助。

David Calhoun 有一篇关于如何做到这一点的精彩文章:http://davidbcalhoun.com/2011/mobile-performance-manifesto

强烈推荐。

【讨论】:

【参考方案6】:

我不确定您是否考虑过这样做,但您可以做的一件事是使用 javascript 检查屏幕分辨率的宽度,然后检查分辨率是否小于某个数字(我使用 480,因为在那个站点看起来很糟糕)然后将css模板从默认切换到移动主题模板。

function alertSize() 
  var myWidth = 0, myHeight = 0;
  if( typeof( window.innerWidth ) == 'number' ) 
    //Non-IE
    myWidth = window.innerWidth;
    myHeight = window.innerHeight;
   else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) 
    //IE 6+ in 'standards compliant mode'
    myWidth = document.documentElement.clientWidth;
    myHeight = document.documentElement.clientHeight;
  
  if (myWidth < 48)
  
   switch css template to mobile template
  

【讨论】:

如果我先加载普通css,然后用js加载其他样式,那么普通css的背景图片已经下载了。 如果我使用js来确定加载哪些样式,那么如果桌面用户没有js,不会下载样式吗? @jdln 如果您在加载 css 文件之前将脚本加载到测试屏幕分辨率的头部中,这应该不是问题。这是一个帮助我理解这一点的链接。 uxmovement.com/content/… @jdln 是的,如果他们禁用了 javascript,这可能会导致问题。您可以在兼容 HTML5 的浏览器中使用头部中的 noscript 来解决此问题【参考方案7】:

为什么不采用移动优先方法,然后使用媒体查询来增强更大的屏幕。

您还可以使用媒体查询来提供特定的 CSS 文件。

对于内联图像,我在头部和打开正文标记之后立即尝试了一个脚本块,它仅适用于找到所有移动设备的移动设备(通过添加到正文的类名或媒体查询 CSS 文件的存在进行检测)内联具有特定类的图像并清空 src 属性。

看这里Prevent images from loading

<script type="text/javascript" charset="utf-8">
    $(document).ready( function()  $("img").removeAttr("src");  );
</script>

另一种方法是使用 url 重写与 mod rewrite 和 .htaccess 或 iis 的 url 重写模块。将手机的用户代理字符串重定向到一个小的空白图像。

见: A way to prevent a mobile browser from downloading and displaying images

RewriteCond %HTTP_USER_AGENT (nokia¦symbian¦iphone¦blackberry) [NC] 
RewriteCond %REQUEST_URI !^/images/$
RewriteRule (.*) /blank.jpg [L]

您可以通过从不同的子域加载内联图像并仅重写移动设备来改进上述内容,因为您不想重写所有图像(徽标等)

【讨论】:

我喜欢第一种移动方式,但我正在修改一个已经构建的站点(我没有构建)。 我担心检测用户代理字符串,部分是从维护的角度来看,但也因为我读过它并不完全可靠。 你很可能想关注我的另一个related question 如果我理解“阻止图像加载”方法,因为 javascript 在 html 和内容下载后运行,该方法仅在图像不在 html 中而是仅加载时才有效通过 javascript。当然不是所有的台式机/笔记本电脑用户都会有 javascript? 我看到了,试试用户代理字符串。很多公司以此为生,想想所有的分析公司。

以上是关于使用媒体查询进行移动优化的背景而不是内联图像?的主要内容,如果未能解决你的问题,请参考以下文章

我可以在内部 CSS 中使用媒体查询,它会避免加载我定义的背景图像吗?

使用媒体查询隐藏背景图像

html 内联媒体查询图像

如果背景图像被媒体查询替换,它们会加载吗?

我应该使用媒体查询进行响应式设计吗?

媒体查询分组而不是匹配的多个分散的媒体查询