HTML5移动开发

978-7-115-43891-1
作者: 【美】Estelle Weyl(埃斯特尔 韦尔)
译者: 范圣刚陈宗斌
编辑: 傅道坤

图书目录:

详情

通过将HTML5和CSS3添加到你的Web开发工具箱中,你可以为所有移动(和非移动)平台创建优秀的网站和应用。通过本书,你将学习到如何开发Web应用,使其不但可以在iOS、Android、BlackBerry和Windows Phone上运行,还可以具有良好的性能并提供卓越的用户体验。

图书摘要

版权信息

书名:HTML5移动开发

ISBN:978-7-115-43891-1

本书由人民邮电出版社发行数字版。版权所有,侵权必究。

您购买的人民邮电出版社电子书仅供您个人使用,未经授权,不得以任何方式复制和传播本书内容。

我们愿意相信读者具有这样的良知和觉悟,与我们共同保护知识产权。

如果购买者有侵权行为,我们可能对该用户实施包括但不限于关闭该帐号等维权措施,并可能追究法律责任。


• 著    [美] Estelle Weyl

  译    范圣刚 陈宗斌

  责任编辑 傅道坤

• 人民邮电出版社出版发行  北京市丰台区成寿寺路11号

  邮编 100164  电子邮件 315@ptpress.com.cn

  网址 http://www.ptpress.com.cn

• 读者服务热线:(010)81055410

  反盗版热线:(010)81055315


Copyright © 2014 by O’Reilly Media. Inc.

Simplified Chinese Edition, jointly published by O’Reilly Media, Inc. and Posts & Telecom Press, 2016. Authorized translation of the English edition, 2014 O’Reilly Media, Inc., the owner of all rights to publish and sell the same.

All rights reserved including the rights of reproduction in whole or in part in any form.

本书中文简体字版由O’Reilly Media, Inc.授权人民邮电出版社出版。未经出版者书面许可,对本书的任何部分不得以任何方式复制或抄袭。

版权所有,侵权必究。


本书全面讲解了使用HTML5和CSS3开发优秀网站和Web应用的技术。

本书总共分为14章,其内容包含移动开发环境的设置,HTML5的元素、语法和语义,使用JavaScript来构建表单,探究应用于图像、音视频的HTML5媒体API以及AppCache、localStorage和其他API,CSS3选择器和语法以及更为深入的特性,响应式Web设计的特性,以及针对所有平台进行性能、用户体验和可靠性的设计。

本书适合具有一定经验的Web前端开发人员阅读。


O’Reilly Media通过图书、杂志、在线服务、调查研究和会议等方式传播创新知识。自1978年开始,O’Reilly一直都是前沿发展的见证者和推动者。超级极客们正在开创着未来,而我们关注真正重要的技术趋势——通过放大那些“细微的信号”来刺激社会对新科技的应用。作为技术社区中活跃的参与者,O’Reilly的发展充满了对创新的倡导、创造和发扬光大。

O’Reilly为软件开发人员带来革命性的“动物书”;创建第一个商业网站(GNN);组织了影响深远的开放源代码峰会,以至于开源软件运动以此命名;创立了Make杂志,从而成为DIY革命的主要先锋;公司一如既往地通过多种形式缔结信息与人的纽带。O’Reilly的会议和峰会集聚了众多超级极客和高瞻远瞩的商业领袖,共同描绘出开创新产业的革命性思想。作为技术人士获取信息的选择,O’Reilly现在还将先锋专家的知识传递给普通的计算机用户。无论是通过书籍出版,在线服务或者面授课程,每一项O’Reilly的产品都反映了公司不可动摇的理念——信息是激发创新的力量。

业界评论

“O’Reilly Radar博客有口皆碑。”

      ——Wired

“O’Reilly凭借一系列(真希望当初我也想到了)非凡想法建立了数百万美元的业务。”

      ——Business 2.0

“O’Reilly Conference是聚集关键思想领袖的绝对典范。”

      ——CRN

“一本O’Reilly的书就代表一个有用、有前途、需要学习的主题。”

      ——Irish Times

“Tim是位特立独行的商人,他不光放眼于最长远、最广阔的视野并且切实地按照Yogi Berra的建议去做了:‘如果你在路上遇到岔路口,走小路(岔路)。’回顾过去Tim似乎每一次都选择了小路,而且有几次都是一闪即逝的机会,尽管大路也不错。”

      ——Linux Journal


Estelle Weyl是一位前端工程师,自1999年起就开发基于标准的无障碍网站。她写作的两个技术博客拥有数百万的访客,并经常在世界各地举行的技术会议上针对CSS3、HTML5、JavaScript和移动Web开发发表演讲。


本书封面的动物是大盘尾。这种独特的鸟类有一个显著的特点,就是它有延长的尾羽,这使得它在其亚洲栖息地很容易被识别出来。大盘尾的鸣声清脆悦耳,具有各种不同的叫声,可以模仿其他鸟类的叫声。

在森林茂密的地区,比如大盘尾通常生活的领域,大量的混合种群聚集在一起,有数百只之多,它们一起觅食。据信,大盘尾模仿其他鸟鸣的能力与这种觅食场景有关—大盘尾学习其他鸟类物种的警告声,然后进行重复。这种行为被比喻为一个人学习各种语言的简短有用的短语和感叹词。尽管非洲灰鹦鹉可以在正确的语境下使用人类的语言,但是它们从来没有在野外表现出这种情景依赖行为。相反,大盘尾是使用其语言能力的优势,通常模仿猛禽的叫声在觅食群体中制造一种恐慌,从而能够不被注意地偷取食物。

尽管在涉及领土时,大盘尾表现得相当具有侵略性,但是它们在求偶时会比较好玩。两个未来的伴侣相互对着歌唱,跳上树枝,从高处将物体扔下来,然后再从半空俯冲下来接住。在交配之后,它们就会搭建一个纸杯状的鸟巢,并在其中产下三四枚蛋。

大盘尾的生活领地包括喜马拉雅山的森林、米什米山以及婆罗洲和爪哇的岛屿。正因为如此,学者Edward H. Schafer认为大盘尾是佛教中提到的神圣的迦陵频伽鸟。这些神鸟在过去被认为有人类的脑袋和鸟的躯干,而且有很长的双尾和曼妙的声音。迦陵频伽鸟又被称为“美音鸟”或“妙音鸟”,这样的称呼使得具有声音天赋的大盘尾愈发引人注目。


我们将要学习如何开发移动Web应用。注意Web这个词,本书关注的是为移动设备(如Android、iPod、iPhone、BlackBerry和平板电脑)开发Web应用,而不是需要iOS或Android SDK进行的本地应用开发。本书讲解的知识与操作系统无关。

移动Web应用是使用了桌面Web应用的标记语言和可触控设备功能的网站或Web应用。Web应用无论是通过手机、平板电脑还是笔记本来访问,都是使用HMTL、CSS、JavaScript以及可选的图片、音视频资源和服务器端技术来构建的。

通过升级到使用新的HTML5、CSS3和JavaScript特性,我们可以创建出具有本地应用外观的Web应用。因移动Web应用是基于Web的,因此它们兼容于台式机、智能手机、平板电脑以及具有现代浏览器的其他设备。由于Web应用是基于Web的,我们可以直接将其分发给我们的用户,而不需要先在Apple App Store或Google Play中上架,也不用承受它们那复杂、昂贵而又冗长的审批流程。

本书讲解的内容可以帮助你使用CSS3、HTML5[1]和JavaScript创建能在浏览器中运行的应用。本书都是关于你已经知道的一些技术:那些能移植到大多数设备的技术。本书讨论的所有内容都与操作系统无关。

也就是说,我们将要学习的知识不仅可以工作在iPhone、iPad和Android设备上,而且可以工作在其他移动平台(其中包括Firefox OS和Windows Phone)以及现代的桌面浏览器或者具有现代浏览器的其他设备(比如Wii这样的游戏设备)上。尽管本书关注的是移动开发,但是所介绍的内容可以用在大量的大小设备上,只要设备带有一个遵循现在Web标准的浏览器即可。

应用程序在本地平台上的能力在10多年以来保持得相当稳定,但是在过去的最近几年,Web平台增强了处理Web应用的能力,使得Web应用几乎和本机上的应用一样。

iPhone增加了Canvas、应用缓存、数据库以及SVG。包含了这些特性的Safari 4.0,又增加了视频、音频和Web Workers。在2009年末,地理位置和Canvas特性不但增加到了iPhone上,而且在Chrome、Opera、Firefox、Internet Explorer和Android上也可以看到它们的身影。

借助于Web浏览器,多年以来我们已经能充分利用HTML、CSS、DOM、SVG和XHR。在本书中,我们将HTML5和CSS3技术囊括了进来:HTML5和CSS3可以用来构建与本地应用相匹敌的Web应用。

使用Web浏览器,很多年来我们已经能够充分利用HTML5、CSS、DOM结构、SVG和XHR。在本书中,我们进行横向扩展以包括HTML5和CSS3:能够用来构建可以与原生应用相匹敌的Web应用的技术,而且现代的移动浏览器和桌面浏览器均对其提供了支持。

你可以在App Store上销售本地iPhone应用,这听起来很酷。你也可以通过Google Play、Amazon以及其他在线平台销售本地Android应用。如果是基于Web的应用,你可以绕过应用商店的审批[2]流程[3],无须向其支付年费和销售费用,也不走它的销售市场,而是通过你的网站或者其他销售渠道直接将应用销售给你的消费者群体。如果你的应用是通过应用商店销售的话,则从成千上万的应用中脱颖而出的难度很大。而且,与本地应用相比,Web应用带来的好处远大于其开发成本。

Web应用的开发和迭代也很容易。只要你想,你随时可以对你的Web应用进行修改;如果需要,可以一天修改好多次。

我们以修改iPhone上的一个本地应用为例,你需要3周以上的审批流程。一旦你的应用被批准并上架之后,你不得不等待用户进行同步并更新他们的应用。而使用CSS3和HTML5开发的Web应用,你所做的修改基本上是实时的,而且用户在离线状态下也可以访问——如同本地应用那样。

如果你本地应用的字幕名单中因为疏忽而没有包含你老板的名字,或者是拼错了你母亲的名字,这些事情将会一直折磨着你,直到你通过应用商店进行了校正推送,但是除非用户通过iTunes下载并同步更新了你的应用,否则这些问题将一直存在。而这可能需要很长的时间。

 

我很善于成为“过时的”,我从不将我的iPhone上的Bump、Twitterfic和Gowalla进行升级。我想我应该不是唯一拥有“古董级”iPhone应用的人。不要假设使用本地应用的用户会升级他们的应用。

通过使用HTML5开发的Web应用,在离线状态下也可以使用,就如同本地应用那样。尽管本地应用需要数周时间来更新,但是可以将Web应用强制为下次在联网状态下使用时进行更新。第6章在讲解离线应用时会讲到这一点。

HTML5 Web应用的开发利用了你已经知道的HTML和CSS技能。我们将在你现有的技能上进行开发,而不是让你学习全新的技术、全新的平台以及只能在一个平台上使用的全新语言。

使用HTML5和CSS3的浏览器标记,你可以构建跨平台的应用。本地的iPhone应用可以在iPod touch和iPhone上运行,而且大多数iPhone应用可以在iPad上运行,但是却不能在Windows、BlackBerry和Android上运行。本地Android应用只能在Android设备上运行,而不能运行于iOS设备。本地Google TV应用也不能在iOS设备上运行。与本地应用不同,你的HTML5/CSS3 Web应用可以在WebKit、IE10、Blink、Opera Mobile(而非Opera Mini)和Firefox Mobile浏览器上。而且只要设备上安装了现代浏览器,而且默认支持HTML5和CSS3特性,你的Web应用就能在这些设备上运行。

使用HTML5和CSS3开发的大多数Web应用,已经能在现代浏览器上运行。但是Internet Explorer 8以及更早的版本还不支持,而Internet Explorer 9只支持部分HTML5和CSS3。Internet Explorer 10在支持这个不断发展的规范方面还是路漫漫。

自从iPhone SDK在2008年发布以来,iPhone大多数应用是作为本地应用创建的。但是在SDK发布之前,则只有Web应用。由于HTML5尚未就绪,人们只能从Web应用转向本地应用。现在移动浏览器已经能够支持很多HTML5 API,因此我们也就可以开发快速的、具有视觉吸引力的响应式Web应用了。

使用HTML5和CSS3开发Web应用的最后一个理由是支持视频!iPhone、iPod和iPad都不支持Flash,而且也不打算支持。但是,安装有Safari WebKit浏览器的所有iOS设备都支持HTML5 <video>元素,这将在第5章讲解。

随着与标准兼容且具有前瞻性思维的浏览器的扩散(手持设备为其扩散提供了助力),我们现在终于有机会将Web开发这门学科带入21世纪。

在学习本书时,希望你能够忘记Internet Explorer的所有旧版本。Web是向前发展的,而且发展速度相当快。你是否会因为IE6、IE7甚至IE8而拒绝学习和使用CSS3和HTML5呢?这些旧的浏览器不会出现在移动设备上,它们在台式机上的受欢迎程度也在下降。不要迟疑不决了!

由于与标准不兼容的传统浏览器依然普遍存在(最知名的是IE6到IE8),Web开发人员受限于此,无法开发出强大的网站。向IE6和IE7的妥协迫使我们只能使用过时的代码,这使得我们在实现高级的旧标准以及不算太新的建议标准时诚惶诚恐。在本书中,我们将学习所有可以使用的技术,因为我们没有必要去迎合已经过时的浏览器。

在学习本书时,要从HTML5和CSS3的角度出发。不要总是想“哦,这可能在某某浏览器中不工作”,而是要想“这太棒了”。通过学习这些技能和语法,当所有的浏览器最终支持这些较新的特性时,你已经领先别人很多。在学习本书的同时,你也将学到一些主要的技巧,并且能够创建强大的Web应用。

Safari、Chrome、Firefox、Opera和IE10(包括它们的桌面版和移动版)都支持现代的Web标准,其中包括HTML 4.01、XHTML和部分HTML;CSS 2.1和部分CSS3;JavaScript(包括AJAX技术)和DOM Leve 2模型。在这场游戏盛宴中,Windows起步虽晚,但是新出的手机支持HTML5。你曾经记得有人在2010年购买了Windows手机吗?直到2012年2月,当我在一个会议上询问“谁用的是Windows手机”时,有人回答“我的是”。现在,Windows手机正在变得越来越受欢迎。当然,我们不是要迎合旧式的“Windows Mobile”,而是那些购买了新款Windows手机的人。

本书关注的是为移动浏览器设计和开发网站,为我们提供机会来使用最前沿的Web技术。我们已经确定不再考虑过时的浏览器,而且我希望我的网站和Web应用能够在所有的浏览器上正确地呈现出来(虽然不一定要在所有的浏览器上都一样)。我猜你也是这样想的。在涉及相关内容时,我们会简要介绍在其他常见的非移动浏览器中处理特性的提示和技巧。

2007年6月,在第一代iPhone上市的一周内,加州旧金山就举行了第一届iPhoneDevCamp。在iPhone最初发布时,还没有可用的SDK。因此,最初所有的iPhone应用都是基于Web的。

在iPhone最初发布时,iPhone操作系统的功能远没有今天市场上的手机那么强大,当时用的是EDGE网络,下载速度慢得要死。鉴于这些限制,人们在开发应用时主要关注的是,要确保应用的图片小于10KB,JavaScript代码小于10KB,而且能适应下载速度为10KB/s的网络。

在第一届iPhoneDevCamp上,参与人员自行开发了文档,旨在相互帮助,从而获得开发出有趣的(基于与Web的)iPhone应用的技能。最初,也没有默认的onOrientationChange事件。相反,我们添加了一个计时器来定期检查手机的朝向,并基于返回的值使用JavaScript来切换CSS类。

在iPhone发布的第一个周末,Joe Hewitt为iPhone编写了第一个JavaScript和CSS库iUI,并将其与在场的开发人员进行了分享。Joe、Nicole Lazarro和另外三位开发人员创建了第一个iPhone程序Tilt,这个程序使用了iPhone的运动感知能力。Dori Smith开发了一个纯JavaScript iPhone游戏iPhone Bingo。Richard Herrera、Ryan Christianson、Wai Seto和我开发案例Pickleview,这是一个Twitter/职业棒球大联盟AJAX混搭(mash-up)应用,它允许用户观看任何棒球比赛并发布与比赛相关的推文。这是一种解放:这是我第一次使用了多重背景图片、边框图像,CSS选择器和不透明度,而不用担心为大量的浏览器、浏览器版本和操作系统提供支持。

在iPhone发布的前9个月内,只有Web应用以及Apple控制的本地应用:除了Apple之外,再也没有本地的iPhone应用开发。由于带宽限制和Apple开发人员文档的缺乏,iPhone Web应用的量并没有扶摇直上。而且由于iPhone WebKit Safari浏览器无法访问iPhone OS的原生特性,因此针对iPhone的Web应用开发并不成功。随着SDK的发布,iPhone应用开发开始蓬勃发展。

iPhone SDK是2008年3月6日首次发布的。iPhone SDK允许第三方开发人员针对iPhone(以及后来的iPod touch和iPad)开发应用,并且可以访问2008年7月推出的App Store。随着SDK的发布、App Store的开张以及开发人员可以在App Store上销售自己开发的应用来赚钱,针对iPhone的开发迅速全面地转移到构建本地iPhone应用上来。

自从SDK发布以来,针对iPhone应用的开发就主要是以开发本地iPhone应用为主了。但是我们将改变这个局面。在2008年,Web应用相较于本地应用的限制打消了开发Web应用的积极性,具体如下所示。

Web应用的缺点(2008年):

但是,在2013年,情况发生了转变。开发Web应用与开发本地应用的争论发生了逆转,具体如下。

Web应用的优点(2013年):

