1. 1. 了解存在的问题
    1. 1.1. 浏览器开发商的文档
    2. 1.2. 第三方文档
  2. 2. 让事情变得简单
    1. 2.1. 优雅降级是web开发者的最佳朋友
      1. 2.1.1. HTML的输入框类型
      2. 2.1.2. CSS的特性选择器
      3. 2.1.3. 表单按钮
    2. 2.2. 放弃CSS
  3. 3. 特征检测和polyfill
    1. 3.1. “不起眼的“JavaScript
    2. 3.2. Modernizr库
    3. 3.3. 关注性能
  4. 4. 结论

所有的web开发者都会很快(或者很痛苦地)意识到Web是一个粗糙的环境,其中最糟糕的一点就是老旧的浏览器。提到“老旧浏览器”,我们脑海中往往复现的就是旧版的IE。但其实老旧浏览器不止这一种,一个一年前的Firefox,比如ESR版本也算得上老旧了。至于移动端,由于有些浏览器和操作系统都不能升级,这就导致了许多老旧的安卓手机或iPhone上的浏览器不是最新的,这些也算是老旧浏览器。

令人沮丧的是,我们工作的一部分都要耗在老旧浏览器这片荒野上。但幸运的是,有一些技巧可以协助解决由老旧浏览器引起的80%的问题。

了解存在的问题

实际上,首要的任务是阅读这些浏览器的文档、试着理解其公共部分。比如,CSS的支持程度是HTML表单的一个重大问题,若你刚开始开发,应先检查下要用的元素(或DMO接口)的支持程度。虽然许多web页面要用的元素、属性、API的兼容性表格,MDN上都有;但别的资源也能提供很大的帮助:

浏览器开发商的文档

第三方文档

  • Can I Use上有各类技术的支持程度信息。
  • Quirks Mode是关于浏览器兼容性的一个极好资源。其移动部分是现在最好的。
  • Position Is Everything是一份关于老旧浏览器渲染问题及其解决方法的最好资料。
  • Mobile HTML5 有着大量移动端浏览器兼容性信息,不只有那些“前5的浏览器”(译注:大概包括苹果、安卓、Nokia、Amazon、Blackberry)

让事情变得简单

由于HTML表单包含了大量复杂的交互,我们得记住一条法则:keep it as simple as possible。许多情况下我们会想让表单变得“漂亮”或“带有高级功能”,但构建高效的HTML表单并不单靠设计或技术就能解决,建议花点时间阅读下forms usability on UX For The Masses这篇文章.

优雅降级是web开发者的最佳朋友

优雅降级和渐进增强这两个开发模式通过同时支持众多的浏览器,能让你建立伟大的产品。当你在现代浏览器上构建了一些东西,并想确保它能在老旧浏览器上运行时,你就是在使用优雅降级了。

接下来我们看些关于HTML表单的例子:

HTML的输入框类型

HTML5带来的输入框类型非常酷,因为它们作降级处理的方法是可预见的。若浏览器不认识<input>元素的type特性值,就会回退到text类型。

1
2
3
4
<label for="myColor">
Pick a color
<input type="color" id="myColor" name="color">
</label>
chrome 24 Firefox 18

CSS的特性选择器

CSS的特性选择器对HTML表单来讲非常有用,但某些老旧的浏览器并不支持它。此时我们常会用一个等价的类名来替代该特性:

1
<input type="number" class="number">
1
2
3
4
5
6
7
input[type=number] {
/* 这里的样式会在某些浏览器下失效 */
}
input.number {
/* 该处样式可以在每个地方都生效 */
}

要注意下面的代码是没有必要的(冗余),而且也会在某些浏览器下失效:

1
2
3
4
5
input[type=number],
input.number {
/* 这里的样式会在某些浏览器下失效,因为它们若不能失败其中一个选择器,
就会跳过整段规则 */
}

表单按钮

在HTML表单中定义按钮有两种方式:

  • <input>元素的type特性设为button, submit, resetimage
  • <button>元素

若你想使用元素选择器来指定CSS,使用<input>元素的话会有些麻烦:

1
<input type="button" class="button" value="click me">
1
2
3
4
5
6
7
8
9
10
11
12
13
14
input {
/* 这处规则会覆盖input定义的按钮的默认样式 */
border: 1px solid #CCC;
}
input.button {
/* 这里并不会恢复默认样式 */
border: none;
}
input.button {
/* 这里也不会恢复!实际上在所有浏览器下都没有方法来做到这点。 */
border: auto;
}

