学习渐进增强开发思想—用CSS3媒体查询支持移动浏览器
[原文发表地址] Learning about Progressive Enhancement - Supporting Mobile Browsers with CSS3 Media Queries
[原文发表时间] 2011-08-25 08:03
我之前也说过我很开心能与Jeremy Kratz合作,一起重新设计我的站点。
我们最近又见面了,讨论一些细小的改进和微调。我们核心目的之一就是要支持许多种屏幕尺寸,大至30”小至小型智能手机屏幕。你可以从右图看到在Windows Phone和iPhone上的效果。
我的团队最近在手机设备上也做了很多工作,不仅仅是像jQuery Mobile ASP.NET这些而是包含了大体上所有的移动web。我们还和51Degrees合作,他们甚至创建了一个NuGet包,可以帮助您量身定制您的网站到任何设备上。Steve之后也会对 ASP.NET中的Mobile做详尽的解释,我也会分享之后相关会议中的一些想法。
我最早在2006年的这一周就曾开过有关移动浏览的博客。那是5年前了,移动设备才刚刚兴起。回到当时,我的移动视图是单独剥离的,而且在用户代理的嗅探下发出的是完全不同的标记。在当时,这相当创新,那可是5年前啊。在ASP.NET中(此篇博客中会慢慢继续)有很多东西可以实现适应性标记。不过更多的现代技术偏向适用服务器端的检测和客户端功能检测相结合。我们用JavaScript询问了浏览器:你是否支持本地地理位置?不支持?那适用这个JavaScript库呢?
当一个页面布局之后,除了通过服务器检测浏览器上的服务器提供不同的标记之外,我们还可以用CSS3媒体查询基于屏幕大小来修改布局。我在这篇博客中要介绍的就是这些技术。
当我认识到有些人希望通过一个完全自定义的iPhone web应用来访问页面,我认为web页面,移动web页面和移动web浏览器应用之间是界限分明的。在访问我定义中的常规网页时,我不想要特定的iOSweb版式和我看不见的常规web。我希望的结果是可以看到我访问的页面,穿插着许多元素和周围的一些东西。
不过,如果网站互动性很强的话,我可能希望移动网站可以为不同的智能手机提供不同的可能基于设备的标记。我认为决定应用程序的样式,或为特定设备设计的依据是,你的移动网站与用户有多大程度的互动性或只是读取/使用内容上做衡量。
基于这篇博客,就不用那么多特定智能手机了。我想要一个移动优化版的网站,而不是一个完整的iOS(或者Android,WP7等等)网站复本。如果我那样做了的话,那我只需要下载一个应用程序。
如果你正在创建一个web应用程序,致力于“生产”(就是按按钮,做应用一类的东西的话),我可以理解那需要使用特定的手机框架,但是在“使用”部分,我希望我的web网页看上去像是真正的web网页。
CSS3媒体查询
设计师Jeremy和我(主要是他)希望能支持像台式机,平板电脑和网络书的1024像素宽度,和手机小于720像素左右宽度的设备。
以下是CSS的总体构架。注意这些都不是JavaScript,只是用来描述“当屏幕是这样时,应用这样的风格”之类的东西。
桌面VS移动页面导航
看上去都很不错,直到你重设页面大小时,顶端的导航栏会被挤压,然后超出范围。不过,Jeremy有个很好的想法。导航放在顶端是不错,但是当屏幕确实很小的时候,导航就看不到了。导航其实就是一个乱序的列表,如下:
1: <div id="nav">
2: <ul id="primarynav">
3: <li id="nav-info"><strong>Info</strong>
4: <ul>
5: <li><a title="Learn more about Scott Hanselman" href="https://www.hanselman.com/blog/AboutMe.aspx">About Me</a></li>
6: <li><a title="Contact Scott Hanselman" href="https://www.hanselman.com/blog/contact.html">Contact Me</a></li>
7: </ul>
8: </li>
9: <ul>
10: ...more..
11: </div>
为什么不为小屏幕设计一个下拉呢?实际上这是一个堆栈溢出的问题(但是你知道吗Jeremy是最早设计堆栈溢出的)我可以在DIV上加一个下拉并把它硬编码了,但是在UL中这个结构已经存在了,我可能要在以后进行变更以免重复了。我们会用JavaScript将SELECT加到HTML DOM(文件对象模型)中。
基本上我们只是分拆UL结构,用已有的机制创建选择,选项和(bonus!)选项组。
1: $(document).ready(function() {
2: var markUp = ["<select id='primarynav-select'>"], $li, $a;
3: markUp.push("<option value='' selected='selected'>Go to...</option>");
4: $("#primarynav > li").each(function(){
5: $li = $(this);
6: if($li.find("li").length){
7: markUp.push("<optgroup label='"+$li.find("strong").text()+"'>");
8: $li.find("li").each(function(){
9: $a = $(this).find("a");
10: markUp.push("<option value='"+$a.attr("href")+"'>"+$a.text()+"</option>")
11: });
12: markUp.push("</optgroup>");
13: }
14: else{
15: $a = $li.find("a");
16: markUp.push("<option value='"+$a.attr("href")+"'>"+$a.text()+"</option>")
17: }
18: });
19: markUp.push("</select>");
20:
21: $("#primarynav").after(markUp.join(''));
22: $("#primarynav-select").change(function(){ window.location = $(this).val(); });
23: });
所以,
就变成了这样,你在重设很小的浏览器大小的时候,只要隐藏掉一个,用CSS显示其他用途就可以了。
在小屏幕上重设图片大小
对于会有许多移动设备流量问题的重要网站,你可能想用像51Degrees这样的浏览器库,可以告诉你特定手机的屏幕大小和图像格式(PNG,JPG,是否透明),这样你就能在服务器端重设大图像大小然后发送移动优化过的图像了。你可以有一个处理器来检测小屏幕手机然后重设大小并缓存图像。甚至可以为非彩屏手机设置图像灰度。
在我的例子中,我的图像没有那么大,而且对我来说要在服务器端重设大小也没那么重要。所以我在客户端使用CSS对图像重设了大小。就像这样:
1: img
2: {
3: width: auto !important;
4: height: auto !important;
5: max-width: 100%;
6: }
就是说,无论其他CSS或者标记说了什么,图像只能调到100%,不能比这再大了。这对那些我博文开始放置的那些大照片来说是简洁有效的方案。要避免超出范围或者满出手机屏幕边缘,然后调整大小。你可以试试重设浏览器大小就能亲自看到效果。
这里你可以在Ipad上看到这个页面。注意右边的护栏没有了。在右边,和iPhone 4一样,640像素宽度。看看图像是如何上移成手机宽度的?
你还可以用CSS媒体查询,不用任何的JavaScript,来检测iPad方向,使用的是iPhone 4高清晰度显示屏还是低清晰度的3G iPhone这些。
这是从DesignerWall上摘录下的CSS样本,分别归Thomas Maier和Cloud Four所有。
1: <!-- Detect iPhone4 Retina Display from CSS -->
2: <link rel="stylesheet" media="only screen and (-webkit-min-device-pixel-ratio: 2)" type="text/css" href="iphone4.css" />
3:
4: <!-- Detect iPad and iPad orientation -->
5: <link rel="stylesheet" media="all and (orientation:portrait)" href="portrait.css">
6: <link rel="stylesheet" media="all and (orientation:landscape)" href="landscape.css">
实际上你可以通过把桌面浏览器设定成宽度大于高度,来模拟测试一下。
还有一些内容需要微调一下,这些技术只能在支持这些功能的现代智能手机浏览器上有效。不过对于你们正在移动设备上阅读这篇博客的8%来说,现在的效果应该好多了。
一个警告—代码样本
所有都挺好的,就有一点不好。代码样本我用的是SyntaxHighlighter。它有<pre>然后会使用JavaScript做很多事情,很有效率地用一大堆东西去替换DOM中的PRE。这在桌面浏览器中还是挺可爱的,但对于移动设备来说就悲剧了。我还在探索怎么修复这一点。以下是我的一些想法。
- 有条件地用媒体查询覆盖SyntaxHlighter CSS
- 更改插件,以隐藏形式保住<pre>。然后用手机上平整的内容替换高光强调的那个。
- 寻找更好的CSS,寻求更好的高光强调
我希望听到你们的想法!
更新: 我最近在读自适应网页设计:使用渐进增强开发思想精加工,真的很棒。Aaron给了我一份复习拷贝。他划出了一个相似的UL来
SELECT增强和很多其他内容,整体很清晰干净,易于阅读。我很乐在其中。
相关链接