本地应用的缺点(2013年):

HTML5[4]已经筹划了多年,自从2004年起就开始发力,当时它的名字还是Web Application 1.0。尽管还没有最终确定,但是其中有些部分已经相当完备,而且得到了现代浏览器的支持(通常情况下是完全支持)。现代浏览器(又称为A级浏览器)包括Safari、Chrome、Internet Explorer 10+、Firefox和Opera。IE8以及更早的版本则不在此列。IE9部分支持HTML5,但它是一款抑制了Web发展的浏览器。尽管并非所有的浏览器都支持HTML5,但是所有的WebKit/Blink浏览器、Opera Mobile[5]、Firefox OS和新款的Windows手机都支持HTML5。现在是开始使用HTML5的最后时间了。

HTML5是一个描述了新的Web API标准的总称,其中有些标准是HTML5规范中的(比如拖放),有些则不是(比如地理位置)。

借助于HTML5和相关的API,我们不再局限于本地应用的开发。鉴于HTML5和相关API的规范太长,本书不会讲解所有的图形,但是会涵盖一些你今天可以拿来使用的特性,比如下面要讲解的主题。

HTML5提供了一些新的标签,用于对标记语言中的标签(tag)或区段(section)进行逻辑分组。在定义你的网站架构时,从语义角度进行分组,而不是使用非语义的<div>和<span>元素来定义页眉、页脚、导航等内容,会对搜索引擎更加友好。第3章将讲解新的分组元素。

Web上有数百万的表单,而且每个表单都有大量的脚本来验证电子邮件、创建弹出式日历,从而确保在提交之前表单上填充了必要的元素,并在表单元素接收到焦点时清除占位符文本。借助于HTML5,我们不再需要使用JavaScript验证表单。在HTML5中,表单元素已经对定义数据类型的新特性和方法进行了更新。

第4章将讲解一些修改后的表单元素,学习如何创建本地滑动条、占位符文本和日期选择器以及验证邮件地址,从而确保填充了所有的必填字段,以及能够基于输入类型来显示自定义的键盘——这一切都不需要JavaScript。

借助于HTML5,图片再也没有必要非得嵌入在对象中了。HTML5添加了两个本地HTML5元素<svg><canvas>,它们使用CSS进行了增强,而且可以通过DOM进行访问。通过添加这两个元素中的任何一个,浏览器将在你可以采用程序方式进行绘制的地方提供一个空白的画布。第5章将讲解<svg><canvas>

到目前为止,所有的浏览器视频和音频都需要插件。通过使用HTML5,我们可以对视频和音频提供本地的浏览器支持。而且视频和音频都可以通过脚本来处理。HTML5浏览器原生地支持webM和mp4格式。借助于DOM,你可以控制视频和音频,比如静音、快进和停止。借助于CSS,你可以对播放器进行样式化处理。尽管iOS设备从来不支持Flash和Silverlight,但是所有的移动浏览器都支持HTML5视频和音频。第5章将讲解<video><audio>

地理位置并不是HTML5规范的一部分,作为一个相关的API,它是一个非常有用的模块。地理位置API可以用来识别移动设备和桌面设备的地理位置。第6章将讲解地理位置API。

手机是移动设备,这一点是显而易见的。Internet服务在手机上进进出出(尤其是注定要使用AT&T的用户)。HTML5应用缓存、本地存储和数据库API可以使得在你的手机离线时,仍然可以使用Web应用。第6章将讲解让你的应用能离线工作的API。

第6章还会简单讲解微数据、ARIA和Web Workers。尽管微数据在你的网页或Web应用上没有视觉或功能上的效果,但是你可以使用微数据将机器可以读取的语义添加到内容中,以便让搜索引擎爬虫找得到。ARIA(Accessible Rich Internet Application,无障碍富Internet应用)在你的内容上也不具备视觉效果,但是它通过提供属性来解释被劫持元素的角色和功能,从而提供更好的可访问性。所谓被劫持元素,指的是用来传递信息“这不是元素的默认用法”的元素。我们也将简单介绍Web Workers,它可以使得我们在不阻止UI线程的情况下,使用额外的JavaScript线程来运行密集的JavaScript。第6章是令人振奋的一章。

CSS3提供了一些伟大的新特性。第7章将要介绍的CSS3选择器提供了在页面上突出显示每一个元素的方法,而且不需要添加一个类,也不需要包含媒体查询来启用响应式Web开发。RGBA和HSLA是新的alpha透明度颜色值,它们以及其他的值类型将在第8章讲解。对于设计师和原型设计师来说,第9章和第10章将是本书的重点所在,讲解了CSS3的特性,具体如下:

Web字体让你能够使用那五六个传统的Web安全字体之外的字体。不同的浏览器有不同的实现,其中包括对iPhone和桌面端的支持不同。尽管所有的智能手机浏览器都支持@font-face,这是一种无衬线字体(Helvetica、Roboto或操作系统的默认字体都是),在针对移动端进行开发时可以考虑这种字体。我不鼓励移动用户下载巨大的字体文件,而是建议大家使用第11章介绍的小图标字体。本书不会大范围介绍Web字体。如果你对桌面端的Web字体很有兴趣,在在线章节资源中有一个链接指向我写的一个教程。这些资源可通过http://www.standardista.com/mobile访问,其中包含了指向外部资源、代码示例的链接以及本书引用的所有链接。

在桌面浏览器中,大多数人使用鼠标和键盘导览一个固定的(stationary)网络,在手机和平板电脑上,我们使用手指来导览网络,会旋转、晃动、触摸和敲击设备,但是我们不会(也不能)单击任何东西。与使用鼠标进行导览的准确性相比,即使用户瘦骨如柴,其手指还是大了很多。由于移动端具有相对较小的屏幕,而且通常用户的注意力持续时间较短,因此就用户界面以及有限的内容存放空间来说,需要有不同的考量。

平板电脑通常是在家通过WiFi或其他无线接入点使用的。手机也可以使用这些相同的接入点,但是通常会通过不一致且受限的共享服务接入Web。它们的屏幕都很小,存放开发者工具栏的空间有限,也没有足够的带宽来下载相当大的JavaScript库和图片。

第11章讲解了响应式Web开发特性。第12章讲解了设计考量。第13章讲解了移动端和触摸屏独特的事件处理程序。第14章讲解了移动端性能、调试和设备限制。

作为Web开发人员,我们一直被束缚在过去。过去12多年以来,我们一直在迎合浏览器。当你没有必要考虑跨浏览器的兼容性,而且无须受限于CSS2时,Web开发将变得令人兴奋。安装有高级浏览器的移动设备实施了前沿的技术。直接使用这些技术就好!

移动端打开了这个令人振奋的新世界。支持HTML5的WebKit在Android平板电脑、iPhone、OpenMoko、BlackBerry手机上均有相应的实现。除了BlackBerry、Android和iOS设备,WebKit还是Bolt、Dolphin、Ozone和Skyfire浏览器的引擎。Firefox、Opera和IE在手机上也四处可见,基于Presto的高级Opera浏览器也安装到了大量的非计算机设备上。Opera和Chrome正在向Blink移植。不久之后,每一个人在手机、电视、汽车甚至是冰箱中都会有一个完全成熟的Web浏览器。

现在,由于Internet Explorer不支持新标准和即将到来的标准,因此在桌面端我们感到力不从心。随着与标准兼容的浏览器的扩展,外加旧版本Internet Explorer的使用率在降低,我们很快就可以拥抱CSS3。在转向移动端时,我们可能会想起过去的CSS2限制。然而,我们现在有了新的问题需要处理:物理层面的限制。不是所有情况都适用同一模式。移动浏览器显然比桌面浏览器要小。

对于某些站点,你可能有一劳永逸的解决方案,但是大多数HMTL文件和CSS文档并不适合所有的浏览器尺寸。

取决于内容和设计的复杂程度,你可能需要为不同的媒介提供不同的HTML和CSS。

有时,你能够临时隐藏一些内容。在其他时候,你可能想提供更小的标题和更小的图片。你可能还想在宽屏幕上放置多列布局,而在手机上放置单列布局。你可能还想根据设备的尺寸来修改外观:例如,为了易读性而在桌面版上呈现三列布局。在移动领域,将这些列进行垂直布局会更行得通。

移动Web设计的宗旨是保持简洁。你只能使用手机提供的那点小屏幕。滚动的情况只适用于较长的文章,而不能在主页面和导览页面中出现。

你可能想要为站点的移动版本提供单独的标记。但这没有必要。除非你创建了一个真实的Web应用,而不是一个简单的网站,否则没有必要这样做。

通过移动设备接入Internet在过去被认为是只有大忙人才需要的。是的,有些移动浏览器用户访问Internet只是为了迅速查找特定的信息。他们可能会查看在线购物清单、查找一个砂锅的成分,或者是试图找到只需5分钟就可以走到的最好的意大利餐馆。

尽管用户当前可能对食品供应商的公司架构不感兴趣,但是当他们在查找这些信息时,他们很有可能会通过移动设备进行查找。当我们在台式机上执行这样的深入研究时,更多的用户只能通过移动设备访问Internet。

或许你的普通移动用户只是想获得一个地址、电话号码或者一个状态更新,并不想删除、重新组织、编辑或研究iPhone手机上的资料。但是有用户可能会这么做,因为移动设备可能是他唯一的计算机。所以,在确保所有必要信息能被轻易访问的同时,还要确保在必要时,用户能够在手机的屏幕上执行能在宽屏显示器上执行的所有任务。

你可能还会想到可用性。触屏设备使用手指(而非鼠标)作为输入设备。而手指要比鼠标的光标更大。因此,对于触屏设备来说,要操作的目标需要足够大而且相互之间有适当的间距。第13章将讲解触屏设备用户界面的变化。

非表象性的(non-presentational)图片应该从移动设备标记中删除:图片通常是针对桌面端而非移动设备优化的。在移动设备中,当物理资源有限而且网速较慢、带宽较贵时,这些图片将消耗应该为内容保留的相应资源。只有当图片是上下文相关的时,才应该包含内容图片,但是对于用作装饰性的图片,要使用背景图片或将其删除。

第1章讲解了开发环境的设置,并讨论了书中用到的几个例子。

第2章到第6章讨论了HTML5中的新增内容,还讲解了编写语义标记以兼容所有现代浏览器(包括桌面端和移动端)的最佳实践。我们还讲解了HTML5中新增的语义元素、Web Forms 2.0以及几个HTML5 API和相应的API(比如地理位置)。我们还提及了SVG、Canvas、Web表单、视频、音频、AppCache(应用缓存)和数据库、Web Workers。

第7章到第11章讲解了CSS3中已有和将要有的内容,包括新的颜色类型、阴影、边框图像、圆角和动画等。你将掌握为移动端和桌面端现代浏览器创建精美Web应用所需的所有工具。第11章重点讲解了响应式Web设计的特性。

第12章到第14章关注的是移动平台,包括触摸事件、用户体验式合集、移动性能考量。这些章节涉及的内容可以用来确保站点的性能、用户体验以及Web页面在所有平台上的可靠性。

我们的目标是为移动端开发卓越的网站。为了方便开发,我们应该在桌面端浏览器中开发站点,但是要时刻记得是为移动端设计和开发网站。然后,通过少量的修改,我们的网站看起来应该相当不错,而且能够在几乎所有平台上执行。我们的目标是开发能够在手机上运行的Web应用,而这是通过创建能在所有现代浏览器上运行的Web应用来实现的。

 提示

这个图标用来强调一个提示、建议或一般说明。

 

 警告

这个图标用来表示一个警告或注意事项。

本书每一章用到的资源可以通过http://www.standardista.com/mobile获取。你可以在这里找到指向外部资源、代码示例的链接以及本书引用的所有连接。

本书旨在帮助读者完成工作。一般而言,你可以在你的程序和文档中使用本书中的代码,而且也没有必要取得我们的许可。但是,如果你要复制的是核心代码,则需要和我们打个招呼。例如,你可以在无须获取我们许可的情况下,在程序中使用本书中的多个代码块。但是,销售或分发O’Reilly图书中的代码光盘则需要取得我们的许可。通过引用本书中的示例代码来回答问题时,不需要事先获得我们的许可。但是,如果你的产品文档中融合了本书中的大量示例代码,则需要取得我们的许可。

在引用本书中的代码示例时,如果能列出本书的属性信息是最好不过。一个属性信息通常包括书名、作者、出版社和ISBN。例如:“Mobile HTML5, by Estelle Weyl (O’Reilly). Copyright 2014 Estelle Weyl, 978-1-449-31141-4.”

在使用书中的代码时,如果不确定是否属于正常使用,或是否超出了我们的许可,请通过permissions@oreilly.com与我们联系。

如果你想就本书发表评论或有任何疑问,敬请联系出版社:

美国:

O’Reilly Media Inc.

1005 Gravenstein Highway North

Sebastopol, CA 95472

中国:

北京市西城区西直门南大街2号成铭大厦C座807室(100035)

奥莱利技术咨询(北京)有限公司

我们还为本书建立了一个网页,其中包含了勘误表、示例和其他额外的信息。你可以通过如下地址访问该网页:

http://oreil.ly/mobilehtml5_le

关于本书的技术性问题或建议,请发邮件到:

bookquestions@oreilly.com