使用<button>元素则要面对两个问题:

  • 老旧IE下会有一个bug,当用户点击按钮时,发送的不是value特性的内容,而是<button>元素起止标签间的HTML内容。当然个问题只有当你想发送value的值时才会凸显,例如,你可能想处理关于用户点击了哪个按钮的数据。
  • 某些非常老旧的浏览器不会吧submit作为type特性的默认值,故而还是推荐你总是设置<button>元素的type特性。
1
2
3
4
<!-- 有时点击该按钮会发送"<em>Do A</em>"而不是"A" -->
<button type="submit" name="IWantTo" value="A">
<em>Do A</em>
</button>

选择这两种元素中的哪种,取决于你项目中的约束。

放弃CSS

HTML表单和老旧浏览器的最大问题是对CSS的支持。如你在表单组件的属性兼容性表一文中所见到的,这很难处理。即使在文本元素上可能可以做些微调(比如大小和颜色),但通常也会有副作用。所以剩下的最佳方式就是不要给HTML表单组件添加一点样式,不过你仍可以给周边元素添加样式。作为专业人士,若你遇到你的客户一定需要给表单组件加样式,可以调研下某些困难的技术,譬如用JavaScript重构表单组件。但其实在这种情况下,你应该毫不犹豫地指出客户的愚蠢之处

特征检测和polyfill

虽然在现代浏览器上JavaScript是个很棒的技术,但在老旧浏览器上使用它却有很多问题。

“不起眼的“JavaScript

JavaScript最大的问题就是API的可用性。因此,最佳实践是使用”不起眼的“JavaScript。这是一种开发模式,规定了两个要求:

  • 结构和行为严格分离。
  • 如果代码挂掉,页面内容和基本的功能必须还有可访问性和可用性。

The principles of unobtrusive JavaScript一文很好地阐述了该观点。(该文由Peter-Paul Koch为Dev.Opera.com撰写,现已移至Docs.WebPlatform.org)

Modernizr库

多数情况下,一个好的”polyfill“可以帮我们提供那些缺失的API。所谓的polyfill,是指一小段用于“填补”老旧浏览器功能上的坑的JavaScript。它们可以用于提供任何功能上的支持,相比CSS或HTML的polyfill,为JavaScript使用polyfill会有更小的风险;毕竟JavaScript会在很多情况下挂掉(比如网络问题、代码冲突等等)。但即使不用polyfill,只要你开发时心中存有“不起眼的“JavaScript原则,其实也没什么大不了。

为缺失的API提供polyfill,最佳的方式是使用Modernizr库及其衍生项目YepNoep。Modernizr是一个能测试功能可用性、并以此来做相应动作的库。YepNoep则是一个按条件作加载的库。

举个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Modernizr.load({
// 此处测试浏览器是否支持HTML5的表单校验API
test : Modernizr.formvalidation,
// 若浏览器不支持,则加载下列polyfill
nope : form-validation-API-polyfill.js,
// 在任何情况下,依赖那个API的核心App文件都会被下载
both : app.js,
// 一旦这些文件都被加载了,下面的函数调用就会来初始化App
complete : function () {
app.init();
}
});

Modernizr团队还维护了一个好用的polyfill列表,请按需自取。

注意:在使用“不起眼的“JavaScript原则和优雅降级技术时,Modernizr其它一些很棒的特性也能帮到你。请阅读Modernizr的文档

关注性能

即使像Modernizr已经很注重性能了,但加载200kB的polyfill仍会影响应用的性能,这对老旧浏览器来讲更为严重。许多老旧浏览器的JavaScript引擎很慢,这样会让polyfill的执行给用户造成不好的体验。性能是本身就是一个主题,老旧浏览器对性能更是敏感:首先它们就很慢,再者依赖越多的polyfill它们就得执行更多的JavaScript。所以,相比现代浏览器,老旧浏览器有着双重的负担;也因此对代码在老旧浏览器上的实际运行情况,更要进行测试。甚至有时为了性能,相比在所有浏览器上实现相同功能,还得在老旧浏览器移除某些些会带来更好用户体验的功能。最后还有一个建议,多考虑下你的终端用户吧。

结论

如你所见,处理老旧浏览器所涉及的内容不止有表单。这是一整套的技术,全面掌握它们已经超出了本文的范围。

如果已经读完了这个HTML表单指南的全部文章,你应该能很轻松地使用表单了。若你还发现了哪些新技术、新技巧,也请帮助完善这个指南