欢迎登录我们的网站(http://www.oreilly.com),查看更多我们的书籍、课程、会议和最新动态等信息。

Facebook: http://facebook.com/oreilly

Twitter: http://twitter.com/oreillymedia

YouTube: http://www.youtube.com/oreillymedia

感谢Bruce Lawson、Adam Lichtenstein、Jennifer Hanen、Tim Kadlec、Jeff Burtoft、Tomomi Imura和Justin Lowery。

Bruce Lawson与他人合著了第一本HTML5图书——Introducing HTML5(New Riders出版)。他还是HTML5Doctor.com的创始人之一,以及W3C Mobile Web Best Practices Working Group(移动Web最佳实践工作组)的成员。他推广了Opera的开放Web标准,Opera是最古老的一家浏览器厂商,其移动端、桌面端、电视端和嵌入端浏览器在全球有3亿的用户量(参见www.opera.com)。大家可以在Twitter上通过@brucel加他关注,也可以通过www.brucelawson.co.uk获悉他的动态。

Justin Lowery创建了CubeeDoo的界面。他在其公司Cerebral Interacive担任UX架构师,擅长Web和移动应用的设计与开发。他从2001年起就是一名平面设计师了,从2006年起以Web开发人员的身份涉足Web开发领域。他还是一名护理信息师(informatics nurse),这个角色使得他可以将当前的关注点更好地放到健康教育领域中具有革命性的信息技术上。大家可通过@cerebralideas或www.cix.io获悉他的动态。

Adam Lichtenstein是一位前端开发人员以及OOCSS/Sass重度爱好者。他是FormFace的创始人,该站点关注的是HTML5论坛的语义构建和样式化。他目前是Wufoo公司的一名前端开发人员兼设计师,正在写作第一本有关前端开发的图书。当不写代码时,他的主要爱好是思考与编码相关的事情。大家可通过@seethroughtrees或http://seethroughtrees.github.io获悉他的动态。

Jenifer Hanen是一位移动端设计人员、开发人员以及摄影师,让每个人像她那样深深爱上移动端是她的追求。在1996年,Hanen为一个朋友的乐队开发了她的第一个公共网站,从2000年开始承担移动端和Web端的咨询工作,同时还是一位辅助Web设计和艺术史教授。大家可通过@msjen或http://blackphoebe.com/msjen获悉她的动态。

Tomomi Imura是一位开放Web拥护者兼移动端的前端工程师。在移动开发领域未成气候之前,她就活跃于这个领域了。她曾经为Yahoo! Mobile开发过移动Web、平台UI/UX以及框架,还在Palm参加了webOS的开发,之后她加入Nokia,与W3C一起工作,开始布道HTML5。大家可通过@girlie_mac或http://girliemac.com获悉她的动态。

Jeff Burtoft是Microsoft公司的一位HTML5布道者,还是JavaScript/HTML5社区的一位狂热的支持者。Burtoft先生强地支持Web标准,并且喜欢所有的编程语言(只要它们与JavaScript相关)。此外,他还是HTML5 Hacks一书(O’Reilly Media出版)合著者以及html5hacks.com博客的创始人。他与妻子以及三个孩子住在得州南部。大家可通过Twitter账户@boyofgreen加他关注。

[1] 我们将使用术语HTML5来指代“HTML:现实中的标准”。

[2] Apple实际上会对应用进行审核,确保应用中没有色情图片、成人暴力等内容。但是,含有可爱暴力(cute violence)的应用却能通过审核,所以,如果你想在应用中包含暴力,可以考虑是针对儿童的可爱暴力。

[3] 要将你开发的本地iPhone应用提交到App Store,你需要为Apple支付“开发人员年费”,而不论你的应用是否大获成功或者是否通过审核。

[4] HTML5已经成为了一个统称。HTML5只是HTML5“统称”的一个组件。Bruce Lawson曾经建议将这个大型的统称命名为NEWT(New Exciting Web Technologies)。我觉得这个术语很愚蠢,但是我喜欢这个术语的吉祥物。

[5] Opera Mini对HTML5的支持并不好。它是一种不同类型的浏览器——代理浏览器——为了降低带宽的使用率,它刻意具备有限的特性。Opera Mini通过Opera的服务器来请求页面,后者先对其进行处理和压缩,然后再将页面发送给手机,从而显著地降低了需要传输的数据量。这个预处理过程使得页面即使不是针对手机设计的,也可以很好地兼容Opera Mini,但是对网站的交互性和功能进行了限制。


如果你跟我多少有点类似的话,你肯定已经痛恨旧版IE浏览器很多年了。那些浏览器满是失败。然而,它们在整个生命周期内在任何地方失败的方式是一样的[1]。我们都知道IE6非常糟糕,但是它糟糕的方式是一样的。一旦我们搞清楚了如何填IE6的坑(polyfill[2]),我们就已经把它搞清楚了。

在移动世界,我们同样面临一些问题,不同的是这些问题以一种更新、更多样化且不断变化的方式存在。在不同设备上的不同浏览器版本可能支持很多新的特性,但实现方式可能不同。或者说,它们可能确实支持某个特性,但是这个特性可能并用不了。举个例子,一个现代浏览器可能支持也可能不支持localStorage。支持localStorage的设备可能允许也可能不允许对其写入。即使浏览器允许从localStorage读取数据,但这个读取操作可能非常耗时从而阻碍了性能。并且,即使浏览器通常情况下允许你对其写入,但localStorage本身可能已经达到了存储上限。

我们在这里无法涵盖所有操作系统和设备上所有浏览器的全部非标准情况(quirk)。即使我了解所有的这些非标准情况(而且我也不了解),这些非标准情况可以装满一个大部头,并且在我完成这个大部头之前它就过期了。这本书呢,实际上也过期了。浏览器支持以及规范等周边环境都在不断发生变化。没有办法制作一本最新的书出来,因为到其交付印刷之际——或者甚至在你刚完成一章的时候——周边环境已经变了。虽然某些浏览器、特性、电话以及提到的网站可能已经过时了,但本书带出的最佳实践在未来几年还是有意义的。本书的一个指导原则是:如果你采用最佳实践,并且依照标准编写代码,你的代码将能够在当前及以后所有的设备上运行。

我把针对特性的浏览器支持包含在内了,而且也没有缺少针对浏览器特性的支持,因为所有的浏览器将沿着正确的方向前进正是大家所期望的。今天在浏览器中的那些非标准模式(quirk)明天也许就解决了。

基于以上原因,在使用一个特性时,你不仅确实要做特性检测,而且需要进行测试以确保能够成功地使用这些支持的特性。

本书将使用与设备、操作系统以及浏览器无关的标记并且不使用JavaScript类库。我选择不使用类库仅使用普通JavaScript进行编码以确保你学到真正的代码。通过使用普通JavaScript编码,希望就不会存在一个方法到底属于原生方法还是框架提供的方法这样的困惑了。

但这不意味着你不应该使用类库。恰恰相反!开源类库是弄清楚浏览器不标准情况的最佳选择之一。开源项目拥有成百上千甚至成千上万的贡献者。这些成千上万的贡献者们密切地在大量的设备上进行开发和测试,他们找出那些不标准的情况,报告问题,并且给类库提交修正来处理这些情况或者提供解决方法和腻子脚本。这成千上万双眼睛同时也在报告bug,提醒浏览器厂商注意那些没有遵循标准运行的东西,以便这些bug可以在浏览器后续发布中得以修正。

流行的开源类库和HTML5 JavaScript API腻子脚本是快速发现各种各样的浏览器不标准情况及其解决方案的最佳资源。它们应被视为你的开发工具箱中的一个重要组成部分。即使你不使用它们,也一定要阅读这些源码来学习别人已经发现了的那些移动浏览器的bug。

在你阅读HTML5、CSS3以及相关的JavaScript API时,学习的最佳方法就是编写代码。让我们开始编码吧。

我学习HTML5和CSS3的方法是在一个单一的移动浏览器上构建一个Web应用,并将其发挥到极致。我初次涉足CSS3是在2007年iPhone首次上市的周末写的一个结合了Twitter和美国职业棒球大联盟的Web应用,叫作Pickleview。当时,iPhone上的Safari浏览器是市场上最先进的浏览器(也许是除了Opera之外的)。通过只为一个单一的浏览器开发这个应用,我无须担心IE6、IE7或是Firefox 2的问题(Chrome当时还不存在[3])早在2007年的时候,这就是当时网络的状态。

在2010年,我又做了一遍在一个单一的浏览器上使用最现代的HTML5和CSS3编写代码的练习。我和一些朋友们使用动画、存储、离线能力以及所有在桌面版的Chrome 12中支持而在移动版Safari 3.1中不支持的新特性设计了一个记忆游戏。通过使用一个单一的浏览器以及利用我能够使用的所有新技术,我能够学习编写新的但是因为需要支持陈旧的浏览器而无法在生产中使用的HTML5、CSS3以及JavaScript模块。截至2010年,有的浏览器自2007年以后已经有了很大的进展。其他的(IE——你知道我这里说的就是你)就没什么了。

在2013年,大多数的浏览器支持HTML5和CSS3。作为开发人员,我们正受困于不得不支持旧的桌面浏览器,也就是IE9及其更早的版本。在移动上,我们有我们自己的“IE6”。我们在某种程度上受困于功能型手机[4]和运行Android 2.3的智能手机。但即使是功能型手机浏览器和Android 2.3都支持很多新特性。

要学习编写HTML5、CSS3以及相关的JavaScript API,就要暂时地不去考虑旧的浏览器。我们将一起学习使用这些新技术都能做什么。大多数在现代浏览器中获得了广泛支持的特性,我都已经放到本书的代码示例中了。

CubeeDoo,如图1-1所示,是一个完全使用前端代码编写的记忆游戏。在本书中,我使用的代码示例都将来自于这个游戏以及一个原生iPhone“设置”应用的翻版(如图9-3所示)。该游戏使用HTML5元素构建,其中的一些主题包括使用生成的内容匹配图标。CSS转换、过渡和动画以及渐变、圆角和其他CSS特性都被用于设计游戏的外观和感觉。该游戏也使用SVG、JSON、虽然已过时但却是移动平台支持的webSQL、localStorage、sessionStorage、数据属性(data attribute)、HTML5表单、音频、媒体查询(media query)和数据URI(data URI)。

本书中的代码没有使用任何形式的框架。正如前面提到的,一切都是使用普通的JavaScript、HTML5和CSS手工编写代码的。目标是教给你真正的API,而不是腻子脚本。

在生产中,你可能希望使用腻子脚本,但是要想巧妙地使用这些脚本,你需要理解这些腻子脚本都做了什么。这本书就是要教你这些。

本书涵盖了CSS3、HTML5以及相关的API。重点是在移动的环境下学习这些技术。我们生活在一个移动的世界里,但是并不存在所谓的“移动互联网”。不过都是互联网罢了。但是如果你只聚焦于桌面,你所设计的互联网版本可能无法正常服务于日益增长的仅从移动设备访问互联网的人群。而且,如果你只聚焦于桌面,你将只会对较旧的IE浏览器版本的共同标准感兴趣。

图1-1 CubeeDoo记忆游戏截屏

永远不要把一个仅在单一浏览器下正常运行的应用推向生产环境。然而要学习那些新兴技术,忽略掉“旧的”浏览器才可以给自己提供机会去学习去挑战自己,跳出框框进行思考,最终达到巅峰。带上在本书中学到的东西,使用一个单一的浏览器,编写程序直到浏览器能做的极限。不断尝试。你会再一次爱上Web开发的。

你只需要一个浏览器、一个IDE以及一些时间。

在开始开发第一移动Web应用之前,你需要使用最好的“吃饭的家伙”来设置你的开发环境。好消息!你已经有这些工具了。

跟随本书学习,你只需要一台装有文本编辑器和浏览器的电脑。你甚至都不需要一部电话,虽然拥有一个移动设备将会很有帮助。

你应该使用一个纯文本编辑器或是一个集成开发环境(IDE)进行开发。IDE软件通常包括文本编辑器、调试器以及其他功能或者插件,例如你完成工作可能需要的FTP。人们都有自己首选的IDE。无论什么,选择适合你的就好。我自己的首选是Sublime Text,但是你可以使用TextMate、DreamWeaver、Eclipses、WebStorm或者无论什么你满意就好。虽然我们只需要一个文本编辑器,但是你会发现使用IDE可以帮助我们组织并简化开发过程。我建议你选择一个IDE并且成为它最好的朋友。IDE是非常强大的工具,它使开发过程变得非常愉悦——甚至接近完美。

你还需要一个浏览器,我倾向于使用Chrome金丝雀版(Canary[5])进行开发,它是Google Chrome浏览器的测试版。我倾向于该浏览器是因为它的调试器。所有的现代浏览器都有调试器,但是Chrome的调试器是其中的佼佼者,而且金丝雀版的调试器可以让我详细了解和访问所有新的额外特性和附加功能,甚至是在它们进入浏览器正式发布之前。

如果你没有一台苹果电脑,你就无法轻松地开发原生iPhone、iPad或者iPod touch应用。如果你没有Windows 8,开发正式名称为Metro风格的应用也将很难。别担心!就我们正在学习的内容而言,你只需要一个现代浏览器。操作系统或设备都无关紧要。你可以在Windows、Unix、Android手机和平板设备以及Mac等只要你能说得出名字的其他平台上测试本书的所有示例。

IDE和桌面浏览器将是你进行移动Web开发的主要工具。整个开发过程中,移动应用将在桌面浏览器中预览和调试。有一些特性桌面浏览器将无法仿真,包括移动渲染精度、JavaScript性能、内存和带宽限制以及API的可用性。然而,使用其他工具和通过直接在真实或虚拟的设备上进行测试,这些差异是可以被克服的。

虽然你将在你最喜欢的浏览器上愉快地开发,但你的工具箱里还是应该有多种其他可用的浏览器用于测试。你可能需要使用IE,这样可以更简单地测试Windows Phone环境。Safari或Google Chrome将使你能够测试Android、Bada[6]、Blackberry和iOS。你可能还需要Firefox来测试Gecko设备。为了测试所有运行Presto渲染引擎的设备,目前还需要Opera,但是由于Opera Mobile 14是基于Chromium的,而且最新的Opera和Chrome都使用Blink[7],所以你开发所需的浏览器需要进行更新以符合开发所处的环境。

如果你还没有这样做的话,如果你使用Mac的话就下载一个Safari浏览器,如果你使用Windows的话就下载一个最新的IE浏览器。同时在设备上下载Chrome、Firefox和Opera,即使你在使用UNIX。你还可以下载Chrome Canary、Aurora、Opera Next以及WebKit当日最新版(nightly builds)来测试这些主流浏览器的下一个版本。这些是在本书编写时流行的桌面浏览器,但环境是在不断地变化的。

浏览器本身就配备有开发工具。开发者工具(developer tools)是浏览器内置工具,使用户可以方便地审查(inspect)和调试代码。使用该工具,你可以针对实时(live)内容操作文档对象模型(DOM)、编辑和调试JavaScript代码、编辑和调试CSS、分析资源请求情况、审查Web内容和Web应用的性能。

开发者工具一般处于隐藏状态,因为除了开发人员之外的大多数用户不会用到这些浏览器特性。移动浏览器经常在设备浏览器中有一些调试功能。这些有限的调试工具通常可以通过设备的设置界面启用。虽然设备级别的调试可能是可用的,但在桌面电脑上通过一个功能更齐备的工具进行应用调试要更简单一些。

如果你一直在开发网站的话,不管你做了多长时间,很可能你已经对Firebug[8]、F12、Web Inspector或者DragonFly都比较熟悉了。Firebug是一个Mozilla扩展。F12、Web Inspector和DragonFly分别是IE浏览器、Chrome/Safari和Opera附带的。这些开发者工具都能够让你调试、编辑和监控网站的CSS、HTML、DOM和JavaScript,并使你可以对HTTP请求、本地存储以及内存消耗等方面进行分析。

Firebug可以从getFireBug.com网站获取。Safari的开发者工具可以在Develop菜单下找到,但是需要打开Preferences →Advanced菜单,然后勾选上“Show develop menu in menu bar”才可以使用。在Chrome中,我们可以通过View → Developer → Developer Tools菜单来打开开发者工具。

我们也可以使用Command-Option-I或者Control-快捷键来打开Chrome、Safari、Firebug以及Opera的调试器。F12和Firebug也可以通过键盘的F12打开。这些工具是浏览器上用于调试CSS、JavaScript和HTML的最佳工具。

你可能需要熟悉Web查看器(Inspector)、错误控制台(Error Console)以及用户代理切换器(User Agent Switcher)。这些调试器能够查看Web页面的CSS、HTML、JavaScript、DOM以及文件头。不管你是使用Web Inspector、Firebug、DragonFly、F12、开发者工具,还是使用这些工具的组合,都要了解你的调试工具。你的调试器将成为你的另一个最好的朋友。

很可能你已经有数年使用桌面应用浏览器调试工具的经验,所以我们不会在这里对它们进行深入探讨。然而,即使这些工具你已经使用5年了,你也有可能只是用到了这些工具的一些皮毛而已。我强烈建议你自己能够对它们进行深入研究,每个地方都用鼠标左键和右键点一下试试。我们将在第14章介绍开发者工具的时间轴(Timeline)标签。

移动视口(Mobile viewport)

要模拟移动视口,可以简单地改变桌面浏览器窗口的大小到你想要测试的移动视口的大小。桌面浏览器视口就是浏览器窗口。在移动设备上,视口是指你看到的部分,不一定是绘制到屏幕上的全部,但是改变窗口大小对于你想要做的大部分测试应该是足够了。

在你手动改变浏览器大小时,窗口的大小可能是随机的。在Settings窗口下的Overrides面板(如图1-2所示)中,Chrome开发者工具提供了一些预设的设备大小。点击开发者工具右下角的齿轮图标即可访问Web Inspector的设置窗口。

图1-2 Chrome开发者工具中Settings窗口下的Overrides面板

当从用户代理(User Agent)选择菜单选中一个设备时,Chrome就把它的用户代理切换成选中设备的用户代理,同时使用选中设备的大小在浏览器窗口中生成一个视口。这就提供了一个与所选设备的视口同等大小的浏览器视口。

如果你的设备没有被列在列表中,简单地在设备指标(Device metrics)下的两个输入框中输入设备的宽度和高度即可。单击设备指标右边的切换按钮即可在横向模式和纵向模式之间切换。尝试一下ScreenQueri.es网站可以预览准确的设备屏幕尺寸。你也可以启用触控事件(touch-event)仿真,或者使用thumbs.js作为触控事件的腻子脚本。

Chrome开发者工具也可以让你改写地理位置(geolocation)来仿真一个特定的经度和纬度,而且即使你的笔记本电脑装有陀螺仪,也可以仿真一个特定的设备朝向。

在你已经使用桌面式浏览器完成应用的第一阶段开发之后,你可能希望在移动设备上进行测试。在移动设备上进行测试的主要障碍在于无法再使用你已经在桌面电脑上逐渐习惯了的强大的查看器了。这就是为什么远程Web查看器(remote web inspector)是很棒的原因了。

有工具可以通过桌面浏览器来远程调试移动浏览器。远程调试器能够让桌面浏览器和外部设备进行通信,从而可以远程执行和捕捉代码。就像常规的调试器一样,使用这些远程调试器也可以查看HTML和CSS,操作DOM和进行实时修改,以及调试脚本。

Opera正在更换浏览器引擎。虽然我不知道将来会提供什么,但Opera自2008年以来一直支持通过桌面Opera Dragonfly调试器进行Opera Mobile浏览器的远程调试。能够远程查看HTML和CSS、更新DOM、加入断点(breakpoint),以及任何其他可以在桌面环境使用Dragonfly完成的事。

WebKi支持通过USB端口进行远程调试起始于Android 4和iOS 6。要使用Chrome 进行远程调试,我们要通过在命令行下使用命令标志(flag)来启动Chrome,而不是通过程序图标:

chrome.exe --remote-debugging-port=9222 --user-data-dir=remote-profile

或者

/Applications/Chromium.app/Contents/MacOS/Chromium --remote-debugging-port=9222

要调试Firefox移动浏览器,需要给Firebug添加Debug API,即以前的Crossfire扩展。

当然,现状总是在不断地变化和改善的。如果对这个议题很感兴趣,请保持关注并随时获取有关浏览器测试和工具工作小组(Browser Testing and Tools Working Group)的远程调试协议(Remote Debugging Protocol)的最新消息。

Android调试工具

Android SDK包含了用于构建、测试和调试Android应用所必需的API类库及开发者工具。我们可以直接使用自己的设备来调试Web应用,或者使用SDK能够创建的仿真器,如图1-3所示。

图1-3 运行在OS X上的Android 4.2.2仿真器

你可以从http://developer.android.com/sdk/下载Android SDK,这里提供了Android调试网桥(Android Debug Bridge,ADB)、调试、控制台监控(console monitoring)以及仿真器创建和启动等功能。

在下载包里,找到tool目录然后打开android可以进入adb。ADB提供了各种设备管理功能,包括移动和同步文件到仿真器,在设备或仿真器上运行UNIX shell脚本,并且提供了与已经建立好连接的仿真器和设备进行通信的通用方法。

你愿意的话,也可以使用一个名为ADB plug-in的Chrome扩展。该扩展可以运行一个ADB后台驻留程序,无须下载SDK即可实现移动远程调试。

同样在tools目录下,打开Monitor可以进入Android调试监视器(Android Debug Monitor)。监视器有一个可以用于调试应用的控制台(console),可以查看所有在网站中包含的console.log()的输出。如图1-4所示,所有的设备都被列在左边的设备面板中,同时底部是控制台日志。

图1-4 Android调试监视器

监视器打开以后,在Window菜单下有一个Android虚拟设备管理器(Android Virtual Device Manager),如图1-5所示。我们可以通过这个窗口来创新新的仿真测试设备并可以从这里启动它们,就像图1-3那样。

图1-5 通过Android虚拟设备管理器可以创建设备仿真器,虽然可供直接选择的设备数量有限,但可以无限制地创建自定义设备配置

weinre

Weinre是远程Web查看器(web inspector remote)的缩写,它是一个功能强大的远程调试工具,可以用来查看和调试JavaScript、HTML5和CSS。Weinre是PhoneGap项目的一部分;既可以在本地使用也可以使用debug.phonegap.com服务。Weinre同时也是Adobe Edge Inspect的基础,我们将在“Adobe Edge Inspect和Ghostlab”小节对其进行详细描述。

Weinre是一个远程调试器,可以让你把当前的移动浏览器窗口和一个远程WebKit查看器的精简版本联系起来。Wernre现在利用的是Node.js和WebSockets[9]

在本书写作之时,它是一个删减版的调试器。Weinre可以实时查看DOM和访问JavaScript控制台,但是没有断点或者堆栈跟踪(stack trace)功能。JavaScript控制台也无法像你希望的那样列出错误信息,所以调试就更加困难,不过还是能用。

使用weinre

Weinre可以通过Java或者JavaScript进行安装。要使用JavaScript进行安装,首先应下载并安装Node.js。Node.js本身包含了npm(node package manager,Node的包管理工具)。在命令行下输入:

npm –g install weinre

来安装weinre。通过在命令行下输入:

weinre

即可启动weinre。

默认情况下weinre服务器将一直运行在localhost:8080上,直到使用Control-C,电脑重启,或者服务被以其他方式中止(killed)才会停止。

要启用调试,需要使用下面的代码给应用程序中加上一个weinre脚本:

<script src="http://localhost:8080/target/target-script-min.js#anonymous">
</script>

在任何桌面环境的WebKit浏览器中,打开http://localhost:8080/client/#anonymous就可以访问调试器。查看器使用一个完整的浏览器窗口显示出来,看起来与Chrome的开发者工具非常类似,但是功能相对有限,而且标签页也要少一些。

在远程(Remote)标签页中,可以看到一列当前可以用于调试的移动浏览器窗口,这些移动浏览器窗口是与你的weinre脚本运行在同一个网络中的。元素(Elements)、资源(Resources)、网络(Network)、时间轴(Timeline)和控制台(Console)标签,如图1-6所示,都与它们在桌面式Web查看器中的样子很像。你也许注意到了,在这个删减版的调试器中没有源代码(Sources)、数据图表(Profiles)和审核(Audits)标签(虽然它们今后可能会被重新加进来)。

图1-6 Weinre调试器

Adobe Edge Inspect和Ghostlab

为了简化这些既定的调试过程,并且让前面这些步骤几乎能够自动化,Adobe Edge Inspect能让你以一种与weinre类似的方式进行调试,前者正是基于weinre构建的。这种简化和自动化的实现,是通过不知不觉地为你执行了启动服务、在浏览器中输入URL、给程序添加脚本等任务的方式。

你首先需要在所有的远程设备上安装Adobe Edge Inspect,同时在桌面环境上安装了它的Chrome浏览器扩展。只要你的测试设备和桌面环境都位于同一个网络中,就可以创建一个到设备的连接。

在移动设备中打开Edge后,Edge会提供给你一个验证码(passcode),只有把这个验证码输入到桌面环境的Edge浏览器扩展以后才能够访问设备。要在桌面浏览器中开启Edge,需要首先打开该应用并登录到Adobe。

登录成功后,点击Edge的浏览器扩展图标,如图1-7所示,就会指示浏览器去寻找网络上的设备。找到你的设备之后,就可以把从设备获得的验证码输入到Edge窗口中了。

验证码确保你授权你的电脑和你的移动设备之间相互通信,防止其他意外的电脑来控制你的设备,以及通过操作其他人的手机来控制你的电脑。

一旦你的电脑和一个或多个设备之间的连接建立起来之后,你就可以立即控制在所有移动浏览器上都载入哪个页面。Chrome中当前打开的标签页,将通过Edge Inspect在所有连接的移动设备上被重新检索并显示。

图1-7 使用Adobe Edge Inspect连接一台Nexus 7和Google Chrome进行调试

要从设备上调试网页,可从Chrome中或者在设备上跳转到希望调试的页面。在点击Chrome扩展Adobe Edge Inspect菜单时,点击你想要调试的设备边上的< >。Weinre将在本机启动,该设备以及Web页面的标题将作为一个有效链接被列在weinre的Remote标签下面,Remote就是显示在图1-6最左边的标签。

免费版本的Adobe Edge Inspect每次只允许与一个设备进行交互。按月订购版本允许同时控制所有的设备。它还可以协助进行截屏。

如果使用的是Mac而且希望测试多种设备,Ghostlab同样能够让你测试多种设备。如果你正在考虑购买这两个中的一个的话,Ghostlab的一次性收费应该比Adobe Edge的按月订购省钱。

使用Aardwolf调试JavaScript

如果你主要关注的问题是JavaScript的调试,你可以试用一下Aardwolf(土狼)。Aardwolf是一个远程JavaScript调试器,使用Aardwolf可以运行和捕获JavaScript代码。Aardwolf的工作原理是在服务器上重写你的代码并添加调试钩子(debugging hook)。与weinre使用一个Node.js后台类似,它采用同步XHR[10]调用来实现在断点处中断运行。你可以使用Aardwolf远程对代码进行单步调试,同时支持查看对象(objects)、断点和调用堆栈(call stacks)。

BlackBerry 10调试器

虽然weinre很棒,但是Blackberry 10提供的调试器功能更强大。

与weinre一样,BlackBerry浏览器也使用客户端服务器架构来实现Web查看器功能。与weinre不同的是,虽然都使用客户端服务器架构,但是BlackBerry浏览器在这里充当的是Web服务器的角色,然后通过USB或者WiFi连接之上的HTTP为Web页面提供服务。你可以在桌面式浏览器中远程查看内容。可以使用在同一个WiFi网络下的任意基于WebKit内核的桌面式浏览器,只要跳转到与BlackBerry浏览器使用的同样IP地址和端口即可开始查看代码。

要使用查看器,必须在BlackBerry浏览器的选项中启用调试功能。一旦启用了Web查看器,该浏览器或者称作应用就会显示出它将用于提供内容服务的IP地址和端口号。

要在BlackBerry 10的浏览器应用中启用Web查看器,可从顶部边框向下滑动以显示浏览器菜单栏。点击“设置”(settings)图标,再点击“开发者工具”(Developer Tools)来开启Web查看器。如果你使用的是平板设备,相应地可以在“选项”(Options)→“隐私与安全”(Privacy & Security)下面找到它。浏览器会显示从桌面式浏览器连接所需要的IP地址和端口号。如果出现提示的话,请输入设备密码以完成启用过程。点击“返回”(Back)可以保存设置并返回到浏览器窗口。你现在可以打开一个到BlackBerry浏览器的连接并远程查看当前显示页面的内容了。

能在真实设备上运行网站是最好的,但是不可能在所有的设备上进行测试,因为有成千上万种设备,而且每天都会有新的设备出现。因此建议你在一组有代表性的设备上进行测试,这组设备能够覆盖各种配置,例如操作系统、浏览器、设备大小以及各种屏幕分辨率(resolution)、内存约束和带宽访问等设备能力。

在真实设备上测试将会非常昂贵而且耗时。除了在上一节中介绍过的调试工具,还有一些工具可以帮助我们实现最大化的测试能力。

仿真器是一种软件,在电脑上复制或是模仿了一个(或多个)移动设备的功能,使得仿真的表现非常类似于真实设备的运转情况。这种注重运转情况的真实再现正是仿真和模拟之间的区别。模拟主要是模拟一个移动操作系统的抽象模型。

仿真器允许你在桌面电脑上使用移动软件,使你无须所有的设备即可运行和调试代码。即使你使用仿真器和模拟器进行测试,仍然无法在所有设备的仿真器上进行测试。仿真器和模拟器仅仅让你得以起步并加快开发和调试的进程。你还是应该在一组不同的移动设备上进行测试。

当在模拟器中运行网站时,你是在桌面电脑的一个模拟器程序中运行的。有些模拟器是针对单独的设备的,其他的则让你选择你想模拟什么设备。举例来说,iOS模拟器允许你选择iPhone还是iPad。通过菜单,你可以在横向和纵向之间改变设备朝向。还有相当于设备按钮的虚拟按钮。而且在非触控设备上,你还可以使用鼠标来模仿 触控事件。

模拟器没有精确地复制设备硬件,因此不保证你的应用程序在真实设备上能够同样地运行。某些类库对于模拟器而言可以正常地编译及链接(因为它确实是在电脑上运行的),但是当你在设备上的时候可能就无法编译。

模拟器和仿真器通常都包含一个完整的SDK,用于在一个“山寨”的本机环境中测试原生应用。为了测试代码,我们需要的是包含浏览器的仿真器和模拟器,每个仿真器和浏览器确实都有。你可能会希望下载下列仿真器和模拟器,并在其浏览器中测试网站。

Android仿真器

适用于Windows、Mac及Linux的免费Android仿真器可以随SDK一起从获取。正如http://developer.android.com在“Android调试工具”小节中描述的那样,先下载基本SDK,然后分别下载各个Android操作系统。在Mac或Linux的下载包里提供了一个Android命令行工具,在Windows上则提供了一个SDK setup.exe程序。

Android仿真器可以让你限制虚拟设备的内存大小以更好地模拟手机。在 Android虚拟设备管理器中,选中一个设备然后点击“修改”(Edit)(如图1-5所示)。在“硬件”(hardware)中点击“新建”(New),然后从“属性”(Property)下拉菜单中选择“设备内存”(Device RAM)大小。

iOS模拟器

iOS模拟器提供了一个免费的包含移动Safari浏览器的模拟环境,仅可用于Mac OS X。要注意的是,iPhone SDK的大小差不多是2GB,下载可能会花很长时间。

这是一个模拟器,而不是仿真器。它没有硬件仿真和性能指示器。它只能让你看到代码是如何运行和网站是如何渲染的,但它总体来说无法测量网站的性能。

如果你只是想看一下你的设计看起来是个什么样子,不需要仿真或是模拟的话,有很多像iPhoney或是iPadPeek这样的工具,它们就是简单地在一个看起来像是旧的设备模型的浏览器中打开你的网站。

BlackBerry模拟器

Windows版的BlackBerry模拟器包括代理服务器、面向Web开发人员的Eclipse和Visual Studio的插件以及模拟器。

Windows Phone仿真器

Windows Phone仿真器只能在Windows上使用。Windows Phone仿真器是一个仿真Windows Phone设备的桌面应用程序。可以从http://dev.windowsphone.com/ en-us/downloadsdk下载Windows Phone SDK。最新发布版以及有关安装的信息可以参阅网址http://bit.ly/16t5utu

目前,在Visual Studio中默认的仿真器映像是Emulator WVGA 512 MB,它仿真的是一个内存有限的Windows Phone 8手机。

Firefox OS模拟器

面向Firefox浏览器的Firefox OS模拟器附加组件(Firefox OS Simulator add-on)是一个Firefox OS仿真器,它提供了一个像Firefox OS一样的环境,而且看起来和感觉都像是一个移动电话。安装完成之后,Firefox桌面浏览器的Web Developer菜单下面就多了一个Firefox OS的菜单。

Opera Mobile仿真器

面向Windows、Mac和Linux的Opera Mobile仿真器可以从www.opera.com/ developer/tools下载。

Opera Mini模拟器

最新版的Opera Mini有一个Java applet版本,这是一个完整的Opera Mini应用程序,可以从www.opera.com/mini/demo获取。

以上是最常见的移动操作系统。大多数的移动操作系统,像Symbian和WebOS,具有可以通过桌面系统加载的SDK,这样你就可以模拟它们的环境。根据你目标市场的不同,你应该测试你的所有目标受众可能会使用的操作系统。有关仿真器的更多信息可参考http://www.mobilexweb.com/emulators

要快速评估设备会影响基本媒体查询的重要统计数据,可以在设备浏览器中打开http://www.quirksmode.org/m/tests/widthtest.html

W3C mobileOK检查器(W3C mobileOK Checker)可以检查网站是否遵循最佳实践,并提供相关的信息和链接来帮助你,使你的网站对移动设备更加友好。mobiReady是一个利用了W3C mobileOK检查器的在线工具,它以一种更能说服你采取行动的方式来显示结果,从而使你的网站更加移动友好。

Firefox的Modify Headers附加组件对于移动Web开发、HTTP测试及隐私非常有用,它可以让你修改(添加、替换或者过滤)发送到Web服务器的HTTP请求头。所有上述资源的链接(以及本书列出的所有其他资源)都放在在线各章资源列表。

在真实设备上进行测试是开发过程中的一个必要步骤,但购买一堆移动设备可是一笔不小的投资。调整浏览器大小和使用仿真器无法复制真实的网站性能、设备能力、像素密度和移动网络的影响。

如果你正在创建原生应用,显而易见你手里要有安装了相应操作系统的设备。在本书中,我们使用HTML5、CSS3和JavaScript进行开发,而不是原生应用,因此我们的代码将运行在所有设备的浏览器中。虽然我们的开发面向的是浏览器,但我们也还是需要在很多设备上进行测试,包括在手机运营商的网络上。永远要在真实的设备上,使用现实世界的网络连接来测试你的代码,包括WiFi热点、3G、4G甚至EDGE。乘坐一辆巴士或者火车出行,当它在城市以及大城市之间的郊区和农村地区移动时,试着从各种不同的地点来访问你的应用。

浏览器实验室(browser labs)

在真实移动设备上测试是开发过程中无法忽略的一个部分。有很多的浏览器实验室,所以要尽量在你的附近找到一个。如果你周围没有这样的设备实验室,那就和别人一起组建一个出来。

如果你倾向于拥有自己的设备实验室,那么你需要具有不同大小、操作系统、设备能力和浏览器的设备。你可以用相当便宜的价格创建一个你自己的设备实验室,从所有设备中按照你自己感兴趣的方面选择系列设备即可。购买全部的设备 是不可能的,但是你应该尽量拿到一组有代表性的不同大小、浏览器和操作系统的设备。

还有像DeviceAnywhere和Nokia Remote Access这样的虚拟设备实验室。这些都是你可以远程访问的真实设备。正因为它们都是真实的设备,所以如果某人正在使用你想用到的那一台的话,你就只能排队等候。

iOS

在北美地区,iOS设备总共只占了整个互联网流量的5%,但却占了整个移动流量的50%[11]。如果在你的开销中还没有一台iOS设备,就投资一台吧。

购买一台能够安装最新iOS操作系统的设备,以及一台稍旧版本操作系统的设备。你可以在Craigslist或者eBay上以很少的费用买到一台旧设备。目前,只有1.8% 的iOS用户,或者说是0.13% 的互联网用户,还在使用iOS 4.3及更老的版本,还有12.5% 的iOS用户,或者说是0.93% 的互联网用户在使用iOS 5。

购买设备的时候,你需要的是能够工作的浏览器。仅此而已。所以如果预算有问题的话,屏幕裂了的设备也可以买,总比没有强。其中一个设备应该是一部手机,另一个可以是手机、iPad或者iPod Touch。

购买iOS设备之后,可以从iTunes免费下载Opera Mini。

如果你所有的iOS设备都是高分辨率显示屏的话,应确保你其他的设备不是。同样,确保你所有的设备不全是手机——要有一两个平板设备。

Android

Android是世界上最流行和最多样化的移动操作系统。Android运行在涵盖手机和平板电脑的很多设备上。购买至少两部(最好更多)Android设备:一部是运行最新操作系统的高配智能机,另一部是运行旧版本的便宜货。在本书写作之时,Android 2.3虽然已经过时了,但是一些商店里售卖的便宜和免费设备上安装的还是Android 2.3,而且它还是目前Android最普遍的版本,占据整个Android市场的34%,也就是整个互联网用户的2.3%[12]

除了多个Android操作系统版本之外,还要有具备不同大小、处理能力、分辨率以及厂商的设备。在Android设备上,你可以添加其他的浏览器,包括Chrome、Opera Mini和Opera Mobile、Firefox Mobile以及Dolphin Mini和HD。

Windows

如果你正准备投资一台Windows设备,钱要花在最新的操作系统上。Windows Phone 7从未大规模流行过,但是Windows Phone 8具有这个潜力。两者都使用Metro UI用户界面。除了测试应用程序以确保代码工作正常之外,要真正地去使用Windows Phone。Windows Phone设备的用户交互与Android和iOS大不相同。通过使用Windows设备,你或许能够意识到,需要调整UI交互以使其更加符合系统本身的默认操作。

BlackBerry

BlackBerry 10设备拥有所有移动设备中最好的调试器,但绝对不是最大的用户群。

市场上有比BlackBerry 10更多的旧版BlackBerry设备。BlackBerry的新旧设备用户都在上网冲浪。我建议再添置一个BB6或BB7。幸好,旧手机并不贵,而且找一个非触控手机来测试你的网站也不错。

BB 6之前的浏览器都不是基于WebKit内核的。只有非常少的用户还在使用那些实在是太老的设备。如果你的目标市场是BB5甚至更低的话,你可能要再买第三个BlackBerry设备了。

Nokia

谈到Nokia,我的意思是Symbian OS,而不是Lumia Windows Phone。

Symbian、S40系列、三星,其次是索尼移动和摩托罗拉,在某些国家比Android、iOS、BlackBerry和Windows更常见。如果我建议某个特别的设备的话,在本书出版的时候,可能已经过时了。你只要能意识到在国际上而言,Nokia在移动市场还是很有影响力的一员。我建议添置一部功能型手机,有十字方向键输入和一个小屏幕的那种,这样你就能知道世界上很大一部分人在看你的网站时,会是什么感觉。

Kindle

别忘了还有装有基于WebKit内核Silk浏览器的Kindle Fire。

WebOS

WebOS已经不再生产,但还是有人在用[13]。你可以以低于30美元的价格买到一个Palm Pre或者Pixi。

刚才列出来的这些测试工具有助于我们可视化和手动地进行测试。要真正充分地测试,你必须不停地翻转(rotate)、缩放(zoom)、点击(pan)手机,操作失误还会无奈地大叫。对呈现而言,你需要实际地在不同设备大小、浏览器和操作系统上查看渲染的页面。对于静态内容,这可能已经足够了,而且像Adobe Edge这样的工具也能帮上忙。

对于Web应用来说,你可能需要自动化测试。你需要持续地测试应用以确保代码确实正常运行,需要测试所有的事件及结果。有一些针对JavaScript的测试类库。

Jasmine是一个行为驱动开发(behavior-driven development,BDD)的框架。PhantomJS是一个没有头文件的WebKit,不是一个测试类库,针对各种Web标准包括DOM处理、CSS选择器和JSON等都提供原生支持。你可以在PhantomJS的网站下载到面向任何操作系统的一个预编译二进制文件。

要利用PhantomJS进行自动的前端测试,可以下载CasperJS。要伪造AJAX请求,可以使用Sinon.JS。每个网站都提供了编写良好的文档,让你可以快速入门,在WebKit中使用这些类库进行测试。但没有解决在移动方面进行测试的问题。

还有一些在线的测试工具。像SauceLabs,可以让你使用上百种的移动或桌面浏览器和操作系统平台进行测试。

你可以选择任何适合你和你的应用程序的设备和工具,但是永远要测试。

现在,让我们开始写代码吧,这样我们才能有东西来测试。

[1] IE6在2001年发布时是最前沿的,几乎垄断了当时的浏览器市场份额,缺乏竞争,然后就再也没有升级过。

[2] 译者注:polyfill这个词源于国外的一个家装产品Polyfilla(是个商标),是一种用作建筑物细微修补的灰浆,也就是我们常说的“腻子”。用在浏览器里指的是“开发者自己实现的一段代码,用于在旧版浏览器上提供标准的HTML5 JavaScript API支持”,这样应用开发不用管是在新的还是旧的浏览器上都可以调用统一接口。

[3] 译者注:Google Chrome浏览器首次发布是在2008年9月。来源:http://en.wikipedia.org/wiki/Google_Chrome

[4] 译者注:功能型手机指的是相对于智能手机的普通手机。

[5] 译者注:Google之所以称为“金丝雀”版,是因为金丝雀曾在矿井中被用于早期预警,而该版本的浏览器在某种程度上也起到相似的作用。金丝雀版采集到的反馈数据,特别是崩溃统计可以帮助Google更快地找到并修复问题。来源:http://ask.zol.com.cn/q/18400.html

[6] 译者注:Bada原本是由三星电子自行开发的移动操作系统,2013年2月已经停止开发,被整合进三星新的移动操作系统Tizen了。

[7] Blink是WebKit的WebCore组件在revision 147503时的一个分支。它是自版本28以来Chrome中的浏览器引擎,Opera从版本15开始使用Blink,并且其他基于Chromium的浏览器也开始使用。

[8] Firefox本身配备了Web开发者工具,但是大部分开发人员使用Firebug。Firebug是Firefox的一个附加组件。

[9] 起初是基于Java的。在WebSockets之前,它利用的是CORS、JSON和XHR。

[10] 译者注:XMLHttpRequest的缩写,详见http://en.wikipedia.org/wiki/XMLHttpRequest

[11] http://bit.ly/HaW2PVhttp://bit.ly/1diKHLb

[12] http://developer.android.com/about/dashboards/index.html

[13] 译者注:WebOS已被LG从惠普收购,目前大量应用于LG TV上。


HTML5易学难精。没错,大多数的软件工程师、设计师甚至大批高中生都声称懂得 HTML,但是他们可能只了解很少的一些元素(element),而且可能这些元素的用法都不正确。

在本章,我们将介绍很多HTML5的分段(sectioning)元素。当你读完本章的时候,应该对HTML5的所有语义有一个很好的理解。我无法在三章的篇幅里向你传授HTML的所有内容。说实话,我自己还在继续学习HTML——而且不仅是因为HTML5仍是一个未完成的规范。由于规范尚未完成,可能仍然会有一些修改。但是也不用为这事担心。多数情况下,那些浏览器已经实现了的特性会保持不变,或者只有细微差异。

我希望你除了学习有关各种元素、它们的属性、它们语义含义以及它们的目的等相关知识之外,还能够认识到你对HTML的了解比你认为的要少:HTML有关的知识学得越多,越知道还有更多的知识要学。

简而言之,我们即将开始介绍元素。虽然可以只用一章来介绍每一个元素,但我们还是有充分的理由把它们划分到几个内容还算比较长的章节里面。我们用了足够的篇幅让你知道如何使用每个元素,而且至少还能够让你了解那些你之前所不了解的。

大家首先要了解的是,在HTML5这个术语中间没有空格:是HTML5,而不是HTML 5。

看到了吧?你已经学到些东西了!你现在已经先人一步了。那我们就快点开始吧。

HTML5与HTML4与XHTML非常类似。后两者支持的大部分元素在HTML5中仍然是支持的。只有一些过时了的标记和属性已被剔除。在大多数情况下,如果你的文档能通过HTML4严格(Strict)模式或是XHTML模式的验证,那么它们作为HTML也能通过验证[1]。HTML和XHTML的语法虽略有不同,但是两者都被支持。仅仅把HTML 4.01或XHTML的doctype改成<!DOCTYPE html>,就可以通过HTML5验证(稍后将介绍更多有关doctype的内容)。

HTML5比HTML4和XHTML更好,包含了之前版本的元素,剔除了已过时的元素,添加了一些新元素,还重新定义或微调了另外一些元素。

HTML5规范的编写者调查了Web上那些开发者们已经在做的:哪些文档分段是各种网站都趋向的,他们都赋给这些组件哪些类(class)和ID,哪些脚本是大多数的网站作者反复使用的,以及哪些类库功能已经激增至普遍存在。

HTML5试图处理那些个人开发者们一直自行在做的:创建一个标准;详细说明浏览器都应该如何处理这些标准;以及当他们的代码,呃,不那么标准的时候,浏览器应该如何处理开发人员标记。HTML5规范明确细化了浏览器应该如何处理,或解析,各种代码正确或错误的情况。通过关注细节,HTML5的一个目标就是告诉浏览器如何处理所有可能会发生的情况,从而浏览器可以从同样的标记构造出一致的DOM,这样开发人员就不会一直把带宽浪费在处理浏览器差异上了。

从我个人而言,我乐于见到更严格的标准。我的观点是开发者们应该正确地编写代码,而不是指望浏览器从宽解析糟糕的代码。你正在读这本书,所以我假定你是“良好代码”阵营的一员。很好!这就是你要学的东西。

Web页面是由一系列元素组成的。有些元素是空的,其他的元素则包含文本,而另一些可以包含其他元素(或者既有元素也有文本)。大多数元素可以包含子元素或文本节点。那些不能包含子元素的,例如图像和meta元素,称为空元素(empty element)。

如图2-1所示,一个元素就是一个结构体,由一个开始标记、一些可选的(有时是必需的)属性、通常还有一些内容,以及一个结束标记,而且如果你使用XHTML风格编写代码的话,还有一个专门针对像<img><input>这样空元素自闭合标记的可选的斜杠组成。

图2-1 组成元素的要素

在HTML之前版本的中,内联元素(inline element)只能包含其他内联元素和文本。根据元素的不同,块级元素(block-level element)可以包含其他块级元素、内联元素和(或)文本。它们的“后代”元素(descendant element),像“祖先”元素(ancestor element)一样,也可以由元素、属性和文本组成。

 

使用CSS,你可以把任何短语元素[2](phrase element)的样子更改成块(block)显示,还可以强制一个块元素或区块元素(sectioning element)显示成内联的样子(注意:我仍然在使用内联这个词。在HTML5中,内联指的是外在表现,而不是指元素类型)。

在HTML5中,我们终于从内联元素还是块元素的观念中解脱出来了——基于外观的命名约定。在HTML5中,元素被定义为区段元素、标题(heading)元素、短语元素、嵌入式(embedded)元素、流(flow)元素、元数据(metadata)元素以及交互式(interactive)元素。不过在语义上,一些观念还是保持不变的。举例来说,区段元素不能位于短语元素内部。

 

在选择一个元素时,要基于语义选择最恰当的元素,而不要基于默认的浏览器渲染。虽然你确实可以针对不管什么文体上的目的而使用任意元素,但你不应该这样做。每一个元素都有语义上的含义。

所有的元素都可以有属性。有些元素有必需的属性。有关属性的一个例子是<a>元素的href属性,如图2-1所示。属性是典型的键/值对(name/value pair),尽管布尔属性的值是可选的[3]。属性为渲染引擎提供了有关元素的附加信息,并且都位于开始标记中,而不在结束标记中。

有几个属性对于几乎所有HTML5元素来说是全局的(global)——包括核心(或全局)属性和国际化(internationalization)属性(将在下一节中介绍)——以及另一些更加元素特有的属性,这些我们将在第3章当讲到这些属性正在被修改的元素时进行介绍。

HTML5已经添加了几个国际化属性和核心属性,这些属性可以被应用到几乎任何元素上。

idclasstitlestylelangdir属性继续在所有元素上被支持。HTML5往核心属性列表中添加了accesskeyhiddentabindex属性,同时还有contenteditablecontextmenuspellcheckdraggabledropzone共5个建议性的交互式属性。随后将讨论这些属性。

除了全局属性,所有的元素也可以有微数据(microdata)属性(WIA-ARIA角色和aria-属性)和自定义数据属性。自定义数据属性是你自己的属性,写成data-*的形式,这里的*由你自己设置。HTML5通过添加data-前缀以允许开发者们创建不会与未来的HTML版本冲突的属性。我们将在“data-自定义数据属性”小节描述data-属性,在第6章介绍微数据和ARIA无障碍属性。

id

id属性是一个唯一标识符。每个文档不应该存在具有相同id的两个元素,并且每个元素最多也只能有一个id。在HTML5中,id的值必须至少一个字符长,而且不能包含空格。这与之前的版本有所不同,之前版本id的值必须以字母A-Z或a-z开始,后面可以跟字母(A-Za-z)、数字(0-9)、连字符(-)、下划线(_)、冒号(:)和句号(.)。

 

我建议你把id限制于仅使用字母和数字,然而无论你选择使用哪种命名约定,重要的是保持统一。

id属性一般是可选的。不过,对于内部页面锚点(anchoring)和正在实现显式标签(explicit label)的表单内部元素是必需的。通过使用标签的for属性和表单元素的id属性可以把显式标签和表单元素关联起来。要注意的是,对于嵌套在一个隐式标签(implicit label)之内的表单元素,id属性不是必需的。我们将在第4章讨论标签和id属性。

id属性作为一个锚点用于使用JavaScript进行定位也非常方便,只是可能有一点重度使用。id属性,如果有被包含的话,可以用在CSS中定位元素。然而,由于id在CSS样式中的高量值或特征性,即使id选择器用起来稍微更好一些,id值也应该尽量少在CSS选择器中使用。所有这些我们将在第6章讨论。现在你只要知道,在你读完这本书的时候,你将能意识到你可以使用CSS3选择器定位到页面中的任何元素,而不需要使用id选择器就够了。

class

class是该元素所属的一个类别的名字或一些类别的列表。class属性具体说明了该元素是哪一个或哪一些类的一员。和id属性不同,任何数量的元素都可以共用同一个类。一个元素可以有多个使用空格分开的类。

就CSS样式而言,class属性中类名的顺序无关紧要。然而在样式表(stylesheet)中的顺序,却很重要(这个问题我们将在第6章进行讨论):

<a href= " http://google.com " class="external popup search">link text</a>

title

title属性为它应用到的任意元素提供了一种人工可读的描述。title属性在有些可视浏览器上经常被实现为一个“工具提示”(tooltip),但是其他浏览器,尤其是移动浏览器,不会显示该title属性。虽然屏幕阅读器可以设置成支持title属性,但是大部分屏幕阅读器不会把title属性的值作为默认设置进行读取,因此在提高可访问性方面不能依赖title属性。

 

title属性对于有些元素来说是必需的,例如<abbr>;对<abbr>来讲,其title属性的值就是其缩略语的扩展。除此之外的title属性一般是可选的。

然而title属性作为一个链接、图像、框架和多媒体元素的属性时还是有用的,它可以作为一种能根据用户交互显示一些零散隐藏信息的方法被派上用场。举例来说,我们可以使用CSS提取title属性的内容,然后通过把title的值作为通过::before::after伪元素(pseudoelement)生成的内容的一部分,就可以为“工具提示”弹出式窗口创建生成的内容。

虽然title属性的值可用于渐进式增强(progressive enhancement)的漂亮花招(trick),但是因为这种花招的非可访问本质,我们不应该依赖于它来提供重要信息。而且因为用户能够访问到它,因此只能在title的内容是有用而且适合的时候才能使用title。如果你为了让你的统计可用而往title属性中添加内容,或者添加供你的JavaScript使用的代码,不要这样做!随着自定义数据属性(我们将在“data-自定义数据属性”小节介绍)的加入,rel属性和title属性巧妙的滥用已经没有必要(而且根本不适合)。

style

style属性可以让你指定某一元素只会出现一次的样式规则。该属性在快速原型设计的时候可以派上用场。除了原型设计之外,应该都不需要使用该属性,因为Web标准规定内容应该与呈现分离。

另外还要注意,当在像Safari和Chrome的Web Inspector、Firefox的Firebug、Opera的Dragaonfly、IE的F1这样的工具中使用检查器来查看代码时,使用JavaScript或者通过调试器接口添加的样式,将作为style属性的值内联出现。这是动态地生成的。浏览器可以这么做。但你最好不要!

lang

lang属性是两个全局的国际化属性之一(dir是另外一个)。一个Web页面的首要语言使用<html>元素的lang属性,通过HTTP头的Content-Languagehttp-equiv="language"属性进行设置。用于国际化或者定义内容的非默认语言区块时,lang属性详细说明了该元素属性值及其内容的语言种类,包括它所包含的那些没有给自己指定lang属性的所有元素。

lang属性使得搜索引擎能够按内容的语言种类编制索引,并允许屏幕阅读器使用国际发音规则。

lang属性使我们能够根据语言来样式化文本。<q>元素应该根据在lang属性中定义的语言来呈现恰当的引号,但这并没有被很好地支持。

dir

lang属性经常一起使用,在书写阿拉伯语(Arabic)、希伯来语(Hebrew)或者其他自右向左的语言时,dir属性可以用于更改文本方向。dir属性的默认值是ltr(从左到右)。如果你的Web页面主要使用一门这种自右向左的语言,则在<html>元素中使用dir属性来设置主要的方向。

在页面正文里面,如果你有不是页面默认方向的内容,可以使用dir属性更改文本方向。虽然没有显式要求,但我还是建议无论何时你在一个元素上面包含了dir属性,同时也要包含title属性和lang属性。一般来讲,dir属性被用于把部分文本改成自右向左。包含lang属性是因为有必要通知搜索引擎、屏幕阅读器以及其他辅助技术该语言已经改变。title属性为你提供了一种方法,让你可以包含一份内容的翻译,使用你的网站的主要语言。这些属性提供了各种方法,不仅让你的网站内容对那些残障人士是可访问的,而且对你主要的“视觉障碍”用户Google也是可访问的!

注意,在HTML5中dir略有不同,现在已经引入了第三个值auto。这样dir属性可能的值就包括rtlltrauto

上面的属性都是之前版本(X)HTML的全局或核心属性,而且继续还是。还有两个在交互式元素上所支持的可访问性属性,现在HTML5中是全局属性。这些将在下面的小节中介绍。

tabindex

在以前的规范中,tabindex被包含在像链接和表单元素这样的交互式元素上,允许开发者们设置这些元素接收焦点的顺序。HTML5已经把tabindex的作用扩展至包括所有的HTML元素。

很多人使用鼠标浏览网站,点击链接和表单元素参与交互。其他人使用键盘浏览页面;点击Tab键就把焦点从一个可交互元素移动到了下一个。在非可触控手机上,用户使用导航或方向键盘(简称D-pad)上的4个方向来导航可聚焦元素。在智能机上,大多数用户通常会触控他们希望跟踪的链接或希望输入的表单元素。一旦他们已经在一个表单元素中完成输入,很多动态键盘都提供了“下一步”按钮供前进到下一个表单元素。默认情况下,只有链接和表单字段通过这种方式接收焦点。不管是通过导航键盘的向右按钮、下一步按钮还是Tab键,从当前元素到正在接收焦点的元素的顺序,就是源代码中表单元素的顺序,除非先天的顺序已经被使用tabindex属性篡改。

在HTML5中,tabindex属性的全局性质给所有元素添加了“可聚焦性”——而不仅是表单元素和链接。该属性把它的值看作是一个整数。当用户按下Tab键时,具有tabindex属性的元素将根据tabindex属性的数字值按顺序接收焦点——适合那些具有正值的tabindex

不要使用带有正值的tabindex,除非你能够给页面上的每一个交互性元素都提供tabindex值,而且你还有很好的理由来重新排列这些顺序,并且你还要确保在该应用的整个“有生之年”你将都可以维护其正确的顺序。与此相反,我们应该使用正确的顺序来标记页面。Tab默认的顺序是与源代码中的顺序相同的。重新排列页面的Tab顺序可能会迷惑用户,从而可能导致非常糟糕的用户体验。最好以一种合理的顺序来布置页面,而且绝对不要使用tabindex属性。使用默认Tab(也就是源代码顺序)通常可以建立最佳用户体验。

所以,如果你不应该更改页面的顺序,那为什么tabindex成为一个全局变量了呢?tabindex属性成为全局性的目的是为了在所有元素上,包括非交互性上启用可编程的聚焦,一般是通过JavaScript或键盘焦点。

因为我们不希望真的更改源自页面源顺序的Tab或键盘焦点的顺序,所以tabindex的值只应该是0或−1。tabindex="-1"(任何负数值都起作用,不过−1是惯例)这样的值可被用于可编程聚焦;而tabindex="0"可被用于提供可访问性等方面的事由,假如你想要给一个链接或表单元素之外的元素提供键盘访问的同时又不更改页面的顺序的话。

 

你可能想知道,在通常不使用Tab进行导航的移动领域, tabindex能做什么。注意,你在填写一个表单元素的时候,有些设备上显示出来的键盘在顶部有一个“下一步”按钮。同样,就像在桌面环境上你希望通过JavaScript启用焦点一样,在手机上你可能也想这么做。并且,就像在桌面环境上一样,不是所有的用户都有一台指点设备(pointing device)[4]。许多视觉障碍人士在使用智能手机,尤其是在美国的iPhone。这样一来,tabindex就有助于可访问性。

accesskey

acesskeytabindex类似,除了它不通过使用Tab按顺序导航到下一个具有更高tabindex值的元素进行页面导航,而是把焦点直接移动到触发访问键(activated access key)已经设置好的元素。可以把它看成是一个键盘快捷键。

acecsskey属性的值创建了键盘快捷键。例如,<input acesskey="s"name= "search"type="text"/> 创建了一个accesskey等于s的搜索框。当用户按下字母“s”时,焦点就移到了搜索框。

accesskey属性的值是一个或多个使用一个空格分开的字符。通常情况下,它只是一个字符,但规范允许一个元素可以有不止一个键盘快捷键。accesskey值的语法与class属性类似,后者的属性的值是一个空格分开的标记(token)的有序集合。不过,这里的顺序是有意义的,第一个标记之后的标记被认为是为无法支持初始值的用户代理准备的回退方案。

虽然tabindexacesskey最初都曾被视为可能解决可访问性问题的方案而备受推崇,但它们不是大家都盼望的可访问性解决方案。如前所述,tabindex由于修改页面原本正常的焦点顺序会产生糟糕的用户体验。类似地,accesskey可能会扰乱客户端浏览器设定的默认行为和快捷键。

迄今为止,我还未发现在智能手机上accesskey有什么用,但是因为我们正在学习HTML5,所以就把它包含进来了。accesskey在智能手机到来之前曾经很有用,那时在一个很小的旧手机上浏览网站是件苦差事。

HTML5包括若干新的属性,其中包括在本节介绍的一些新的全局属性。在接下来的两章,当我们讨论到一些元素的时候,将介绍这些元素特有的新的属性和值。

hidden

当含有hidden属性的时候,表示该元素尚未或者不再适用。支持的浏览器不会显示具有hidden属性,或在用户代理的样式表中定义了display:none;的元素。最好不要仅仅为了对用户隐藏元素而使用该属性,因为它是具有语义的:它表示围绕在该hidden属性的内容要么是已经过时的,要么是不再适用的。

contenteditable

contenteditable属性表示该元素是否是可编辑的。当包含该属性时,虽然用户对内容的更改并没有被保存,但的确修改了DOM,这样你就可以捕获这些更改并发回给服务器以保存。所有的桌面浏览器都支持contenteditable属性;随着Android 3.0和iOS 5.0开始提供支持,除了Opera Mini之外的所有移动设备也都支持该属性。

一旦设置了元素的contenteditable属性,触控设备上的动态键盘就应该弹开以启用编辑。

contextmenu

contextmenu属性使元素能够和一个提供了更多上下文相关信息的<menu><command>关联起来。该属性把你希望与之关联的<menu>元素的id的值作为它的值。除了Chrome试验性地提供支持之外,该属性尚未被其他任何浏览器所支持,因此本书并未涉及<menu><command>元素。

draggable

可拖动属性表示该元素是否是可拖动的。你也许已经注意到了,在大多数桌面浏览器上可以拖动图像,但无法放下。这就是目前默认的可拖动行为。为了使draggable属性变得确实有用,应该把它与JavaScript事件处理器结合起来使用,例如dragstartdragdragenterdragleavedragoverdropdragend。除IE10之外的移动浏览器都不支持拖放,因此这些API没有包含在本书中。

dropzone

拖动一个元素是一回事,但是拖完之后你要做什么呢?HTML5提供了一个dropzone属性,可以指定在一个元素上可放下什么类型的内容。你可以使用movecopylink属性值,分别移动、拷贝原来被拖动的内容或为其创建一个链接。因为移动浏览器没有对拖放提供很好的支持,所以我们在本书中不会对其进行进一步讨论。

spellcheck

spellcheck属性表示一个元素是否要进行拼写和语法检查。默认情况下,大多数  智能手机和平板电脑会在输入的时候自动更正(autocorrect)文本区域,但并不总是很  好——有几个拿“更正”寻开心的网站。虽然它们不支持spellcheck属性,但它们的确支持自动更正。

有趣的是,虽然iOS的默认行为是自动更正文本,但如果autocorrect属性被添加到一个文本类型输入,它实际上不检查拼写;它只会在没有包含这个属性的时候才自动更正。

ARIA无障碍属性

HTML5支持无障碍富Internet应用(ARIA)可访问性模块的rolearia-*属性。ARIA是一个单独的模块,而不是HTML5规范的一部分。使用实时区域(live region)、角色以及ARIA状态和属性,WAI-ARIA能够帮助提高动态更新内容和被劫持(hijacked)元素的易访问性。

当与富Internet应用程序交互时,使用屏幕阅读器访问的用户,可能正在让页面的一部分大声地朗读出来,同时页面的另一部分正被动态更新。ARIA实时区域可以帮助向用户表明页面其中的一部分 ——当前没有获得焦点的那部分 ——已经更新了。使用arialiveassertivepolite或默认的off值,ARIA为网站作者提供了一种方法,可以暂停屏幕阅读器,并通知用户页面的一部分已经被更新。相关的属性包括aria-atomicaria-busyaria-relevant

ARIA的role属性可以在改变用途的元素上创建一个语义化结构。举例来说,其用途改变为一个gridlistboxmenumenubartablisttoolbartreetreegrid的元素都可以认定为是这样的元素。使这看似非语义化的标记变得易于访问、可用,以及可以跟辅助技术互操作。虽然屏幕阅读器对新的HTML元素(参见第3章)的完全支持可能会使一些ARIA结构角色不再适用,但是现在就给页面添加rolearticleapplicationbannercomplementarycontentinfodocumentformheadingmainnavigationsearch值可以帮助支持ARIA但尚不支持HTML5的屏幕阅读器。

关于角色需要注意的两个问题是:(1)一旦设置之后,role不应该被动态更改,因为这将会扰乱辅助技术;(2)角色优先于元素的默认语义。

除了role属性和它的很多值之外,ARIA 还为状态和属性提供了相关属性。状态属性有aria-disabledaria-busyaria-expandedaria-hidden,有关属性的属性有aria-describedbyaria-haspopuparia-labelled,这些属性在动态部件(widget)和改变用途的元素上提供了附加信息。最好的作法是针对任务使用语义最符合的现有元素,但是当你针对一个无法预期的用途(例如一个树状菜单)无论如何必须使用一个特定的元素时,应该使用ARIA。

data-自定义数据属性

在HTML5中,你可以创建自己的属性。虽然之前也可以创建自己的属性,但是标记不会通过验证。HTML5引入了自定义数据属性,这样的话,作为作者的你,可以自己定义这些属性的名称。

为了给用户交互提供数据,开发者们一直在编写无效的属性和滥用titlerel属性。仅仅使用data-前缀创建一个属性,代码就可以通过验证,而不是误用像reltitle这样的HTML4属性。

例如,在我们的CubeeDoo游戏中,我们需要维护每一张卡片的值和位置,这样当我们对它们进行比较时,我们就能够知道第一张翻开的卡片是否与第二张翻开的卡片一致,而且在我们暂停游戏以及离开屏幕时,还需要和localStorage结合来维护状态。我们可以在JavaScript中使用数组的方式来记住每一张卡片。相反地,我们在代码中创建了data- positiondata-value属性,可以为每一局新游戏的设定动态地更新data-的值:

    <div id="board" class="level1">
        <div data-value="0" data-position="1">
            <div class="face"></div>
            <div class="back"></div>
        </div>
        <div data-value="0" data-position="2">
            <div class="face"></div>
            <div class="back"></div>
        </div>
        <div data-value="0" data-position="3">
            <div class="face"></div>
            <div class="back"></div>
        </div>
        <div data-value="0" data-position="4">
            <div class="face"></div>
            <div class="back"></div>
        </div>
        ...
        <div data-value="0" data-position="24">
            <div class="face"></div>
            <div class="back"></div>
        </div>
</div>

当用户选择两张卡片时,它们的data-value的值进行了比较。如果一致的话,我们就得到了一对相匹配的。data-position属性使我们可以跟踪每张卡片的位置,在两张卡片成功匹配的时候把它们的data-value的值都改成了0。我们还使用data-value的值来设计卡片正面的样式,使用的是属性选择器(attribute selector),将在第7章进行介绍。

在能够使用data-*属性之前,我们可能已经使用像<div class="…"rel="15" title="4">这样或类似的代码来构建我们的卡片了。虽然title可以通过验证,但却没什么好处,而且在桌面悬停的情况下,甚至会让人们能够轻易地作弊(在这个游戏中,你仍然可以使用一个元素查看器作弊,但是显示一个工具提示就让游戏变得有点太简单了)。data-前缀已经为此目的而被保留了,以避免和未来HTML的版本发生冲突。自定义数据属性旨在存储页面或应用程序的私有自定义数据。对这些属性的唯一要求就是它们不能用于像–moz-–webkit-这样的用户代理扩展(user agent extension)。

数据集(Dataset)API。自定义数据属性带来了dataset API。使用dataset API,你可以获得属性/值对,即使自定义数据属性的名称是动态生成的(即你不知道破折号后面的属性名称是什么)。

1              // get all the cards values and positions
2              // use dataset to get value for all the cards.
3              currCards = document.querySelectorAll('#board > div');
4              for (i = 0; i < qbdoo.cards; i++) {
5                  cardinfo.push(currCards[i].dataset);
6              }
7              currentState.cardPositions = JSON.stringify(cardinfo);

虽然我们记得已经设置了哪些属性,但当我们在暂停游戏前获取它们的值的时候,还将使用dataset API,而不是getAttribute()方法,目的就是为了讲授一下dataset API。来自qbdoo.pauseGame方法的代码片段使用了一个查询选择器(query selector)来获取所有的卡片(第3行),然后对所有卡片进行遍历,使用dataset API来获取以DOMStringMap形式表示的所有dataset属性的键/值对,并作为一个数组值存起来。最后一行(第7行)把我们已经获取的键/值对转换成了一个JSON字符串。或者,我们可能还已经遍历了整副牌:

1                for (i = 0; i < qbdoo.cards; i++) {
2                     for (key in currCards[i].dataset) {
3                       deck[key] = currCards[i].dataset[key];
4                  }
5                cardinfo[i] = deck;
6             }

Itemid、itemprop、itemref和itemtype

有5个与微数据(microdata)相关的其他全局属性被从HTML5规范的主体删除了,并且现在是微数据规范的一部分,包括itemiditempropitemrefitemscopeitemtype。我把它们包含在这里,这样就把所有的全局属性都罗列出来了。这些属性将在第6章的“微数据API”小节中进行讲解。

我们已经谈到了元素和属性,但我们还没有讨论如何把它们包含进来。语法是很重要的,所以让我们开始吧。

要在Web页面中包含一个元素,你要包含一个开始标记和一个结束标记。开始标记以一个左尖括号(或小于号<)开始,后面跟着元素名称,然后是右尖括号(或大于号>)。

正确:

<a>
<p>
<div>

错误:

<m> <!-- there is no 'm' element' -->
< div><!-- there can be no space before the element name -->

如果有属性的话,它们都包含在开始标记中,位于元素名称的后面,使用空格分开。所有的属性都是名称/值对。与XHTML不同的是,HTML5布尔型属性不需要被显式声明。在一个布尔型属性存在但值被忽略的情况下,浏览器默认为true

尽管HTML5没有提出要求,但为了便于阅读及符合最佳实践的要求,属性应该全部使用小写,同时属性的值应该全部用引号引起来。属性的值可能是大小写敏感的,这取决于属性的类型。

对于每个元素的开始标记来说,一个属性只能出现一次。虽然很可能你是知道的,而且也没有有意在一个元素中多次包含同一个属性,但这还是验证错误的一种常见情形,所以把这当作一个友情提示吧。

正确:

<a href="http://www.standardista.com" >
<p class="racket-tailed drongo">
<div id="content">

有效,但并非最佳实践:

<a href=http://www.yahoo.com>
<!-- best to quote all attribute values -->

无效:

<p class="racket-tailed" class="drongo">
 <!-- no duplicated attributes allowed. -->
<p class=Racket-Tailed Drongo>
 <!-- while HTML5 does not require quotes around all attributes, it is
best practice. And, if there is a space in the attribute value, the
quotes are required to unambiguously delineate the start and end of
the attribute's value! -->

要结束或者说是关闭一个元素,使用一个左尖括号和一个斜杠,后面跟着元素名称(与在开始标记中的元素一致)以及一个右尖括号。如果该元素是一个空元素(参见2.2.1节),你可以通过在紧挨开始标记的右尖括号前面添加一个可选的斜杠来结束元素:

<a href="http://standardista.com/mobile/ch2">Files for this chapter</a>
<p class="racket-tailed drongo">Exotic Asian Bird</p>
<div id="content">. . .</div>

元素的内容放在开始和结束标记之间,可能会包含其他元素以及文本节点。正确地嵌套元素!如果你把一个元素作为另一个元素的子元素包含了进来,嵌套的子元素的开始和结束都必须在父元素的关闭标记之前:

<div id="content">
 <p class="files">
  Examples in the <a href="http://standardista.com/mobile">
  online chapter resources</a>
 </p>
</div>

在上面这个例子中,<div>元素包含从第一个<到最后一个>的所有内容,包括了作为“后代”的段落(paragraph)和锚点(anchor)元素。注意,<a>元素的开始和结束都位于<p>元素的开始和结束标记内部,而且相应地<p>元素也在<div>元素内部开始和结束。

所有元素都有结束标记,除了自闭合元素,也被称作空(empty)元素或空白(void)元素。按照XHTML语法,我们使用反斜杠来自闭合这些元素。

空元素不能包含嵌套元素或文本。作为自闭合元素,它们不能包含结束或关闭标记。如果你愿意的话,可以在开始标记的右尖括号前面包含一个斜杠。虽然HTML5并不要求元素一定要闭合,但XHTML语法却要求必须有一个结尾的斜杠。自闭合或空元素包括:

<img>       图像
<br/>       换行符
<meta/>    元数据
<hr/>      水平分隔线(thematic break)
<base/>    资源和链接的基准 URL 和默认目标
<link/>    外部链接<a href='#anchor25' id='ac25'><sup>[5]</sup></a>
<keygen/>  表单控件密钥对生成器
<area/>    图像映射中的区域(指的是带有可点击区域的图像)
<col/>     表格的列
<command/> 菜单命令
<embed/>   嵌入内容,如插件
<input/>   表单控件
<param/>   对象参数
<source/>  音频或视频的媒体源
<track/>   外部文本轨道,如字幕文件(Timed media tracking)
<wbr/>     单词换行时机(Word Break Opportunity)

有一些XHTML要求的编码规则在HTML中是可选的,甚至还不支持。虽然HTML5同时支持这两种编码格式,但还是有一些非必需的最佳实践:

标记使用小写

在XHTML中,元素标记和所有属性的名称必须全部小写。虽然HTML5支持驼峰命名(camelCase[6])以及其他形式,请使用全部小写的代码。在W3C中也没有任何地方规定属性的值需要小写,但有的属性的值,像id,是大小写敏感的,所以还是要坚持小写。

所有属性都用引号括起来

在XHTML中,所有属性的值必须使用单引号或双引号括起来。在HTML5中,只有属性的值包含空格或特殊字符的时候需要使用引号。让我快乐:把所有属性的值都用引号括起来。

闭合所有元素

在XHTML中,每一个开始标记必须同时有一个结束标记。像<img/><br/>这样的空元素必须是自闭合的。在HTML5中,有些标记可以不让它闭合。虽然省略结束元素可以减少页面上字符的数量,但它也会让你的代码难以阅读,从而更难以维护。有些演讲人/博客发文建议针对移动平台可以省略结束标记以减少字符数量从而生成更小的文件。节省的这些很少的字节并不值得带来的风险。减少DOM元素的数量比用这种方法减少字符数作用更大。让我高兴:闭合所有元素。

就用来关闭元素的末尾斜杠而言,你可以包括也可以忽略。选择哪种方式都可以,重要的是保持一致。

嵌套所有元素

所有标记必须正确地进行嵌套:如果你开始了一个<a>标记,然后开始或嵌套了一个<strong>,就必须在关闭</a>标记之前关闭</strong>标记。只要正确地嵌套标记:代码就会正常地渲染,除错也会变得更容易,而且代码也就会通过验证(还有,你会让我高兴)。

为所有非布尔型属性提供值

在XHTML中,所有的属性必须被编码为属性/值对,即使是布尔值。XHTML的selected的默认选项应该写成selected="selected"。在HTML5中,同样的代码可简写成selected。在HTML5中,给布尔型属性提供值不是必须的,因为包含状态属性就使一个布尔值为true,即使在大多数浏览器中该属性的值是false。不管你选择包含还是不包含布尔的值,都要让你的决定始终如一。如果你包含了布尔的值,就要总是包含它们。如果忽略的话,就要一直忽略。

对于一个布尔型(或甚至非布尔型)属性,不要包含一个空字符串="";可以总是包含一个值。

 

注意,如果你包含了一个布尔值,设成空字符串的话它将是true。如果希望是false,必须使用removeAttribute(attributeName)而不是setAttribute(attributeName,"),因为空字符串将导致布尔属性为true。

注意,空字符串可能会产生意外的结果,尤其是在涉及将在第3章出现的表单属性时。

针对任务使用语义上最合适的正确元素

在XHTML中,元素需要以语义的方式编码。表格和表单不能包含在段落中。表单元素,是短语元素,需要被包含在语义上的块级元素内部,例如段落或表格的单元格。是的,你可以使用span和div来包含页面上所有的东西,但是如果一个页眉就是一个页眉,则使用<h1-6>标记。

元素是组成Web的构成要素(building block)。网站如果没有内容的话,CSS和JavaScript将无从增强。但实际上,一个Web页面要成为有效的XHTML只需要5个元素。

换句话说,使用XHTML语法的有效HTML5文档的最低要求是:

<!DOCTYPE html>
<html>
  <head>
   <meta charset="utf-8"/>
   <title>Blank Document</title>
  </head>
  <body>
  </body>
</html>

我包括了charset &lt;meta>元素,如果你在服务器上正确设置了HTTP头的话,这个元素不是必需的。如果你对服务器没有控制权,则要把它当成必需的。

事实上,一个有效的HTML5甚至都不需要这么多元素。如果省略<html><head><body>的话,浏览器会隐式包含它们。最短且合理的HTML5文档实际是:

<!DOCTYPE html>
<title>Blank Document</title>

注意在图2-2中浏览器包含了那些缺失的标记。当忽略<html><head><body>或结束标记时,浏览器会正确地渲染文档,在渲染进DOM的时候会添加这些节点,并添加结束标记。

图2-2 上面是HTML源码,下面是渲染出来的文档

是的,你可以把整个HTML5文档放进一条140字的微博里面。仅仅因为你可以省略一个页面上总共5个必需元素中的3个并不意味着你应该这样做。为了易读性和维护,尤其在是由其他人负责的情况下,选择一种编码风格并坚持下去:最好使用XHTML风格的语法编码,并包括这5个元素。

让我们看一下这5个“必需的”元素更细节的东西。

文档类型声明

文档类型声明(Document Type Declaration),doctype或DTD,告诉浏览器你使用的是哪种标记语法,这样浏览器就知道期望什么以及如何处理它。这个总是要发给浏览器的东西的第一行,如果作为XML解析的话,带着XML开端的例外。前一个例子使用HTML5的DTD,这个是最短的,而且是本书的点,但还是存在如表2-1所列的其他几种。

表2-1 HTML4、XHTML以及HTML5文档类型

页面类型

文档类型声明

HTML 4.01 Transitional

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional //EN" "http://www.w3.org/TR/HTML 4/loose.dtd">

HTML 4.01 Strict

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/HTML 4/strict.dtd">

XHTML 1.0 Transitional

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional// EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional. dtd">

XHTML 1.0 Strict

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1- strict.dtd">

XHTML 1.1

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

HTML5

<!DOCTYPE html> a

a.与HTML5的其他部分一样,doctype不区分大小写

虽然你可能有10年的XHTML DTD使用经验了,你可能还得把它拷贝粘贴到文档中,因为你仍然没有把它记住。我也是!在敲了一次HTML5 doctype之后,我再也没有再次查找它。

所有的现代移动浏览器支持所有的HTML和XHTML DTD,包括新的、更短的HTML5 doctype声明。

如果你担心旧代码会如何与新的HTML5 doctype相处,请放心[7]。如果你的Web页面作为HTML4或XHTML Strict验证通过,你的标记就是有效的HTML5。支持HTML5的浏览器应该提供对所有之前版本的HTML和XHTML的向后兼容,包括过时的元素。然而,仅因为已过时的元素被浏览器支持并不意味着你就应该使用!虽然<center><font>也许可以如预期般渲染,但是它们不能被当成有效或良好的代码[8]!为了确保一贯的整洁和可扩展的代码,我建议使用XHTML语法,包括把所有属性的值用引号括起来以及关闭所有元素。HTML5考虑到了懒惰的编码习惯,但不要做一个懒惰的编码者!

<html>元素

<html>元素是HTML文档的根元素。虽然它在HTML5中是可选的,但在使用XHTML语法时是必需的。HTML4 transitional不要求<html>元素,HTML5也不要求,但是我们希望编写良好、整洁且标准兼容的代码。所以,无论出于何种目的,它是必需的而且应该如表2-2所列的那样书写。

<html>有两个子嵌套其中:<head><body>。在HTML元素中包含lang属性是一个好的做法(但不是必须的)。

表2-2 HTML元素及页面类型要求

页 面 类 型

HTML元素

HTML 4.01 Transitional
HTML 4.01 Strict
HTML5

<html>
<html lang="en">

XHTML 1.0 Transitional
XHTML 1.0 Strict
XHTML 1.1

<html xmln="http://www.w3.org/1999/xhtml">
<html lang="en" xmlns="http://www.w3.org/ 1999/xhtml">

HTML5在<html>元素上提供了一个新属性。manifest属性,在包含了的情况下,把它的值作为manifest文件的URL。应用缓存、manifest文件和离线应用将在第6章讨论。

有些像modernizr的HTML5脚本工具会往<html>元素开始标记中添加一些类。这是完全合法的。算上应用缓存,用于特性检测的modernizr脚本,以及语言声明,我的<html>开始标记看起来往往是这样的:

<html lang="en" manifest="cache.appcache" class="no-js">

我们之前已经讲解了lang属性。第6章在讲解离线和存储时会讲到manifest属性。如果你使用modernizr<a href='#anchor29' id='ac29'><sup>[9]</sup></a>来测试本书讨论的各种Web技术的原生支持情况的话,应该包含no-js类。

<head>元素

文档的<head>包含了一些重要信息,除<title>元素之外,均不直接在浏览器窗口上显示[10]。虽然<head>的内容通常不显示,但是大部分浏览器会在标签或其他浏览器Chrome上显示标题,标题是一个有效的HTML5文档的唯一必需元素。<head>元素的其他内容告诉浏览器如何渲染页面,以及与搜索引擎爬虫关于页面内容进行“对话”。就HTML4和HTML5之间的变更而言,<head>元素中的profile属性从未被使用过,因此没有包含进提议的HTML5规范里面。

<head>是必需的<title>元素以及可选的<style><script><link><meta><base>元素的父元素。

<title>元素

<title>属性是必需的,而且必须包含</title>结束标记。你的页面没有head><body>甚至没有<html>标记都可以通过验证,但是如果没有必需的<title>就无法通过验证,而且如果结束标记缺失的话就无法解析。<body>可以是空的,并且对用户可以不显示任何内容。尽管<title>可以不包含任何文本,但它还是必需的。

<title>标签的内容应该是对文档综合内容的定义。虽然<title>可能好像对Web页面的布局并不重要,但是当涉及搜索引擎的时候,<title>是文档中最重要的元素。

注意<title>标记的内容是如何在浏览器Chrome中显示的,如图2-3所示。虽然与<title>在桌面环境上搜索引擎优化中的重要性相比,这可能不是一个重要因素,但是当你在手机的小屏幕上浏览的时候,它可能快速变丑,所以要谨慎地选择标题。

图2-3 显示在iOS Safari和Firefox OS浏览器Chrome中的<title>元素内容

<body>元素

我们已经添加了<title>,但Web页面还是空白。你希望在网站上显示的所有内容需要放到页面的主体中,包含在唯一的<body>元素里面。<body><html>根元素的两个子元素中的第二个,也是最后一个元素。

body元素有一些外观类属性,在XHTML中是过时了的。HTML5赞同XHTML的这个机智传统:HTML5没有任何的曾经属于HTML4的外观类属性,像alignbgcolor,以及背景和链接配色,因为这些功能由CSS能够处理得更好。如果有必要的话,你能给<body>元素添加的属性应该只有idclasslangdir

在查看Web页面的源代码时,你经常会在<body>的开始标签中碰到事件处理器,例如 onload="doSomething();"。一般来说,你应该只添加像classid这样的全局属性到<body>开始标记中。事件处理器应该放在外部的JavaScript文件中,同时样式应该放在外部的CSS文件中。

我们的第一个最基本的HTML5文档应该像下面这样编码,唯一能注意到的差别是字符集和文档类型声明:

<!DOCTYPE html>
<html>
<meta charset="UTF-8"/>
 <head>
  <title> My First HTMLS Web Page </title>
 </head>
<body>
</body>
</html>

而且使用这6个元素(DTD、<html>根、<head><meta>字符集、<title>元素,以及<body>元素),我们已经创建了一个Web页面—— 一个空白的Web页面,但仍然是一个网页。而且,因为<title>元素中的相关内容,我们的空白网页比Web上的很多网站更容易被搜索引擎找到。

我之前提到,你甚至都不需要这么多的元素:

<!DOCTYPE html>
<meta charset="utf-8">
<title>我的第一个 HTML5 网页</title>
<p>Hello World

虽然这是一个有效的HTML5文档,但却不是好习惯。让你的代码更清楚,以后维护你代码的开发人员,包括你自己,就会更好地体会你的代码的原本意图。

<head>可能是网页标记中最不诱人的部分,因为它默认对用户不可见。但是只是因为它不诱人并不意味着你就可以不重视它。在Web文档的头部分,作为一名开发人员,你可以告诉浏览器如何渲染你的页面,还可以在此为打印机、搜索引擎和解析器提供你的内容应该被如何处理的提示。

<head>中,你总能找到<title>,但你也可能会遇到<meta><base><link><script><style><command>以及<noscript>标记。

这里是一个非常饱满的头部区域可能的样子:

<head>
<meta charset="UTF-8"/>
<title>Mobile HTML5</title>
<meta name="author" content="Estelle Weyl"/>
<meta name="publisher" content="O'Reilly"/>
<meta name="copyright" content="Copyright 2013"/>
<meta http-equiv="date" content="Mon, 18 Nov 2013 16:15:30 GMT"/>
<meta http-equiv="date-modified"
    content="11/18/2013" scheme="MM/DD/YYYY"/>
<meta name="keywords" content="html5 css3 svg
    border-radius canvas audio iphone android ipad"/>
<meta name="description" content="Moving from desktop to mobile:
    Learning CSS3 and HTML5."/>
<meta name="pagetopic" content="Internet"/>
<meta name="page-type" content="Instruction"/>
<meta name="audience" content="all"/>
<meta name="robots" content="index,follow"/>
<meta name="generator" content="Sublime"/>
<meta name="apple-mobile-web-app-capable" content="yes"/>
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<base href="http://www.standardista.com/"/>
<script src="/js/application.js"></script>
<link rel="apple-touch-icon" href="touch-icon-iphone.png"/>
<link rel="apple-touch-icon" sizes="72x72"
    href="touch-icon-ipad.png"/>
<link rel="apple-touch-icon" sizes="114x114"
    href="touch-icon-iphone4.png"/>
<link href="/css/prettification.css" media="all" rel="stylesheet"/>
<link href="/css/tinylittledevice.css" media="only screen and
    (max-device-width: 480px)" rel="stylesheet"/>
<link href="/css/print.css" media="print" rel="stylesheet"/>
<style>
     p {color: #333333;}
</style>
</head>

这是一个冗长的头部,而且你的永远不要看起来像这样子,但是你应该理解它。所以,让我们来看一下所有这些都是什么意思。

<meta>元素能让Web开发者通过指定一个属性和一个值在页面上包含各种类型的元数据。<meta>有4个特有属性:charsethttp-equivcontentname

<meta charset="UTF-8" >

我们将涵盖的第一个<meta>元素是在你创建的每一个HTML5文档中最可能使用的:

<meta charset="utf-8"/>

你可能很长时间以来一直往文档添加:

<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>

高速浏览器把页面作为HTML处理,以及在服务器的HTTP头没有设置字符集的情况下使用UTF-8字符集。

虽然<title>元素应该是<head>开始标记后面的第一个元素,但我们还是允许字符集声明这个例外,因为我们希望确保在字符得到渲染之前,渲染代理知道渲染哪一个charset。尽管是HTML5新增的,但下面这行代码还是在所有主流浏览器中都支持,因为浏览器一直支持错误地没有用引号括起来的meta

<meta http-euiv=Content-Type content=text/html; charset=utf-8>

注意,在这个书写错误的<meta>标签中,由于缺少引号以及content属性值中的空格,浏览器把charset看作一个单独的属性。这个从前的“错误”,因为实在是太普遍了,导致所有的浏览器都支持,现在是HTML5建议规范已经实现的部分。

你可以(或者说应该)使用UTF-8的方式从服务器上提供所有文件。如果你运行的是Apache,可以在.htaccess文件中添加一行AddDefaultCharset UTF-8

对于charset这个例外,<meta>标记的类型是通过name的值或是http-equiv属性的值定义的。除charset之外,每个<meta>标记必须包含namehttp-equiv属性以及一个content属性。

一个<meta>元素由name属性和content属性组成。一般来说,除非你正在试图生成一个HTTP响应消息头,否则这两个属性的值总的来说是自由的:你来创建name的值和content的值。我们将首先覆盖普遍存在的<meta>类型,然后再深入更移动特有的那些。

描述meta标记

有一些标准值,包括一个最重要的非移动特有的description。"description" <meta>标记的内容是那些许多搜索引擎返回的当你的网页被包含在搜索结果中时。所以,确保description的content值是一个与页面内容相关的符合语法规则的描述性的句子,包括关于页面的关键字(参见图2-4):

<meta name="description"
  content="CSS3, JavaScript and HTML5 as explained by Estelle Weyl">

图2-4 显示Google搜索结果中的description <meta>标记的content

关键字meta标记

在所有的<meta>标记中,"keyword"是最知名的。然后,由于在上一个世纪垃圾邮件发送者对"keyword"meta标记的滥用,搜索引擎不会给其内容很高的评估值。你可以随意包括keyword元数据,但是对于你的搜索引擎的努力不要依赖它:

<meta name="keyword" content="CSS3, HTML5, JavaScript">

<meta http-equiv="…">

虽然使用name属性的<meta>元素是相当自由的,但http-equiv属性却不是。使用http-equiv属性来代替name,能够替换由服务器所创建的HTTP响应头。我在http:// www.standardista.com/html5/http-equiv-the-meta-attribute-explained/上创建了一个http- equiv&lt;meta>标记的值的列表。如果你在服务器上有权限访问.htaccess文件,则可以使用该文件来设置头。依赖于<meta>标记来设置头应该是你的最后一招,而不是优先考虑:

<meta http-equiv="cache-control" content="no-cache" />

有一些<meta>标记特别适合移动设备。其中有些是让浏览器占据整个视区和禁止缩放以及改变状态栏颜色,这些都将在下面的各小节中讨论。

视口meta标记

在桌面环境上,除非你把浏览器窗口大小延展到超过显示器的边界,否则视口的大小就是浏览器窗口大小。在大多数移动设备上,页面缩放是可以控制的,但视口大小保持不变,由设备屏幕的尺寸所决定[11]

"viewport"<meta>标记能让我们在移动设备上支配浏览器窗口的逻辑尺寸及缩放。在我们的Web应用CubeeDoo里面,我使用了下面的meta标记:

<meta name="viewport"
content="user-scalable=no, width=device-width, initial-scale=1.0"/>

视口<meta>标记在所有的智能手机和移动设备上都支持,包括iOS、Android、webOS、Windows Phone以及Opera Mobile。通过设置视口宽度等于device-width,我们等于告诉浏览器把文档宽度设成设备宽度。

视口<meta>标记支持一个逗号分隔的指示列表,能让我们支配浏览器视口的宽度、缩放和高度。你可以告诉浏览器不支持缩放,或放大到某个最大值,或缩小到某个最小值。

width=<num>|device-width

一般来讲,你可能希望使用device-width关键词来把视口宽度设置成设备宽度,虽然数字值也是有效的。默认值依据浏览器各有不同,但一般都是980像素左右。最小值200,最大值10000。

height=<num>|device-height

设置成device-height,或者一个值,像iPhone 4及其更早版本就是480像素,定义视口高度。这个值一般是被忽略的,我赞成只使用宽度。参考起见,最小值是223。

user-scalable=no|yes

决定用户是否可以改变视口的缩放比例。设成yes是允许缩放,no是禁止缩放。默认是yes。设成no同时也阻止了在数据集上的滚动。用户缩放,如果允许的话,可以使用视口<meta>minimum-scalemaximum-scale属性进行限定。

initial-scale=<float>

设置用于查看网页的初始比例或缩放因子(或乘数)。默认值1.0不使用缩放来显示网页。

maximum-scale=<float>

除非user-scalable被设成no,否则设置用户放大的上限。最大值是10,但可以是浮点数0.25或更大的浮点数。

minimum-scale=<float>

设置用户缩放网页的下限。最小值是0.25。

大多数移动浏览器的渲染出来的默认宽度是980像素。通过把宽度设成device-width,用户就不需要在页面加载时放大页面,只是因为你在一个320像素的设备上提供的是980像素。我们也可以针对320像素把视区宽度设成320而不是device-width,但这样它就只能在正好320像素宽的设备上正常运行了。我们将把窗口的宽度设成设备宽度,这是最适宜的:它会相应于设备缩放页面,不需要作者必须知道用户可能使用的设备的宽度。

然而,这不是对所有网站都最适宜的,而是仅适合移动网站和移动Web应用。然后,在user-scalable被启用的情况下,用户可以放大页面从而让难以阅读的小字体变得清晰易读。

使用CubeeDoo,我们将创建一个移动游戏。在玩的时候,用户将触控屏幕。我们不希望用户在试图轻击标题的时候不小心把页面放大或缩小了,所以我们告诉浏览器让游戏全屏而且不允许缩放。我们一直在设计网站而不是一个app,为了更好的可用性,我们将允许用户无限制地缩放,我们在语言选择器中是这样做的:

<meta name="viewport" content="user-scalable=yes, width=device-width, initial-scale=1.0"/>

视口<meta>标记的功能就是上面说的这些,而从来不是任何规范的一部分;更确切地说,它是由Apple发起的一项特性。把这项功能从HTML标记转换到使用@viewport的CSS的规范正在顺利进行中,而且在IE10中已经部分支持。

还存在一些移动厂商特有的值。例如,Google和Apple为了与它们自己的一些服务/API相整合,已经创建了它们自己的名称/值对。我们已经在项目中使用3个这样的标记,将在下面的几个小节进行讲解。

apple-mobile-web-app-capable

这个<meta>标记显示的是“apple”,但在Android上也支持;它设定一个Web应用是否运行在全屏模式。当在全屏模式下运行的时候,不会显示任何浏览器边框。浏览器占据全部的屏幕,只显示手机的状态条。这个<meta>标记只会影响网站被加入收藏的Web应用。在我们的应用中包含了这个<meta>标记,这样如果用户选择收藏我们的应用的话,我们就可以使用尽可能多的屏幕空间:

<meta name="apple-mobile-web-app-capable" content="yes"/>

如果将content设成yes,Web应用就以全屏模式运行;否则不会。

你可以用JavaScript来判断网页是否以全屏模式显示,为此可使用window.navigator. standalone这个布尔型的只读属性。

apple-mobile-web-app-status-bar-style

正如前面已经指出的,即使在你使用apple-mobile-web-app-capable启用了全屏模式的情况下,状态栏仍然显示。这是在移动设备上开发者们无法删除的一个元素,即使是原生Web应用。然而很少有人知道,你是可以对状态栏的呈现进行一些控制的,即使只是极小的控制:我们可以使用apple-mobile-web-app-status-bar- style&lt;meta>标记影响它的颜色和透明度:

<meta name="apple-mobile-web-app-status-bar-style" content="black"/>

如果你的Web应用主要是黑色,让状态栏变得相匹配可以改善设计并让Web应用看起来更像原生应用。iOS对应的值是defaultblackblack-translucent。不幸的是(或者是幸好,考虑到某些人缺乏品味),目前你只有这些选择。

format-detection

format-detection动&lt;meta>标记启用或者禁用对网页上可能出现的手机号码的自动检测:

<meta name="format-detection" content="telephone=no"/>

默认情况下,有些设备会自动检测格式看起来像手机号码的字符串,没有链接的会自动创建,能够直接呼叫,或至少启动手机号码已经预先输入进去的手机应用。指定telephone="no"将禁用这项功能。在我们的应用中没有手机号码以及类似手机号码的任何事物,所以我们在应用中将不使用这个<meta>标记。

虽然几乎从来没有用到,<base>在涉及本地测试时还是非常有用的。<base>元素为解引用(de-referencing)相对URL提供了一个基础。举个例子,假设你的代码中有一个像<img src="image/drongo.gif"alt="Meandering Racket-TailedDrongo"/>这样的相对路径的图像。通过包含<basesrc="http://RacketTailedDrongo. com"/>,浏览器会到RacketTailedDrongo.com服务器上的image目录寻找drongo.gif[12]

这个base URL可以使用HTTP头重写,但它通常用于本地测试。试着从Web上保存一个文件到你的硬盘,然后在文件的<head>中添加一个到源服务器的base指针。当你在本地打开页面时,页面很可能在桌面环境上正确渲染,即使该文件是一个本地文件,而且你从未下载图像或者修改页面body中的路径。该语法是:

<base href="http://www.mydomain.com"/>

<link>元素没有获得称赞。它是一个强大且经常使用但却又很少被当回事的元素。<link>元素提供了在HTML文档和其他文档及资源之间定义关系的能力。<link>可被用于控制打印渲染、链接样式表和脚本、定义favicon,或者提供当前文档的替代形式。

我们的Web应用有4个link标记:

<link rel="icon" href="/appleicon.png"/>υ
<link rel="apple-touch-icon" href="/appleicon.png"/>
<link rel="apple-touch-startup-image" href="startup.png"/>
<link rel="stylesheet" href="styles.css"/>

υ IE需要添加rel="shortcut icon",在favicon没有被命名为favico.ico或者没有存储在网站根目录下的情况下,IE需要“shortcut”项。

<link>元素可以包括href、rel、type、size、hreflang、mediatitle等属性。在HTML5里面,rev和charset属性均被从<link>上剔除了。下面是语法:

<link href="url to resource" rel="type of relationship" title="title"/>

rel属性指明了从当前文档到由href属性指定的资源之间的命名关系(named relationship)。relhref属性都是必需的。

在4个<link>标记中,前三个用于图片,第四个也是你可能最熟悉的:到样式表的链接。

添加样式表<link>

这个短小精悍的<link>元素可以被用于给手机、平板电脑和桌面电脑发送不同的样式表。可以被用于根据任意类型手机的倾斜方向或用户浏览器的宽度提供不同的样式表。

尽管我们的Web应用只包含了一个样式表,但我们本可以包含几个的,每个都面向不同或重叠的媒体、浏览器大小、DPI,甚至浏览器朝向:

<link href="/css/styles.css" media="all" rel="stylesheet"/>
<link href="/css/tinylittledevice.css"
  media="only screen and (max-device-width: 480px)" rel="stylesheet"/>
<link href="/css/print.css" media="print" rel="stylesheet"/>

这些示例应该看起来很熟悉,可能有两点例外。注意下type="text/css"属性/值对没了。当前不存在其他类型的样式表语言(在可以预见的未来也没看到),所以HTML5就假定类型是text/css,并明确规定可以不写。此外,media="only screen and (max-device-width: 480px)"对你来说可能也比较陌生。我们将在下面的几个小节中把这个属性和<link>标记的其他属性一起快速讲解,并将在第7章深入有关媒体查询的细节。

<link>标记的属性

像几乎所有元素一样,<link>标记接受所有全局属性。表2-3显示的是<link>元素的其他属性。

表2-3 <link>元素属性

属  性

描  述

href

必选。“超链接引用(hyperlink reference)”是<link>目标文件的URL

media

描述将被包含的链接内容适用哪种媒体

rel

指定<link>和当前文档的关系

hreflang

被链接媒体的语言

type

被链接媒体的MIME类型。可选,除非该值不是rel关系希望的类型

sizes

新的。如果媒体是一个图标,则它定义了该图标的尺寸

media属性

media属性描述了将被包含的链接内容是针对哪种媒体。如果没有声明,默认是all,表明由href属性描述的源将一直出现。

media的值曾经相当有限,例如针对桌面环境的screen和针对打印机的print等。现在包括screen、tty、tv、projection、handheld、print、braille、auralall。现在你可以包括@media查询。media属性的值已经随着CSS3大大增加了。我们现在可以基于media属性更深奥的值提供不同的样式表。举个例子,移动设备的翻转和桌面浏览器的大小调整将把屏幕宽高比从纵向模式变成横向模式并再次返回,所以你可以相对于处于纵向模式和处于横向模式的不同情况下提供不同的CSS文件:

<link rel="stylesheet" media="all and  (orientation:portait)" href="prtrt.css"/>
<link rel="stylesheet" media="all and (orientation:landscape)" href="lndscp.css"/>

CSS3新的@media查询是media属性可以接受的值。在该属性的值中新近可以接受的关键词如下所列。

曾经是HTML 4的一些<link>属性后来被从HTML5规范中剔除了,包括cords``、shape、urn、target、charset、methodsrev属性。此外,该元素的title属性具有特定的语义。

rel属性

rel属性指定了从当前文档到href属性指定的资源的命名关系。rel属性从规范上来讲是可选的,但如果你没有包含它,浏览器将不会正确地把资源链接到文档。没有rel="stylesheet"的样式表链接可能无法正确地呈现任何样式:浏览器将仅下载该文件,然后会想“唉,浪费带宽啊。”(是的,浏览器能够思考,而且还经常取笑我们。)表2-4把rel属性的一些值和这些值的释义一起列了出来。

表2-4 rel属性

rel属性值

释  义

stylesheet

rel属性最常用的值,告诉浏览器链接的文件应用于渲染当前文档的呈现
在包含stylesheet的情况下,type="text/css"不再是一个必需的属性/值对,因为text/css是样式表语言的唯一类型,从而是可以推断出来的

next

该链接指向一个引导性浏览或一个有序系列中的下一篇文档。该规范最初用来辅助后续文档的预加载,提升用户体验

prev

该链接指向一个引导性浏览或者一个有序系列中的上一篇文档

index

该文档的索引

help

该链接指向一个帮助文档(例如,对一个大背景的描述或者提供了与本文相关的更多链接),旨在帮助迷失方向的用户重定位

contents

链接到包含当前文档或网站目录的一个文档

alternate

指定该文档的一个替代版本。当与hreflang属性一起使用的时候,意味着链接的文件是该文档的一篇译文。当与media属性一起使用的时候,意味着链接的文件是一个媒体专用版本,例如打印机。当与stylesheet结合的时候,表示还有一个可供用户选择的备选样式表

copyright

指向该文档或网站的版权声明

glossary

包含当前文档所使用的术语定义的文档

icon

该页面或网站的网站图标(favicon)

apple-touch-icon

定义了当一个Web应用被用户收藏并添加到屏幕时,在用户屏幕上显示哪个图标

apple-touch- startup-image

在该Web应用启动时显示的启动图像。对离线Web应用尤其有帮助。如果没有包含该引用,有些浏览器会显示Web应用最后一次使用时的屏幕快照

Android和iOS都支持apple-touch-iconapple-touch-startup- image。Windows Phone使用图块[13](tile)而不是图标。要包含图块信息,添加:

<meta name="msapplication-TileColor" content="#<color>"/>
<meta name="msapplication-TileImage" content="<image reference>"/>

<style>

<style>元素提供了一种添加样式到文档的方法。与通过<link>元素导入的样式不同,包含在页面头中<style>标记中的样式只适用于当前页面,因而对于其他文档而言无法在缓存中直接读取使用。与在一个元素上使用style属性添加的样式也不同,该样式只影响该style属性所在的元素,除非支持了scoped属性,包含在<style>里面的样式适用于整个文档中相匹配的选择器。

<style>属性过去要求具有type属性(通常是type="text/css")。在HTML5中可以忽略,在这种情况下使用"text/css"值的type属性是隐式存在的。与像<link>标记一样,<style>也接受media属性。

scoped属性是HTML5新增的,但还没被任何浏览器支持。为<style>元素添加scoped属性就告诉渲染代理(rendering agent)在该范围或区段内查找样式,应用这些CSS。这对于你在非你控制的网站上创建小挂件非常有帮助,确保了针对小挂件的CSS不会不小心覆盖了宿主网站的CSS。

<style>和移动性能:标准反模式。在过去的12年里,一直都建议使用<link>而不是<style>来包含全站范围的样式。通过<style>来包含CSS可能会减少HTTP请求的数量,但它无法缓存。这显然不是最优的。

由于额外HTTP请求等待时间的问题,一个移动类反模式出现了。

为了减少等待时间,站点CSS被内嵌包含在主响应的一个或多个style标记内部。style代码块(block)被使用JavaScript提取并作为localStorage保存起来,并把key的值添加到了cookie字符串。额外的HTTP请求包含了带着在localStorage中存储的样式名称的cookie。在服务端,服务器读取该cookie,检查还需要哪些资源(如果有的话),然后只返回在localStorage中还没有的嵌入在第一个响应中的文件。这导致第一次请求的下载很大,而后续请求的下载就小得多,以及初始的网站加载和所有后续的网站重新加载都是单次HTTP请求和响应。

虽然这是一种反模式,但减少HTTP请求的数量可以大大地提升性能。性能的提升和发送相当数量的大文件(其内容无论如何都是必需的)及访问存储在localStorage中数据的代价相比完全更有价值。

添加<script>到网页

<script>标记能够让我们包含JavaScript代码块或链接到外部的JavaScript(或其他脚本类型)文件。type属性在XHTML中是必需的,而且几乎永远是type="text/javascript"。在HTML5中,type被假定为text/javascript。只要你的脚本是JavaScripttype属性就应该省略。还有,它的language属性也是过时的了。

在包含了src的情况下,该元素可能看起来像是空的,因为在开始和结束标记之间没有任何文本。总之要包含一个完整的结束标记,还有就是不要在这些标记之间放置任何JavaScript代码。

JavaScript性能小贴士。虽然我们正在讨论的是位于文档的<head>内的元素,但是在文档的<body><head>内部都能看到<script>元素的存在,而且有时候(其实是经常性地)body的末尾是<script>元素的最佳位置。

为什么?因为JavaScript通常会在一下载完就立刻被解析,会把它这一条通路上的文档下载挂起,直到该JavaScrip完成下载、解析和执行。这将使感觉上的页面下载时间大大变慢。基于这个原因,建议把脚本包含在接近文档末尾的地方,而不是在<head>中。

在页面所有元素花时间下载、解析和执行期间内,要把你的访客当成非JavaScript用户。难道你不愿让他们看到一些内容而不是一个空白屏幕吗?这就是为什么JavaScript性能以及源代码顺序很重要的原因。

有两个属性可以改变JavaScript的执行顺序:defer属性和async属性。都是布尔型,async是HTML5新增的。async表明该脚本变得可用时应该异步执行。defer表明该脚本应该在文档解析完成后再执行。如果任一属性都不存在,那么一遇到JavaScript就开始解析。两个属性都只对外部脚本有效,内置脚本无效。

如前所述,JavaScript是一碰到就立即解析(除非包含了asyncdefer,而且浏览器还支持)。浏览器会停止从服务器上下载另外的元素,直到JavaScript被完全下载、解析和执行。通过在文档末尾而不是头部包含JavaScript,感觉上的下载时间被大大缩短了。当脚本位于<head>中时,页面在加载和执行JavaScript的时候会挂起。把<script>放在页脚,虽然下载和执行脚本实际上会花费同样的时间,但因为没有明显的没有响应,所以感觉上是下载得更快了。

在HTML5中有一个新的解决方案,可以用于解决因为耗时的JavaScript引起的UI挂起问题。将在第6章进行描述的Web Workers,使JavaScript的多线程能够并发执行。动态生成脚本标签是提升性能的另一个技巧。

用户关闭JavaScript时——<noscript>

你可以包含一个<noscript>元素,该元素的内容只有在用户禁用JavaScript时可见。一般来说,最好渐进地增强页面的静态功能,让<noscript>成为过去就好。然而有一些项目经理坚决主张网站要完全依托JavaScript。在这种情况下,你可以在文档的body中使用<noscript>包含一个指南,告诉用户如何再次启用JavaScript。JavaScript在所有移动浏览器和其他现代浏览器中是默认启用了的,包括 mobile WebKi、Blink、Opera Mobile、Windows和Firefox。

元素之<body>

<body>永远是<html>元素的第二个也是最后一个子元素,第一个子元素是<head>。在浏览器主窗口中显示给用户的所有内容都存在<boby>元素里面。<head>包含了页面所有的元数据,<body>包含了所有可见(而且偶尔有一些不可见)的内容。

下一章讨论实际地显示到客户端的元素:<body>元素及其所有子元素。如前面讨论必需的元素时已经提到的,<body>元素没有元素特有的属性,但有很多事件处理器,包括:

最好把这些事件处理器包含在外部JavaScript中,而不是在<body>元素中。我把它们包含在这里这样你就知道哪些是可用的,但我强烈建议并完全鼓励你保持内容和呈现分离,也与行为分离。

现在是时候关注在我们页面的实际内容了。

[1] 要查看改变了的元素和属性可参阅http://www.w3.org/TR/html5-diff/,另外还有过时了的元素和属性。

[2] 译者注:短语元素(phrase element)是内联元素的一种类型,用于在块或结构化元素中描述词或短语,主要是给文本片段添加结构化信息。每一种短语元素都表示一种特定的语义,例如<strong>、<blockquote>、<cite>、<code> 等。参见http://en.wikipedia.org/wiki/HTML_element#Phrase_elements

[3] 布尔属性是如果有赋值就是true,没有赋值就是false的属性。XHTML中的例子包括readonly=“readonly”、checked=“checked”以及disabled=“disabled”,这些在HTML5中可以(而且是应该)分别写成readonly、checked或者disabled。

[4] 译者注:指点设备,指的是可以在屏幕上控制指针的移动进行选择的设备,如鼠标、轨迹球、摇杆、触摸板和手写笔等。参见http://en.wikipedia.org/wiki/Pointing_device

[5] 译者注:例如,链接一个外部样式表。

[6] 译者注:参见http://en.wikipedia.org/wiki/CamelCase

[7] HTML5 DTD会使较旧的IE桌面浏览器进入非标准(quirk)模式。

[8] 过期特性请见http://bit.ly/16t5Z6L

[9] modernizr是一个JavaScript类库,用于在用户浏览器中检测HTML5和CSS3特性的浏览器支持情况。

[10] 使用CSS来显示<head>的内容是可行的。

[11] 在大多数小设备上,浏览器是自动全屏而且不是用户可改变的。在某些设备上,例如平板电脑,浏览器是可以调整大小的。

[12] 你想知道为什么我不断提到Racket-tailed Drongo吗?因为它就是本书封面上的鸟。

[13] 译者注:Windows Phone的图块,指的是“开始”屏幕上代表应用程序的图像。详见http://msdn. microsoft.com/zh-cn/library/windowsphone/develop/hh202948(v=vs.105).aspx


相关图书

HTML+CSS+JavaScript完全自学教程
HTML+CSS+JavaScript完全自学教程
零基础入门学习Web开发(HTML5 & CSS3)
零基础入门学习Web开发(HTML5 & CSS3)
HTML CSS JavaScript入门经典 第3版
HTML CSS JavaScript入门经典 第3版
HTML+CSS+JavaScript网页制作 从入门到精通
HTML+CSS+JavaScript网页制作 从入门到精通
从0到1:HTML5 Canvas动画开发
从0到1:HTML5 Canvas动画开发
从零开始:HTML5+CSS3快速入门教程
从零开始:HTML5+CSS3快速入门教程

相关文章

相关课程