HTML5-样板文件的-Web开发-全-

HTML5 样板文件的 Web开发(全)

原文:zh.annas-archive.org/md5/8C583EAEFA986CBF606CD0A7F72F11BE

译者:飞龙

协议:CC BY-NC-SA 4.0

前言

使用 HTML5 Boilerplate 入门将使您能够轻松掌握设置新项目并以最有效的方式将其部署到生产环境的方法,同时确保强大的性能。它将带您逐步创建网站,并教您充分利用 HTML5 Boilerplate 中提供的默认设置,无论是样式、标记还是代码,以便您尽可能少地解决跨浏览器问题来实现您的目标。

本书涵盖了什么内容

第一章, 在我们开始之前,涵盖了您需要为项目设置 HTML5 Boilerplate 而不费吹灰之力的一切。我们还广泛地研究了作为该项目一部分包含的文件以及它们如何帮助您。

第二章, 开始您的项目,涵盖了如何使用示例单页面网站开始使用 HTML5 Boilerplate。在本章中,我们将研究配置默认设置的基本要点,这些设置适用于您的项目。

第三章,创建您的网站,涵盖了如何自定义网站的样式和标记,以及如何利用 HTML5 Boilerplate 的默认样式选项的一些技巧。

第四章, 添加交互性和完成您的网站,将帮助您发现如何进行特性检测,使用 JavaScript 添加一些交互性,并完成您的网站实现。

第五章, 自定义服务器,介绍了如何通过使用 HTML5 Boilerplate 为托管您的网站的 Web 服务器定制配置,以确保您的网站尽快加载。

第六章, 让您的网站更好,探讨了可以用来为您的网站用户提供更好体验的可选功能,这些功能与 HTML5 Boilerplate 非常匹配。

第七章, 使用构建脚本自动部署,通过查看提供工具来压缩 CSS、JS、HTML 和图像的构建脚本,帮助您使您的网站准备好上线。

附录,您是专家,现在怎么办?涵盖了一些单元测试的基础知识,并提供了有关 HTML5 Boilerplate 提供的功能决策的额外研究信息。

您需要为本书做好准备

由于我们将在网站上工作,我们将需要以下基本工具来完成我们的工作:

  • 一个您习惯使用的文本编辑器;推荐使用SublimeText。如果您还没有,请从sublimetext.com/下载。

  • Apache Web 服务器(可从httpd.apache.org获取)以应用 HTML5 Boilerplate 的服务器配置。

  • 一个浏览器来验证您的网站在屏幕上的渲染。推荐使用 Chrome,因为它的开发者工具可用于调试。从google.com/chrome下载 Chrome。

  • Git,用于确保软件处于版本控制下;从git-scm.com下载。

  • 您显然还需要 HTML5 Boilerplate,您可以从html5boilerplate.com下载。

本书适合谁

这本书是为所有熟悉使用 HTML、CSS 和 JavaScript 创建 Web 项目的作者而写的。不需要深入的知识。了解 Web 服务器是什么以及如何配置是有好处的。此外,您不应该害怕使用命令行工具(不要害怕!书中有链接可以帮助您减少恐惧)。我们不指望您了解 HTML5 Boilerplate,只是让您尝试一次,看看它是否适合您。

约定

在这本书中,您会发现许多不同类型信息的文本样式。以下是一些样式的示例,以及它们的含义解释。

文本中的代码单词显示如下:“但是,Normalize.css确保这些默认样式在所有浏览器中保持一致。”

代码块设置如下:

header h1 {
background-image: url('/img/heading-banner.png');
width: 800px;
height: 300px;
}

新术语重要单词以粗体显示。您在屏幕上看到的单词,例如菜单或对话框中的单词,会以这种方式出现在文本中:“以下屏幕截图显示了当用户将键盘焦点切换到“跳过导航”链接时,它是如何立即可见的。”

注意

警告或重要提示出现在这样的框中。

提示

提示和技巧会以这种方式出现。

第一章:在我们开始之前

当您开始一个新项目时,您会有多么高兴?我也是!新项目文件夹的气味非常令人兴奋。不幸的是,它很快就变成了一堆文件夹,子文件夹和匆忙编写的标记,然后你就知道了,这是发布日,你恐惧地意识到你的页面缺少一些基本的元数据(嗯,那些网站图标!),一些部分在某些浏览器中无法阅读——什么?打印时也需要好看?

HTML5 Boilerplate 的诞生是因为从头开始并错过了重要部分而感到沮丧。拥有一个清单并不像从一个已经带有您的清单所需文件的项目开始那么有用。

HTML5 Boilerplate 为您提供了最好的工具,让您可以开始下一个 Web 开发项目。

HTML5 Boilerplate 的特点

在我们深入了解 HTML5 Boilerplate 的内部之前,让我们看看它的一些特点,这些特点将帮助您在下一个项目中使用。HTML5 Boilerplate 可以从html5boilerplate.com下载,并且根据 MIT 许可证可用于任何免费或商业产品。源代码可以在 Github 的 URL 上找到,即github.com/h5bp/html5-boilerplate/

跨浏览器兼容性

HTML5 Boilerplate 带有一组文件,可以轻松进行跨浏览器开发。

文档类型

跨浏览器兼容性最重要的原因是使用不正确的文档类型声明。通过使用 HTML5 文档类型声明,您可以确保浏览器以标准模式呈现您的网站。

注意

如果您对文档类型有兴趣,我在nimbupani.com/the-truth-about-doctypes.html上详细介绍了它。

Normalize.css

浏览器会在您未指定属性的元素上应用它们的默认样式。问题是,每个浏览器应用的样式是不同的。但是,Normalize.css确保这些默认样式在所有浏览器中保持一致。

注意

Nicolas Gallagher 在necolas.github.com/normalize.css/上详细介绍了Normalize.css背后的动机。

清除浮动

Clearfix 一直是清除浮动的一种流行方式。在 HTML5 Boilerplate 中,这已经简化为使用微清除解决方案,这是一组更小的选择器,可以实现相同的目标,并经过测试和验证,可以在 Opera 9 及更高版本,Safari 4 及更高版本,IE6 及更高版本,Firefox 3.5 及更高版本以及 Chrome 上使用。

注意

微清除解决方案的发明者 Nicolas Gallagher 在nicolasgallagher.com/micro-clearfix-hack/上更详细地介绍了使用的声明背后的选择。

搜索框样式

当您将输入元素的类型设置为搜索时,所有 WebKit 浏览器(如 Safari,Chrome,Mobile Safari,以及即将推出的)都会添加难以样式化的 UI chrome。HTML5 Boilerplate 带有一组样式,可以使搜索框在所有浏览器中的外观和感觉保持一致,同时也很容易进行样式设置。

条件类

index.html页面带有一组类,可以在 HTML 元素上轻松调整样式,以适应低于 9 的 IE 版本。

Modernizr

Modernizr 是一个 JavaScript 库,用于测试 HTML5 技术的存在,并根据加载您网站的浏览器中的存在或不存在输出一组类。例如,如果浏览器不支持边框半径,Modernizr 会输出类no-borderradius,而在支持边框半径的浏览器上,它将输出类borderradius。Boilerplate 中包含了 Modernizr 的自定义构建。

注意

modernizr.com/docs/www.slideshare.net/michaelenslow/its-a-mod-world-a-practical-guide-to-rocking-modernizr的幻灯片中了解有关使用 Modernizr 的更多信息。

没有 console.log 错误

在现代浏览器中工作时,通常会使用console.log函数来调试 JavaScript 代码。有多少次你忘记在生产中删除或注释掉它们,结果发现它们在不支持该函数使用的 Internet Explorer 或其他浏览器中抛出错误?你可以安全地使用plugin.js文件中包含的log函数,只在支持它的浏览器中记录语句。

辅助类

曾经需要隐藏文本来显示图片吗?如何为使用屏幕阅读器的人提供额外的文本或在所有浏览器中隐藏?HTML5 Boilerplate 提供了这两种情况的类,经过实地测试,可以在各种情况和所有浏览器中使用。

性能优化

.htaccess文件包含了最佳的缓存默认设置,这使得当页面由 Apache Web 服务器提供时,页面加载速度显著加快。还有其他 Web 服务器的配置文件可提供类似的功能。

渐进增强

HTML 元素有一个no-js类,可以用于为不支持 JavaScript 的浏览器提供替代样式。使用 Modernizr 时,当在支持 JavaScript 的浏览器中使用时,这个类名会被替换为js

可访问的焦点样式

所有浏览器在点击链接时都会提供默认的焦点样式。HTML5 Boilerplate 确保这些样式仅在使用键盘导航时元素处于焦点状态时应用。

打印样式

一个良好的默认打印样式是我们在创建网页时经常忽略的东西。然而,HTML5 Boilerplate 已经为您提供了最佳性能的默认打印样式。

开始使用的工具

你可以使用你喜欢的编辑器开始使用 Boilerplate。如果你使用 Git 作为你的版本控制系统,我们还包括一个.gitignore文件,它会自动忽略文件,如.DS_STORE或其他不必要的文件,不会被标记为版本。可以用来处理 HTML5 Boilerplate 的一些编辑器如下:

注意

这些工具并非由 HTML5 Boilerplate 项目官方维护,因此可能已经过时。最好使用下一节中概述的流程。

获取文件的位置

有三种获取 HTML5 Boilerplate 的方法,如下:

  • 从网站上:项目的最新稳定版本可在html5boilerplate.com上获得。

  • 来自 Initializr:Jonathan Verecchia 在initializr.com上托管了一个更广泛的模块选择。这里的所有模块都来自该网站上可用的稳定版本。

  • 从 Github 主页:HTML5 Boilerplate 托管在 Github 上。最新文件可从项目的 github 页面github.com/h5bp/html5-boilerplate获取。您可以放心地在启动新项目时使用这些文件,并且在从 Github 下载时保证获得这些文件的最新版本。

由于您刚刚开始使用 HTML5 Boilerplate,我强烈建议您从 Github 下载文件,甚至更好地通过 Git 这样做,这样当 Github 上的主文件更新时,您可以轻松更新它们。

注意

如果您对 Git 不熟悉,Roger Dudler 在 rogerdudler.github.com/git-guide/上维护了一个很好的入门介绍;如果您对版本控制的概念不熟悉,可以在hoth.entp.com/output/git_for_designers.html上找到一个很好的解释。

H5BP 文件概述

HTML5 Boilerplate 的不同文件和文件夹解释如下:

  • index.html:这是我们建议您使用的所有 HTML 页面的标记。

  • main.css:样式位于名为main.css的单个样式表中,位于css文件夹中。

  • normalize.css:此文件位于单独位置,以便您可以立即使用最新更新的normalize.css版本。在生产中,理想情况下,您应将main.cssnormalize.css合并为单个文件,以确保网络请求的最小数量,从而使您的页面加载更快。

  • doc:此文件夹包含了理解 HTML5 Boilerplate 文件所需的所有文档。

  • img:此文件夹应包含您将用于创建网站的所有图像。一开始是空的,但您应该在这里包含您使用的所有图像。

  • js:这是所有脚本的父文件夹。HTML5 Boilerplate 附带了一组脚本,使您更容易入门。此文件夹包含以下文件和文件夹:

  • vendor:此文件夹包含所有脚本库。您可以获取最新的压缩和未压缩版本的 jQuery 以及现代化的自定义版本。您将使用的任何其他库理想情况下都应放在此文件夹中。

  • plugins.js:您将使用的所有 jQuery 插件都应内联在此文件中。如果您使用了 jQuery 轮播插件,您将把代码复制到plugins.js中。

  • main.js:这将是您调用在页面上运行的脚本的文件。以 jQuery 轮播插件为例,我们将从此文件中调用插件在我们的页面上运行。

  • 404.html:如果您有一个找不到的页面,那么可以提供此页面。确保它包含所有可用的信息,并且与网站中的其他页面具有相同的外观和感觉。

  • humans.txt:这是一个很棒的倡议,允许您指明谁在网站上工作(在 humanstxt.org 上阅读更多关于此倡议的信息)。我们强烈建议您使用此功能来指示您的工作,并告知任何好奇的人,这是谁的工作。

  • crossdomain.xml:如果您希望将 Flash 文件托管在其他地方以访问位于您的网站将托管的域上的资产,则此文件非常有用。您可以使用另一个域中的 Flash 音频播放器来使用托管在您的网站上的文件。在这种情况下,您需要仔细选择您的跨域策略(我们将在第五章中详细介绍此文件,自定义服务器)。

  • robots.txt:搜索引擎使用此文件来了解哪些文件要索引,哪些不要索引。

  • .htaccess:这是特定于您的网站的 Apache 服务器配置文件。默认情况下包含了大量最佳实践。

  • favicion.ico:大多数浏览器在您收藏网站上的页面或在标签上的页面标题旁边时使用网站图标。通过使用一个独特的可识别的图标,您将能够使您的网站脱颖而出,并且易于导航到。

  • apple-touch-icon-*.png:iOS 和 Android 设备允许将网站添加到手机主屏幕的书签。它们都使用这些触摸图标来表示您的网站。Boilerplate 附带了一组图标,以识别您需要创建图标的所有尺寸和格式。

  • readme.md:readme 包含了所有的许可信息,以及关于使用这些文件的功能和获取更多信息的列表。

寻求帮助

现在我们已经知道这些文件是什么,以及从哪里获取它们,重要的是您要熟悉如何寻求帮助,最重要的是在哪里寻求帮助。请记住,大多数 HTML5 Boilerplate 项目的维护者都是在业余时间工作。您在明确表达需要帮助的内容方面花费的时间越多,他们就能越快、越好地帮助您。以下是如何寻求帮助:

  • 隔离问题:确切的问题是什么?使用 dabblet.com、codepen.io、jsfiddle.net 或 jsbin.com 创建一个最少标记、样式和脚本的测试案例来重现问题。大多数情况下,这样做本身就会让您找到问题所在。

  • 如果您能够重现这个问题并将其隔离为 HTML5 Boilerplate 功能引起的问题,请转到github.com/h5bp/html5boilerplate.com/issues,使用搜索字段检查是否已经报告过。如果没有,请创建一个新问题,并附上测试案例的链接。

  • 如果这个问题不是 HTML5 Boilerplate 的结果,而是您无法确定的交互作用,请转到stackoverflow.com/questions/tagged/html5boilerplate,创建一个链接到隔离测试案例的问题。确保将问题标记为 html5boilerplate 或 h5bp,这样维护者中的一个就可以迅速回答。

  • 如果问题小到可以在 Twitter 上提问,请在twitter.com/h5bp上发推文,附上测试案例的链接以及您需要帮助的具体部分。

注意

Lea Verou 在coding.smashingmagazine.com/2011/09/07/help-the-community-report-browser-bugs/上写了一篇关于提交浏览器错误报告的好文章,同样适用于寻求任何开源网页开发项目的帮助。

总结

在这一章中,我们已经了解了为什么 HTML5 Boilerplate 是网页开发者的绝佳工具箱。此外,我们已经了解了哪些功能对您的网页开发项目最有用,以及 HTML5 Boilerplate 中的每个文件都做了什么。我们还花了一些时间看看从哪里获取 HTML5 Boilerplate 的文件以及如何寻求帮助。在下一章中,我们将开始使用 HTML5 Boilerplate 进行一个示例项目。

第二章:开始你的项目

你希望尽快开始你的项目,并在本章中我们将看到一些使用 HTML5 Boilerplate 的最快方法。

有许多种 HTML5 Boilerplate 可供选择,我们将研究一些创建起始文件夹的机制,并查看一旦开始后你可以处理的即时任务。

创建你的初始项目文件夹

HTML5 Boilerplate 可以从网站上以三个版本获得,就像我们在上一章中看到的那样。以下是使用最新文件的两种最快方法:

  • 下载 HTML5 Boilerplate 的最新版本,用于你开始的每个新项目

  • 维护 HTML5 Boilerplate 的本地最新副本,并使用脚本将文件复制到你的项目中

现在我们将看看这两种方式。

下载 HTML5 Boilerplate 的最新版本

这是使用 HTML5 Boilerplate 最新文件的最简单方法。如果你熟悉 Git,你可以将 HTML5 Boilerplate 下载为一个文件夹。在你的命令行界面中,导航到你通常存储项目的文件夹,然后在命令行界面中输入以下命令:

git clone git://github.com/h5bp/html5-boilerplate.git

这将在该文件夹中下载一个名为html5-boilerplate的文件夹。然后你可以将其重命名为你自己的项目并开始使用。

如果你不熟悉命令行界面,你可以将最新文件下载为 ZIP 文件并解压到一个你想要使用的项目的文件夹中。

如果你觉得这些选项很繁琐,我建议你使用 shell 脚本。但是,这需要你已经设置好 Git 并熟悉命令行界面。

注意

如果你使用 Windows,请确保下载Cygwin,网址为sources.redhat.com/cygwin/cygwin-ug-net/cygwin-ug-net.html,并在输入我提到的所有命令行时使用它。

nathanj.github.com/gitguide/tour.html上还有一个关于在 Windows 上设置和使用 Git 的图解指南。

使用 shell 脚本

使用这个脚本,我们将为 HTML5 Boilerplate 设置一个本地存储库,以便随着项目中的更改进行更新。

前往你想要存储最新 HTML5 Boilerplate 文件副本的文件夹。在我的情况下,我想将它保存在一个名为source的文件夹中。

然后,使用前一节中提到的相同命令行脚本来下载文件的最新副本。脚本如下:

git clone git://github.com/h5bp/html5-boilerplate.git

我们将让这个文件夹保持原样,而不是重命名文件夹。接下来,我们将把createproject.sh shell 脚本复制到这个文件夹中。

在你的 shell 中,导航到html5 Boilerplate文件夹,并按照以下命令行脚本中所示下载createproject.sh文件:

curl https://raw.github.com/h5bp/ant-build-script/master/createproject.sh > createproject.sh

确保它是可执行的,通过在 shell 中执行以下命令:

chmod +x createproject.sh

这些命令行脚本的执行如下截图所示:

使用 shell 脚本

然后从命令行执行以下脚本:

./createproject.sh <project-name>

这将在html5-boilerplate文件夹的父文件夹中创建一个以项目名称命名的文件夹。如果你希望将项目文件放在其他地方,你也可以使用项目文件夹的绝对路径,如下面的脚本所示:

./createproject.sh /Users/divya/projects/<project-name>

创建我们的项目

在本书中,我们将通过一个示例项目来理解如何使用 HTML5 Boilerplate。我们所有的项目源文件都可以在nimbu.in/h5bp-book/sun-shine-festival-2012/上找到。

假设我们需要为塞内加尔达喀尔的 Ngor 和 Terou Bi 举办的一个虚构的阳光和沙滩节创建一个网站,时间是 2012 年 11 月 12 日至 2012 年 11 月 16 日。我想将这个项目标记为sun-sand-festival-2012

我将所有项目存储在一个projects文件夹中,所有框架和起始工具包存储在一个source文件夹中。

在我的源文件夹中,我有最初使用以下脚本创建的html5-boilerplate文件夹:

git clone git://github.com/h5bp/html5-boilerplate.git

我通过使用以下脚本定期从 Github 托管的主存储库中拉取最新更改来保持其最新:

git pull origin master

我还在同一个文件夹中有createproject.sh shell 脚本,我们将用它来创建我们的新项目。在 shell 界面中,我导航到html5-boilerplate文件夹并输入以下脚本:

./createproject.sh ../projects/sun-sand-festival-2012

这将创建包含所有所需文件的项目文件夹,以便开始。创建的文件如下截图所示:

创建我们的项目

House-keeping

现在我们的项目准备好了,让我们开始做一些基本的工作,这是我们在任何项目中都需要做的。在任何你习惯使用的文本编辑器中打开项目。

提示

我强烈推荐跨平台的Sublime Text文本编辑器,可从www.sublimetext.com下载。命令行大师可能想尝试使用Vim文本编辑器,可从www.vim.org下载。

设置标签

我们的index.html页面包含一些需要填写的标签:

<title></title>
<meta name="description" content="">

对于我们项目的标题标签,让我们输入以下内容:

<title>Home | Sun and Sand Festival 2012, Dakar</title>

带有name描述的meta标签在网站在搜索引擎结果中列出时非常有用。此标签将用于呈现解释此页面内容的文本片段。让我们将其设置为以下内容:

<meta name="description" content="Sun and Sand Festival is occurring between Nov 12 to Nov 16 2012 at the Ngor and Terou Bi, Dakar featuring performances by top Senegal artists">

编辑网站图标

添加网站图标是我们大多数人在开始项目时忘记做的下一个琐事。这是你可以在开始思考你将要创建的代码之前轻松达成的下一个目标。

网站图标有助于唯一标识您的网站。如下截图所示,拥有一个网站图标可以轻松识别您想要访问的标签或书签:

编辑网站图标

当你的页面被添加到 iOS 的主屏幕(如右侧的截图所示)和 Android 设备(如左侧的截图所示)时,触摸图标非常有用:

编辑网站图标

HTML5 Boilerplate 在根文件夹中附带了一组图标,这些图标的尺寸适合触摸屏图标(Android 和 iOS 设备都使用)和网站图标的所有所需图标。在制作图标时,您可以将它们用作指南。

HTML5 Boilerplate 附带以下一组图标:

  • favicon.ico:桌面浏览器用于在标签上或标题旁渲染图标的默认图标。

  • apple-touch-icon.png:如果没有指定其他内容,iOS 将使用此图标在主屏幕上呈现。不幸的是,这也意味着 iOS 将在此图标上添加自己的效果,如阴影、圆角和反射光。如果没有其他支持,这也是一个很好的后备图标格式,例如 iOS 1 和 BlackBerry OS 6。

  • apple-touch-icon-precomposed.png:这可以防止 iOS 在你的图标上应用任何效果,并使其呈现原样。提供此图标还将确保 Android 2.1 及以上设备在将你的网页添加到主屏幕时使用此图标。

  • apple-touch-icon-57x57-precomposed.png:这将被没有 Retina 显示屏的 iOS 设备使用。

  • apple-touch-icon-72x72-precomposed.png:这将被没有高分辨率显示屏的 iPad 使用。

  • apple-touch-icons-114x114-precomposed.png:这将被高分辨率的 iPhone Retina 显示屏使用。

  • apple-touch-icons-144x144-precomposed.png:这将被高分辨率的 iPad Retina 显示屏使用。

为什么我们有这么多图标的原因已经由 Mathias Bynens 在mathiasbynens.be/notes/touch-icons中记录。

注意

Hans Christian Reinl 在 drublic.de/blog/html5-boilerplate-favicons-psd-template/ 上托管了所有图标的 PSD 模板,你可以使用它来开始为你的项目创建图标。如果你需要关于如何创建这些图标的指导,Jon Hicks 在 www.netmagazine.com/features/create-perfect-favicon 上写了关于如何做的文章。

如果你有必要创建图标的图形元素,你可以开始将这些图标添加到项目的根文件夹中。当截止日期临近时,你很可能会忘记这样做。

对于我们的阳光和沙滩节例子,我们已经收集了关键的图形元素,下面的截图显示了从 PSD 模板生成的图标:

编辑网站图标

添加第三方库

如果你已经有一个将要使用的库列表,你可以开始将它们添加到文件夹中。

HTML5 Boilerplate 自带最新稳定版本的 jQuery,所以你已经有了。如果你想使用其他库,比如 jQuery UI,你可以将它们复制到 libs 文件夹中。

假设你想在项目中使用 jQuery UI,在 www.jqueryui.com 上可用,那么将最新版本的 jQuery UI 复制到 libs 文件夹中,然后在 index.html 标记的底部使用 script 标签引用它。

使用内容传送网络

通过使用内容传送网络CDN),我们可以减少在我们的网络服务器上提供的资源数量,并通过引用由谷歌或微软普遍托管的资源,更有可能文件会被缓存,因为用户访问的许多其他网站也会引用这个特定的资源。

如果你仔细观察,你会注意到链接到 jQuery 的脚本的源与我们的 jQuery UI 源不同。这有两个原因,这两个原因在以下部分中有解释。

协议相对 URL

通常,大多数链接到网络上资源的 URL 以 http:// 开头。然而,有时页面托管在使用加密通信的服务器上。因此,你的页面将使用 https:// 而不是典型的 http://。然而,由于你的脚本源仍然使用 http:// 协议,IE 将向你的页面访问者抛出一个令人讨厌的对话框,询问以下问题:

协议相对 URL

你绝对不希望你的访问者因此而恐慌。所以,最简单的方法是完全删除 URL 中的协议(http:)部分,如下所示:

//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js

这样,浏览器将使用页面所使用的任何协议进行请求。你可以在附录部分了解更多关于协议相对 URL 的信息。

当然,这意味着如果你在本地测试,并且在浏览器上查看你的页面,浏览器将使用类似 file://users/divya/projects 的 URL,因此浏览器将尝试使用以下 URL 查找 jQuery 文件:

file://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js

这个请求肯定会失败,因为在该路径下没有本地资源。因此,如果你使用协议相对 URL,你需要设置一个本地服务器来测试你的文件。在 Mac 或基于 Unix 的操作系统上,通过在你的 shell 界面中导航到项目文件夹并执行以下命令来轻松完成这个操作:

python -m SimpleHTTPServer

这将启动一个服务器,你的项目的 index.html 文件将在 http://localhost:8000 上可用。

提示

如果你使用的是 Windows,将 Mongoose 可执行文件(写作时的最新版本是 mongoose-3.3.exe)从 code.google.com/p/mongoose/ 复制到你的项目文件夹并启动它。然后你的项目的 index.html 将在 http://localhost:8080 上可用。

谷歌 CDN 托管

Google 托管了许多流行的 JavaScript 库。在code.google.com/apis/libraries/devguide.html上可以找到托管在 Google 的 CDN 上的所有库的列表。

我们也可以利用 Google 的 CDN 来托管 jQuery UI,因为它也托管在上面。让我们通过将脚本文件的来源从js/libs/jqueryui-jquery-ui-1.8.17.min.js更改为以下内容来将其转换为使用 Google 的 CDN:

//ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js

但等等!让我们看看在 HTML5 Boilerplate 中如何引用 jQuery CDN。如下代码片段所示:

<script src="img/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="img/jquery-1.8.2.min.js"><\/script>')
</script>

您是否注意到我们还引用了 jQuery 文件的本地副本?我们这样做只是为了在 Google 的 CDN 失败时仍然有本地副本可用。尽管这种情况并不经常发生,但在发生时有一个备用方案是很有用的。

window.jQuery || document.write(…) 这个语句有两个作用。具体如下:

  • 检查 jQuery 对象是否存在:如果存在,这意味着 Google 的 CDN 起作用了。如果存在,就什么也不做。

  • 如果window.jQuery对象不存在:这意味着 Google 的 CDN 失败了;它会立即呈现一个带有对项目libs文件夹中 jQuery 副本的引用的script标签。这告诉浏览器立即请求该资源。

我们可以对 jQuery UI 做类似的操作。

所有的 jQuery 插件都是 jQuery 对象内的对象。因此,我们只需要验证插件对象是否存在,如果不存在,就使用以下代码片段加载libs文件夹中的插件副本:

<script>window.jQuery.ui || document.write('<script src="img/jqueryui-jquery-ui-1.8.17.min.js"><\/script>')
</script>

因此,我们引用 jQuery UI 的完整脚本文件如下所示:

<script src="img/jquery-ui.min.js "></script>
<script>window.jQuery.ui || document.write('<script src="img/jqueryui-jquery-ui-1.8.16.custom.min.js"><\/script>')
</script>

注意

还有其他托管库的 CDN。cdnjs.com网址托管了许多 JavaScript 库。微软也在其 CDN 上托管了一些库;列表可在www.asp.net/ajaxlibrary/cdn.ashx上找到。

添加 Google Analytics ID

这是另一个在截止日期到来时被遗忘的小动作。HTML5 Boilerplate 已经为您提供了准备好的代码片段。您只需要包含您网站的唯一标识符即可。

请注意,HTML5 Boilerplate 将代码片段包含在页面的页脚中,这意味着指标只有在页面加载后才会发送。然而,有一些人认为分析应该在页面加载之前就发生,以衡量在页面加载完成之前离开页面的人数。如果您想这样做,您应该将分析代码片段移到index.html页面的</head>标签的正上方。

更新humans.txt

humans.txt公布了在网站上工作的人员。任何人都可以简单地访问example.com/humanx.txt立即知道在该网站上工作的人员的姓名。将您和您团队成员的姓名添加到 HTML5 Boilerplate 中的humans.txt文件中。

对于我们的阳光和沙滩节的示例,以下截图显示了我们的humans.txt的外观:

更新 humans.txt

总结

在本章中,我们看了如何使用 HTML5 Boilerplate 开始项目以及我们新项目中应该采取的第一步。在此过程中,我们了解了协议相对 URL 和链接到托管在 CDN 上的库。我们更新了humans.txt文件和要在项目中使用的图标。到目前为止,我们对示例项目所做的所有更改都可以在nimbu.in/h5bp-book/chapter-2/上找到。在下一章中,我们将看看为我们的项目编写一些代码。

第三章:创建您的网站

现在我们已经完成了关于我们项目的所有基本工作,让我们来看看构建这个网站的实际任务。我们将首先从标记开始,然后转入样式表,最后添加脚本交互性。

在标记上工作

我们对 Sun and Sand 音乐节项目有一个简单的设计构想。设计如下截图所示:

在标记上工作

从组织结构上看,页面的总体结构如下所述:

  • 页眉:带有一组导航链接的横幅标志

  • 主要内容:页面的主要部分,其中包含导航链接将链接到的部分

  • 左列:这包含了主要内容

  • 右列:这包含了对观众可能有趣但不是必要的次要信息

  • 页脚:赞助商标志和带有音乐的音频播放器,这些音乐将参加音乐节

创建标记

HTML5 Doctorhtml5doctor.com/element-index/上列出了您可以在网页中使用的所有元素。将其与我们之前制作的列表进行比较,看起来header标记很适合放置我们的标志和导航链接,而赞助商标志和音频播放器可以放在footer标记中。这就留下了我们的主要内容;看起来带有主要角色的div标记是最适合它的!

以下是我们最终得到的标记。第二章中的index.html页面,开始您的项目,也包含以下代码:

<header>
  <a href="#main">Skip Navigation</a>

  <h1>Sun &amp; Sand Festival 2012</h1>
  <h2>Ngor&amp; Terou Bi, Dakar</h2>
  <nav class="site-nav">
  <a href="#tickets">Tickets</a>
  <ahref="#about">About</a>
  <a href="#line-up">Line-up</a>
  <a href="#contact">Contact</a>
  <a href="#gettinghere">Getting Here</a>
  </nav>
</header>
<div role="main">
  <section id="primary">
    <article id="tickets">

    </article>
    <article id="about">
    </article>
    <article id="lineup">

    </article>
    <article id="contact">

    </article>
    <article id="gettinghere">
    </article>
  </section>

  <aside id="secondary">
    <article>
      <h2>Get some sun!</h2>
      <ul>
      <li>Follow us on <a href="http://twitter.com/sunnsand">twitter</a>!</li>
      <li>Stalk us on <a href="http://facebook.com">facebook</a>!</li>
      <li>Get some sun through <a href="http://flickr.com/photos/sunnsand">flickr</a>!</li>
      </ul>
    </article>
  </aside>
</div>
<footer>
    <article class="sponsors">
    <a href="#">Boca-Cola</a>
    <a href="#">Darbucks</a>
    <a href="#">Kugle</a>
    <a href="#">Pling</a>
    </article>
    <audio src="img/audio.webm" controls></audio>
</footer>

提示

您可以从您在www.PacktPub.com购买的所有 Packt 图书的帐户中下载示例代码文件。如果您在其他地方购买了这本书,您可以访问www.PacktPub.com/support并注册,文件将直接通过电子邮件发送给您。

决定使用哪个元素

使用 HTML5,我们有大量元素可供选择,这可能会导致一些人选择困难。如果您的文档结构中有任何明显适合任何新元素的地方,请标记它们。如果没有,请继续使用div或任何其他明显适合的元素。

在我们的代码中,当我们有结构上不同的主要内容时,我们使用section元素,当我们有类似但重复的内容部分时,我们使用article元素。您对这些选择的看法可能会有所不同;在这种情况下,我建议您选择您感到舒适的内容。

如果您想了解更多关于新的 HTML5 元素的信息,我建议您查看HTML5: Up & Running, Mark Pilgrim, O'Reilly中关于语义的章节,该书由 Google Press 印刷,在diveintohtml5.info/semantics.html上可以找到。

编写有效的标记

编写有效的标记可以确保您的页面在所有呈现它的浏览器中表现一致。有效的标记是指符合浏览器遵循的 Web 标准的标记。这样,您将防止任何不可预测的行为。

编写有效的标记的最简单方法是使用可以在保存文件时立即验证的工具。

在第二章中,开始您的项目,我建议在 Web 开发中使用 Sublime Text 和 Vim。这两种工具都有内联验证,您可以使用它们来编写有效的标记。此外,这些工具还提供标签和元素的自动完成,使编写有效的标记变得微不足道。

如果您无法访问这些工具,我建议使用validator.w3.org/来验证您的标记。

对于您来说,自动化这些工具非常重要,以确保将您网站上的任何问题减少到最低限度。

创建样式

现在我们已经准备好了标记,让我们看看应该如何进行样式设置。HTML5 样板带有最佳默认样式的样式表。如果您打开main.css,您会在Chrome 框架提示样式规则和辅助类部分之间找到以下部分:

创建样式

这就是我们将撰写样式规则的地方。稍后,我们将看看如何使用Sass (sass-lang.com)或Less (lesscss.org/)来使用一些样式框架,以便更轻松地编写样式。

即使不写一行 CSS 代码,您会注意到我们的页面看起来就像以下截图中显示的网站:

创建样式

这个默认样式要归功于 HTML5 样板中可用的规范化样式规则。

为什么不使用 reset.css?

很长一段时间以来,建议使用reset.css,它可以在html5doctor.com/html-5-reset-stylesheet/上找到,并将每个可用元素的边距和填充重置为0,并使所有标题的字体大小与正文文本相同,而没有更高的字体重量。

HTML5 样板建议不要这样做。浏览器提供有用的浏览器默认值,这将使您的样式表更小,因为您不必重新声明这些样式。

使用normalize.css,您将不会在调试工具中看到以下类型的混乱:

为什么不使用 reset.css?

normalize.css的联合创始人之一 Nicolas Gallagher 在nicolasgallagher.com/about-normalize-css/上详细介绍了为什么它比reset.css更好,对于那些仍然不确定 CSS 规范化的优点的人来说,这是一篇很好的文章。

我们可以使用的有用样式类

在第一章开始之前中,我们简要地看到 HTML5 样板带有一堆默认类,这些类对工作很有用。您可能已经注意到我们在样式规则中使用了其中一些类。

我们所有的辅助类都是最后定义的,因此当使用时它们可以覆盖所有其他样式。确保它们覆盖的属性在其他地方没有过度指定;您可以在www.w3.org/community/webed/wiki/Inheritance_and_cascade#Specificity上阅读更多关于特异性的信息。

图像替换

在我们的项目中,我们希望为Sun & Sand Festival 2012标题添加一个时髦的徽标。HTML5 样板有一个方便的图像替换类可用于此目的。在标记中,我们只需向h1标签添加一个名为ir的类,如下面的代码所示:

<h1 class="ir">Sun &amp; Sand Festival 2012</h1>

这样做的作用是将 HTML5 样板中图像替换类(ir)中指定的样式应用于隐藏文本。然后,您只需要向h1元素添加背景图像以及其宽度和高度,以便按照您的规范显示,如以下代码所示:

header h1 {
background-image: url('/img/heading-banner.png');
width: 800px;
height: 300px;
}

这将导致标题看起来类似于以下截图:

图像替换

隐藏元素

我们的标记中有内容,我们希望只有在用户点击时才显示。在我们的网站中,当用户点击到这里链接时,我们希望显示一个 Google 地图。通过使用iframe,这样做非常简单,如下面的代码片段所示:

<iframe width="425" height="350" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="img/maps?f=q&amp;source=s_q&amp;hl=en&amp;geocode=&amp;q=ngor+terrou+bi,+dakar,+senegal&amp;aq=&amp;sll=37.0625,-95.677068&amp;sspn=90.404249,95.976562&amp;ie=UTF8&amp;hq=ngor&amp;hnear=Terrou-Bi,+Bd+Martin+Luther+King,+Gueule+Tapee,+Dakar+Region,+Guediawaye,+Dakar+221,+Senegal&amp;t=m&amp;fll=14.751996,-17.513559&amp;fspn=0.014276,0.011716&amp;st=109146043351405611748&amp;rq=1&amp;ev=p&amp;split=1&amp;ll=14.711109,-17.483921&amp;spn=0.014276,0.011716&amp;output=embed">
</iframe>

但这意味着,一旦您的页面在浏览器中加载,浏览器将立即尝试显示地图并从 Google 地图获取资源。但我们只希望在用户点击到这里链接时才显示这张地图。HTML5 样板提供了一个可以用于此类目的的类名。我们将应用一个名为hidden的类,以确保这些元素在明确设置为显示之前不会呈现。hidden类在以下代码片段中使用:

<iframe class="hidden" width="425" height="350" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="img/maps?f=q&amp;source=s_q&amp;hl=en&amp;geocode=&amp;q=ngor+terrou+bi,+dakar,+senegal&amp;aq=&amp;sll=37.0625,-95.677068&amp;sspn=90.404249,95.976562&amp;ie=UTF8&amp;hq=ngor&amp;hnear=Terrou-Bi,+Bd+Martin+Luther+King,+Gueule+Tapee,+Dakar+Region,+Guediawaye,+Dakar+221,+Senegal&amp;t=m&amp;fll=14.751996,-17.513559&amp;fspn=0.014276,0.011716&amp;st=109146043351405611748&amp;rq=1&amp;ev=p&amp;split=1&amp;ll=14.711109,-17.483921&amp;spn=0.014276,0.011716&amp;output=embed">
</iframe>

请注意,这会使内容从屏幕阅读器和浏览器显示中消失。

注意

屏幕阅读器是用于帮助那些无法在屏幕上查看文本的人阅读网页的设备。Victor Tsaran 在www.yuiblog.com/blog/2007/05/14/video-intro-to-screenreaders/上有一个关于屏幕阅读器的很好的介绍视频。

使这种情况发生的规则如下:

.hidden {
display: none !important;
visibility: hidden;
}

这确保了所有屏幕阅读器(JAWSWindows-Eyes是最流行的)都会隐藏所有具有此类名称的元素。

如果您希望内容对使用屏幕阅读器的用户可用,您应该使用我们将要学习的visuallyhidden类。

在不影响布局的情况下隐藏元素

有时,您不希望将某些内容呈现到屏幕上,但希望使用跳转导航链接使其对屏幕阅读器可用。这将确保那些使用屏幕阅读器的人可以立即跳转到内容的重点,而不必听一长串导航链接。因此,让我们将这个类添加到我们在页眉中的跳转导航链接中,如下面的代码所示:

<a class="visuallyhidden" href="#main">Skip Navigation</a>

这使得链接从我们的屏幕上消失,但对于屏幕阅读器是可用的。下面的网页截图不显示跳转导航链接:

在视觉上隐藏元素

使这种情况发生的 CSS 规则如下:

.visuallyhidden {
border: 0;
clip: rect(0 000);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}

通常使用的解决方案涉及将它们绝对定位,并将高度设置为0px,但这会阻止苹果的 VoiceOver 屏幕阅读器读取内容。

另一种解决方案涉及使用text-indent属性将文本定位到屏幕之外,但当内容用从右到左的语言书写时,需要小心,这种解决方案会失败。

使用clip属性可以避免所有这些问题,同时使内容在所有屏幕阅读器上可读。

注意

乔纳森·斯努克在snook.ca/archives/html_and_css/hiding-content-for-accessibility上写道,clip属性是在视觉上隐藏内容但仍然可供屏幕阅读器使用的最佳方式。

那些广泛使用键盘导航的人也希望跳过导航。但是,因为它在视觉上是隐藏的,他们不会知道这个选项存在。对于这种情况,您希望在此元素获得焦点时可用。让我们添加一个额外的类focusable,使我们的跳转导航链接在通过键盘导航激活此链接时可见。

<a class="visuallyhidden focusable" href="#main">Skip Navigation</a>

下面的截图显示了当用户将键盘焦点切换到跳转导航链接时,它会立即可见:

在视觉上隐藏元素

在不影响布局的情况下隐藏元素

在我们的网站上,我们希望在几天内以选项卡形式显示阵容,如下截图所示:

在不影响布局的情况下隐藏元素

以下是标记的简化视图:

<article class="t-tabs t-section" id="lineup">
<nav class="t-tab__nav">
<a class="t-tab__navitem--active t-tab__navitem" href="#day-1">Day 1</a>
<a class="t-tab__navitem" href="#day-2">Day 2</a>
</nav>
<ul id="day-1" class="t-tab__body t-grid t-before-1-6 t-after-1-6">
<li class="t-grid__cell t-unit-1-2">
<a class="t-media--row" href="#">
<img width="100" height="100" class="t-media__aside t-image--artist" src="img/artist-kidjo.png">
<b class="t-media__body t-title-tabartist t-artist__name">Angelique Kidjo</b>
</a>
</li>
</ul>
<ul id="day-2" class="t-tab__body t-grid t-before-1-6 t-after-1-6">
<li class="t-grid__cell t-unit-1-2">
<a class="t-media--row" href="#">
<img width="100" height="100" class="t-media__aside t-image--artist" src="img/artist-sangre.png">
<b class="t-media__body t-title-tabartist t-artist__name">Oumou Sangre</b>
</a>
</li>
</ul>
</article>

最简单的方法是只显示Day 1,并使用hidden类隐藏其余的天数,如下面的代码片段所示:

<article class="t-tabs t-section" id="lineup">
<nav class="t-tab__nav">
<a class="t-tab__navitem--active t-tab__navitem" href="#day-1">Day 1</a>
<a class="t-tab__navitem" href="#day-2">Day 2</a>
</nav>
<ul id="day-1" class="t-tab__body t-grid t-before-1-6 t-after-1-6">
<!--list content below -->
</ul>
<ul id="day-2" class="t-tab__body t-grid t-before-1-6 t-after-1-6 hidden">
<!--list content below -->

</ul>
</article>

通过隐藏元素,我们使其占用的尺寸消失为 0。这意味着以前由该内容占用的区域会坍塌。

当用户点击每天阵容的导航链接时,每天的内容将经常被隐藏和显示,这看起来会很突兀,如下截图所示:

在不影响布局的情况下隐藏元素

在这种情况下,我们可以使用辅助类invisible来使元素不渲染,但保持其尺寸;它在屏幕上不可见,也不可供屏幕阅读器使用。如下截图所示,TICKETS部分不会根据哪个选项卡处于活动状态而改变位置:

在不影响布局的情况下隐藏元素

清除浮动

我们将图像元素定位在艺术家姓名的左侧。我们通过将图像浮动到左侧来实现这一点。幸运的是,我们没有任何跟随浮动元素的内容。如果有的话,那么该内容将覆盖在浮动元素上。您可以通过在浮动元素的父容器上设置一个名为clearfix的类来防止发生这种情况。在我们的情况下,为了确保我们的浮动元素永远不会触发这种行为,我们将在艺术家图像元素的父元素上添加clearfix类:

<a class="t-media--row  clearfix" href="#">

要了解clearfix类的工作原理,请阅读附录中的相关内容,You Are an Expert, Now What?

现在我们已经处理了基本要点,让我们将样式应用到页面上,使其看起来更像我们心目中的设计。以下代码片段显示了如何向我们的页面添加样式:

html {
background: url('/img/waves-bg.png') repeat-x, 
url(/img/heading-banner-back.png) 50% 100px no-repeat, 
url(/img/bg-active.png) 50% 72px repeat-x, 
url('/img/bg.png') #e7dcbb;  
box-sizing: border-box;  
margin: 0 1em;
font: 100%/1.5 georgia, serif;
}

body {
max-width: 80%;
margin: 0 auto;
text-align: center;
}

.t-tabs {
min-height: 400px;
position: relative;
}

.t-tab__body {
position: absolute;
left: 0;
right: 0;  
}

.t-tab__navitem--active { 
position: relative;
}

.t-tab__navitem--active::after{
position: absolute;
bottom: -2em;
left: 0;
height: 2em;
width: 100%;
content: "";
border-radius: 0 0 20em 20em;
background: #305da1;
box-shadow: 0 -0.3em 0 0 #77aec3 inset, 0 0.3em 0 0 #1A9DC8;
}

/* TICKETS */
.t-tickets__currency {
font-family: georgia, serif;
text-align: center;
position: absolute;
transform-origin: 100% 100%;
transform: rotate(-90deg) translate(0, -2.1em);
 }

/* MEDIA OBJECT */
.t-media,
.t-media--column,
.t-media--row,
.t-media__body {  
text-align: left;  
list-style: none;
}
.t-media--row .t-media__aside {
float:left; 
margin-right: 16px;
}

/* Image replaced social media links */
.t-links__item--twitter,
.t-links__item--facebook,
.t-links__item--flickr {
padding: 0.25rem 1rem;
display: inline-block;
}

.ir.t-links__item--twitter,
.ir.t-links__item--facebook,
.ir.t-links__item--flickr {
background-size: contain;
background-repeat: no-repeat;
width: 1rem;
height: 1rem;
background-position: center center;
display: inline-block;
}

.ir.t-links__item--twitter {
background-image: url(/img/logo-twitter.svg);
}

.t-title--h1,
.t-title--h2,
.t-title--navsite,
.t-title-tabartist {
font-family: FolkSolidRegular, sans-serif;
text-transform: uppercase;  
color: #E4773A;
text-shadow:  3px 3px 1px #C84134, 
                4px 4px 1px #C84134;  
letter-spacing: 2px;  
}

编写有效的样式表

当我们浏览时,您可能已经注意到样式中没有任何拼写错误。编辑人员毫无疑问做得很好,但我意识到在编写样式表时您没有这样的助手!一个错误的拼写错误可能会给我们带来无法估量的创伤,因为我们要找出为什么某个特定的样式没有被应用。这就是为什么自动验证样式并尽可能自动完成样式声明也很重要。

Sublime Text 和 Vim 都提供 CSS 属性的自动补全,并且您还可以自动插入分号!如果您无法使用这些工具,您可以使用在线 CSS 验证器jigsaw.w3.org/css-validator/来测试您的 CSS。

还有另一种自动编写有效和高效样式规则的方法——使用编译成 CSS 的替代样式语言。接下来我们将研究一些这样的语言。

使用样式语言编写高效的样式表

很长一段时间以来,编写样式表的唯一方法是使用 W3C 在其规范中提供的语法。然而,通过使用一些编程逻辑来编写样式表,可以获得许多生产力上的好处。但是浏览器只能理解 W3C 规范规定的语法。这意味着任何使用额外可编程功能的样式语言都应该转换为浏览器可理解的典型样式表(这称为编译)。

最早为此设计的样式语言之一称为 Sass。现在,我们有了一些更多,最流行的是 Sass、Less 和 Stylus。在 Sass 和 Less 中,有效的 CSS 自动成为有效的 Sass 和 Less 代码。这使得从 CSS 转换到这些语言变得微不足道。

通常,您会在名为main.scss(如果您使用 Sass)、main.less(如果您使用 Less)或main.styl(如果您使用 Stylus)的文件中编写样式规则。使用每种语言自带的编译器,这些文件将分别编译为styles.css

优点

使用样式语言有许多优点,例如以下:

  • 这些语言使您始终可以编写语法有效的样式表,因为如果使用任何无效的语法,它们都会抛出错误。

  • 所有这些语言都提供了一些在 CSS 中受欢迎的功能,例如变量、能够在其他类中重复使用样式规则而不必重复多次、算术计算、颜色函数等等。

  • 在开发时,您可以选择输出扩展可读的样式,然后在生产中使用时输出紧凑的性能优化、去除空白的样式表。

缺点

然而,使用样式语言也有一些缺点,如下所述:

  • 虽然很容易转换为 Sass 或 Less,但不可能对生成的样式表进行修改,并将这些更改传输到其原始的 Sass/Less/Style 文件中。因此,您需要小心确保没有人编辑生成的 CSS 文件。

  • 团队合作需要整个团队共同使用其中一种语言。如果没有这样做,就不可能维护两个样式表的分支并使它们保持同步。

  • 在调试时,如果您正在检查一个元素,大多数调试器只会显示样式表中的行号,而不是原始语言文件中的行号。这可能会使得难以找出在原始文件中特定规则的位置。

学习的地方?

如果您对了解更多关于这些语言感兴趣,请继续阅读一些好的入门地点。

Sass

官方网站是sass-lang.com。Chris Coyier 在css-tricks.com/video-screencasts/88-intro-to-compass-sass/上有一个关于 Sass 的很好的介绍视频。

Less

官方网站是lesscss.org。有一个 Less 的视频概述可在net.tutsplus.com/tutorials/html-css-techniques/quick-tip-you-need-to-check-out-less-js/上找到。

Stylus

官方官方网站在learnboost.github.com/stylus。有一个 Stylus 的视频概述可在thechangelog.com/post/3036532096/stylus-expressive-robust-feature-rich-css-language上找到。

使用样式语言的 HTML5 Boilerplate

如果您对任何这些语言有相当自信的掌握,那么您可以使用我们接下来将要看的任何可用端口来启动您的项目:

Sass

HTML5 Boilerplate 的 Sass 版本相当更新,需要Compass,这是在github.com/sporkd/compass-html5-boilerplate上的 Sass 框架。

Less

存在一个不太经常更新的 HTML5 Boilerplate 到 Less 的端口,位于github.com/m6tt/less-boilerplate

Stylus

目前没有针对 Stylus 的 HTML5 Boilerplate 的完全功能性端口,尽管使用命令行将其转换为 stylus 似乎是最简单的方法。有关使用此方法的更多信息,请访问learnboost.github.com/stylus/docs/executable.html

总结

哇!那是一个紧张的编码会话。在本章中,我们几乎基于 HTML5 Boilerplate 创建了一个完整的网站。我们看了如何编写标记、样式和脚本。此外,我们还探索了一些工具,使编写有效的标记和样式更容易。

到目前为止,我们对示例项目所做的所有更改都可以在nimbu.in/h5bp-book/chapter-3/上找到。

在下一章中,我们将看看如何使用 jQuery 为这个相当静态的页面添加一些交互性,并使其更容易在网站上进行导航。

第四章:添加交互性并完成您的网站

我们已经创建了网站的第一个版本。虽然网站看起来非常可读和可导航,但使交互更加流畅将使其成为一个显著更好的体验。

使用 jQuery

正如我们在第二章中看到的,开始你的项目,HTML5 Boilerplate 提供了一种方便且安全的方式来加载 jQuery。使用 jQuery,编写访问元素的脚本变得非常简单。

如果您正在编写自定义的 jQuery 脚本,要么启动您正在使用的插件,要么执行一些小的交互,请将其放在js文件夹中的main.js文件中。

使用其他库

如果您更喜欢使用其他库,您也可以以类似的方式加载和使用它们。

以下是我们加载 jQuery 的方式:

<script src="img/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="img/jquery-1.8.2.min.js"><\/script>')
</script>

假设您想使用另一个库(如 MooTools),然后查看 Google Libraries API,看看该库是否可在developers.google.com/speed/libraries/上找到。如果可以找到,只需用该网站上的适当引用替换引用。例如,如果我们想用 MooTools 替换我们的 jQuery 链接,我们只需替换以下代码:

<script src="img/jquery.min.js">
</script>

使用以下代码行:

<script src="img/mootools-yui-compressed.js">
</script>

我们还将在本地的js/vendor文件夹中下载 Mootools 的压缩文件,并替换以下代码:

<script>window.jQuery||document.write('<script src="img/jquery-1.7.2.min.js"><\/script>')
</script>

使用以下代码行:

<script>window.jQuery||document.write('<script src="img/mootools-core-1.4.5-full-compat-yc.js"><\/script>')
</script>

有关为什么我们使用代码的本地副本的更多信息,请查看第二章,开始你的项目。但是我们对我们默认选择的 jQuery 非常满意,所以让我们继续使用它。

添加平滑滚动插件和交互

如果您还没有注意到,我们正在构建的网站是一个单页面网站!所需的所有内容都在同一页上找到。根据我们目前的网站设计,点击站点导航链接将大致滚动到导航链接所指的部分。我们希望这种交互是平滑的。让我们使用 jQuery 的平滑滚动插件来实现这一点。

让我们从 Github 仓库下载插件文件,托管在github.com/kswedberg/jquery-smooth-scroll上。

在其中,我们找到了插件的压缩版本(jquery.smooth-scroll.min.js),我们将在文本编辑器中打开它。

然后复制所有代码并粘贴到plugins.js文件中。

让我们添加一个类名js-scrollitem,以便我们可以区分这个元素是否有一个将在这些元素上使用的脚本。这样,意外删除通过 JavaScript 提示的交互所需的类名的机会将会更小。

现在,我们将编写代码在main.js文件中调用这个插件。在文本编辑器中打开main.js文件并输入:

$('.js-scrollitem').smoothScroll();

这将使所有链接到同一页内具有js-scrollitem类的父容器的可点击链接通过插件平滑滚动。如果我们已经正确使用了 HTML5 Boilerplate 的默认设置,添加这个将足以开始平滑滚动。

接下来,我们希望行程部分中的导航链接根据点击的日期打开右侧的行程。目前,在下面的截图中,它只显示了第一天的行程,没有做其他任何事情:

添加平滑滚动插件和交互

让我们继续编辑main.js文件并添加启用此功能的代码。

首先,让我们添加我们将用于控制样式和代码内部的隐藏/显示行为的类名。此功能的代码如下:

<nav class="t-tab__nav">
<a class="t-tab__navitem--active t-tab__navitemjs-tabitem" href="#day-1">Day 1</a>
<a class="t-tab__navitemjs-tabitem" href="#day-2">Day 2</a>
</nav>

现在,我们将编写代码来显示我们点击的元素。这段代码如下:

var $navlinks = $('#lineup .js-tabitem');
var $tabs = $('.t-tab__body');

var hiddenClass = 'hidden';

var activeClass = 't-tab__navitem--active';

$navlinks.click(function() {
// our code for showing or hiding the current day's line up
$(this.hash).removeClass(hiddenClass);
});

通过检查我们迄今为止所做的工作,我们注意到它始终保持每天的行程可见,并且完成后不会隐藏它们!让我们也添加这一点,如下面的代码片段所示:

var $navlinks = $('#lineup .js-tabitem');
var $tabs = $('.t-tab__body');

var hiddenClass = 'hidden';

var activeClass = 't-tab__navitem--active';

var $lastactivetab = null;

$navlinks.click(function() {
var $this = $(this);
  //take note of what was the immediately previous tab and tab nav that was active
  $lastactivetab = $lastactivetab || $tabs.not('.' + hiddenClass);
  // our code for showing or hiding the current day's line up
$lastactivetab.addClass(hiddenClass);
$(this.hash).removeClass(hiddenClass);
$lastactivetab = $(this.hash);
return false;
}

您会注意到活动标签导航项似乎仍然表明它是第 1 天!让我们通过更改我们的代码来修复这个问题,以便与选项卡导航锚点类似,如下面的代码片段所示:

var $navlinks = $('#lineup .js-tabitem');
var $tabs = $('.t-tab__body');

var hiddenClass = 'hidden';

var activeClass = 't-tab__navitem--active';

var $lastactivetab = null;
var $lastactivenav = null;

$navlinks.click(function() {
var $this = $(this);
//take note of what was the immediately previous tab and tab nav that was active
$lastactivetab = $lastactivetab || $tabs.not('.' + hiddenClass);
$lastactivenav = $lastactivenav || $navlinks.filter('.' + activeClass);

  // our code for showing or hiding the current day's line up
$lastactivetab.addClass(hiddenClass);   
$(this.hash).removeClass(hiddenClass);   
$lastactivetab = $(this.hash);

  // change active navigation item
$lastactivenav.removeClass(activeClass);
$this.addClass(activeClass);
$lastactivenav = $this;

return false;
});

太棒了!我们已经准备好按天排列了。现在我们需要确保当用户单击在地图上查找链接时,我们的 Google Maps iframe会呈现。我们还希望使用相同的链接来隐藏地图,如果用户想要这样做的话。

首先,我们为用于触发地图显示/隐藏和地图的iframe的锚元素添加一些可识别的特征,如下面的代码片段所示:

<p>The festival will be held on the beautiful beaches of NgorTerrou Bi in Dakar. 
<ahref="#" class="js-map-link">Locate it on a map</a>
</p>

<iframe id="venue-map" class="hidden" width="425" 
height="350" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="img/maps?f=q&amp;source=s_q&amp;hl=en&amp;geocode=&amp;q=ngor+terrou+bi,+dakar,+senegal&amp;aq=&amp;sll=37.0625,-95.677068&amp;sspn=90.404249,95.976562&amp;ie=UTF8&amp;hq=ngor&amp;hnear=Terrou-Bi,+Bd+Martin+Luther+King,+Gueule+Tapee,+Dakar+Region,+Guediawaye,+Dakar+221,+Senegal&amp;t=m&amp;fll=14.751996,-17.513559&amp;fspn=0.014276,0.011716&amp;st=109146043351405611748&amp;rq=1&amp;ev=p&amp;split=1&amp;ll=14.711109,-17.483921&amp;spn=0.014276,0.011716&amp;output=embed">
</iframe>

然后,我们使用以下 JavaScript 来触发链接:

  $maplink = $('.js-map-link');
  $maplinkText = $maplink.text();

  $maplink.toggle(function() {
    $('#venue-map').removeClass(hiddenClass);
    $maplink.text('Hide Map');
  }, function() {
    $('#venue-map').addClass(hiddenClass);
    $maplink.text($maplinkText);
  });

现在,让我们看看如何使我们的音频播放器在所有浏览器上工作。

使用 Modernizr 安全添加 HTML5 功能

我们在第一章中简要介绍了 Modernizr,开始之前,但我们还没有为它做过太多事情。强烈建议我们创建一个自定义的 Modernizr 构建。HTML5 Boilerplate 附带了一个 Modernizr 的自定义构建,其中包括自定义构建器(modernizr.com/download/)中的所有选项,包括额外的功能,如 HTML5Shiv、资源加载器(modernizr.load)、媒体查询测试,并根据 Modernizr 的测试结果向html标签添加 CSS 类名。

Modernizr 的自定义构建在 IE 中启用了 HTML5 元素(在paulirish.com/2011/the-history-of-the-html5-shiv/中了解更多信息)。但是,现在,通过我们的音频播放器,我们有机会使用另一个作为额外功能可用的 Modernizr 函数,即modernizr.load

浏览器中的音频支持并不像我们期望的那样简单。由于许可限制,不同的浏览器期望不同的格式。一些浏览器甚至不支持 HTML5 音频。使用一个可以为我们抽象出所有这些问题的框架将是完美的。在html5please.com上看到,推荐建议是使用一个名为mediaelement.js的框架来帮助我们处理这些问题。

注意

html5please.com是一个网站,告诉您这些新功能中哪些是可用的,以及在不支持它们的浏览器上应该如何使用它们。

让我们仅在未检测到音频支持时使用这个框架作为我们的音频播放器。

首先,我们从mediaelementjs.com下载框架,并将构建文件夹中的所有文件复制到js/vendor/mediaelement/中。然后,我们应该在index.html中为我们的播放器添加跨浏览器友好的音频标记,如下面的代码片段所示:

<article class="t-audio">
<audio controls preload="none" autobuffer>
<sourcesrc="img/festival.mp3" />
<sourcesrc="img/festival.ogg" />
</audio>
</article>

请注意,我们需要在head元素中指定样式表,以确保它在所有浏览器上都能完美工作(而不是及时加载),如下面的代码所示:

<link rel="stylesheet" href="js/vendor/mediaelement/mediaelementplayer.css">

然后,我们在main.js文件中使用 Modernizr 仅在缺少音频支持时加载mediaelement.js,如下面的代码所示:

Modernizr.load({
test: Modernizr.audio,
nope: {
'mediaelementjs': 'js/vendor/mediaelement/mediaelement-and-player.min.js'
},

callback: {
    'mediaelementjs': function() {
$('audio').mediaelementplayer();
}
} 
});

这段代码首先使用 Modernizr 测试音频是否受支持。如果不支持,那么我们将加载必要的资源来使音频在我们的mediaelement.js框架中工作。一旦加载了mediaelement.js,我们就调用它,这样它就会运行并将我们的音频文件转换为那些缺少音频支持的浏览器能够理解的格式。

使用 Modernizr 安全添加 HTML5 功能

前面的屏幕截图显示了我们的页面在不支持 HTML5 音频的浏览器上的呈现(回退到使用mediaelement.js的 Flash),以及在支持 HTML5 音频的浏览器上的呈现(使用浏览器提供的本机控件)。

何时使用 Modernizr.load?

Modernizr.load是一个很好的实用工具,当您有多个文件需要有条件地加载时,比如我们的音频播放器。

有时,您希望只有在用户单击链接或元素时才发生某些事情。您可以在用户单击元素后及时加载这些资产,而不是预先加载所有所需的资产,并使浏览器渲染页面变慢。

使用 Modernizr 加载 CSS 功能

Modernizr 还会在页面的html标签上输出其对各种 HTML5/CSS3 功能的测试结果,如下截图所示:

使用 Modernizr 加载 CSS 功能

这对于基于可用功能的体验进行样式设计非常有用。例如,我们注意到html元素中有一个名为no-touch的类名。这意味着加载此页面的浏览器不支持触摸界面。如果支持触摸,那么我们可以为所有链接添加更多的填充,以适应尝试点击它们的大手指。让我们在css/style.css文件中添加样式来实现这一点,如下所示:

.touch a {
padding: 0.25em;
background: #CEC3A1;
border-radius: 0.5em;
display: inline-block;
}

这是我们的网站在支持触摸事件的浏览器上的外观(左侧)和不支持触摸事件的浏览器上的外观(右侧):

使用 Modernizr 加载 CSS 功能

测试我们的网站

哇!这真是太多了!但是等等,我们还没有完成!我们已经编写了所有的代码,但是怎么样进行一些测试呢?那里有很多种浏览器的变体,不可能对每一种都进行测试。幸运的是,在大多数主要版本的浏览器上进行测试是相当简单的。

如果您使用 Windows,我建议您安装 Opera、Opera Next、Safari、Chrome、Chrome Canary、Firefox、Firefox Nightly、IE8 和 IE10 的最新版本。

如果您使用的是 Mac,获取上面列出的所有浏览器,除了 IE。如果您有能力的话,购买一个 Windows 操作系统,并将其安装为 Virtual Box 上的虚拟镜像(www.virtualbox.org/)。微软提供了旧版 IE 的虚拟镜像供测试使用,您也可以使用 ievms(github.com/xdissent/ievms)在 Virtual Box 上安装。

对于一个更简单但不太严格的测试选项——比如当您还没有最终确定您的网站时——尝试www.browserstack.combrowserling.com

所有这些浏览器都有开发者工具,可以很容易地检测页面是否按预期渲染。

让我们在 Internet Explorer 7 中测试我们的 Sun and Sand Festival 网站。乍一看,一切似乎都按预期工作。但是看着标签,似乎一切都乱了!以下截图显示了我们在 Internet Explorer 浏览器上的页面:

测试我们的网站

为了调试这个问题,让我们使用 Firebug Lite 来检查这些元素上应用了哪些样式。您可以在 IE7 上安装 Firebug Lite(getfirebug.com/firebuglite)的书签。点击该书签将使我们能够在 IE7 上使用受限版本的 Firebug。

使用 Firebug,我们看到一个调试窗口,如下截图所示:

测试我们的网站

检查我们的main.css,似乎我们基于媒体查询的样式都被 IE7 解析和解释,而不管其中的条件如何!例如:

.t-unit-1-2{
width: 100%;
}

先前的样式是在媒体查询@media only screen and (max-width: 750px)中声明的,这个查询应该只在满足条件时覆盖现有规则(.t-unit-1-2 { width: 50%; })。但是 IE7 简单地忽略了提到的功能,并盲目地应用它找到的所有样式规则。

由于条件 CSS 类名的存在,我们可以通过在原始 CSS 声明中添加额外的样式规则来轻松解决这个问题,以防止 IE6 到 IE8 覆盖原始样式。附录,您是专家,现在怎么办?详细介绍了条件 CSS 类名。

HTML5 Boilerplate 为您提供了三个类名,用于这种情况,描述如下:

  • .lt-ie7:以这个类名来定位所有低于 IE7 的 IE 版本。这将应用样式到 IE 6 及以下版本。

  • .lt-ie8:以这个类名来定位所有低于 IE8 的 IE 版本。这将应用样式到 IE6 和 IE7。

  • .lt-ie9:针对所有低于 IE9 的 IE 版本。这将应用样式到所有低于 IE9 的 IE 版本。

多亏了这个,我们现在可以应用针对 IE8 及以下版本的规则,这些版本不理解媒体查询中的条件,通过以下方式应用样式规则:

.lt-ie9 .t-unit-1-2 {
width: 45%;
}

由于 IE8 及以下版本也不支持box-sizing属性(Mozilla 开发者网络在developer.mozilla.org/En/CSS/Box-sizing描述了此属性的效果),这意味着这些框的宽度将随着我们添加填充而扩展。让我们删除父元素的边距,以防止框堆叠,如下面的代码片段所示:

.lt-ie9 .t-before-1-6,
.lt-ie9 .t-after-1-6 {
margin-left: 0;
margin-right: 0;
}

然而,这并没有完全解决我们的问题。然后,再往上看,我们注意到我们的网格单元,也就是具有类t-grid__cell的元素,其display属性设置为 inline-block。知道 IE7 不会将此应用于除具有自然内联属性的元素之外的任何元素,我们需要添加额外的声明才能使其工作,如下面的代码片段所示:

.lt-ie9 .t-grid__cell {
display: inline;
}

最后,现在这样就可以了!

测试我们的网站

让我们滚动到页面底部。我们注意到价格都混乱了,因为 IE7 不支持 CSS3 变换,如下面的截图所示:

测试我们的网站

有了 Modernizr,我们只需要将这个规则添加到我们的样式表中:

.no-csstransforms .t-tickets__currency {
position: static;
}

这将使任何不支持 CSS 变换的浏览器更易读,如下面的截图所示:

测试我们的网站

继续向下滚动,我们注意到我们的 SVG 图标在 IE8 及以下版本中丢失,因为它们不识别 SVG 文件,如下面的截图所示:

测试我们的网站

再次感谢 Modernizr!在我们的main.js文件中,我们将检查 Modernizr 中 SVG 测试的结果,然后用它们的等效 PNG 图像替换所有 SVG 图像。请注意,这意味着您需要为 HTML 页面中使用的每个 SVG 文件都有一个 PNG 等效文件。替换 SVG 为 PNG 文件的代码如下:

if(Modernizr.svg == false) {
  $('img[src$=".svg"]').each(function() {
	this.src = /(.*)\.svg$/.exec(this.src)[1] + '.png';
 });
}

提示

为什么使用 SVG?

我们使用 SVG 图标,因为这些图标可以根据我们对响应式网站的需求进行缩放,SVG 是一种矢量图像格式。此外,与典型的 PNG 文件相比,它们非常轻量,并且可以比 PNG 格式加载得更快。

下面的截图显示了 IE7 如何以 PNG 格式呈现图标,这要感谢 Modernizr:

测试我们的网站

当您开始进行 Web 开发时,您应该花更多时间使用浏览器开发工具;Andi Smith 在andismith.com/blog/2011/11/25-dev-tool-secrets/写了一篇很好的文章,概述了每个工具的一些特性。

在非桌面浏览器上测试

让我们看看在小规模设备上网站的外观。最快最简单的方法是从www.opera.com/developer/tools/mobile/下载Opera Mobile Emulator,然后使用其中的几个选项之一加载我们的页面。这个模拟器显示在下面的截图中:

在非桌面浏览器上测试

在模拟器左侧选择一个选项,然后单击启动按钮,打开一个模拟 Opera 浏览器实例,模拟您选择的设备上的显示效果。

例如,下面的截图显示了我们的页面在Opera Mobile Emulator上的渲染实例,用于Amazon Kindle Fire

在非桌面浏览器上测试

最好的部分是Opera Mobile浏览器是最现代的移动浏览器之一,这使得它成为您积极开发网站时进行测试的非常好的浏览器。它还适用于各种设备,这使得使用Opera Mobile Emulator测试各种设备宽度变得很容易,如果您正在使用媒体查询来调整页面以适应不同的设备尺寸。

如果您也拥有运行 iOS 6 的 iPhone,使用Safari 6 进行远程调试并使用 Safari 开发者工具检查代码是相当容易的(Max Firtman 在www.mobilexweb.com/blog/iphone-5-ios-6-html5-developers上有更多信息)。

如果您有 Android 设备,您可以在 Chrome for Android 浏览器上启用调试,但您需要安装 Android 开发者工具才能这样做。关于如何做到这一点的更多帮助,请参阅 Chrome for Android 远程调试指南developers.google.com/chrome/mobile/docs/debugging

注意

如果您有多个运行不同浏览器的移动设备,您还可以使用html.adobe.com/edge/inspect/上的Adobe Edge Inspect来测试这些页面在所有这些设备上的外观。

摘要

在本章中,我们看了如何使用 jQuery 插件为网站添加一些交互。我们还学习了如何使用Modernizr.load来加载脚本,以便轻松地有条件地检测对 HTML5 音频的支持,并为不支持的浏览器加载资源并正确呈现音频。我们还研究了一些使用浏览器开发者工具调试网站和验证页面在各种浏览器上显示方式的方法。

在下一章中,我们将学习如何在 Apache 和其他 Web 服务器上优化我们的网站。

第五章:自定义 Apache 服务器

我们的 Sun and Sand 节日网站基本上已经完成了!但在部署到生产环境之前,让我们确保我们已经优化了页面和相关文件所在的服务器的配置,以便最终用户可以尽快加载页面,同时我们检查可能导致我们的网站被黑客攻击的安全漏洞。

服务器端配置

在我们继续之前,让我们简要地看一下服务器的作用。服务器理解浏览器对站点页面的请求,然后寻找 URL 请求的文件。服务器然后以 HTTP 头的形式将文件发送回浏览器。Apache是网站最流行的服务器软件,HTML5 Boilerplate 附带了一个名为.htaccess的 Apache 配置文件。

设置 Apache 服务器

在我们查看 HTML5 Boilerplate 提供的 Apache 配置文件的各种功能之前,让我们设置一个本地 Apache 服务器,这样我们就可以看到这些功能的运行情况。

安装 Apache

我们将看一下在 Mac、Windows 和 Linux 上安装 Apache。

Mac

您无需做任何特殊操作;Apache 已经安装好了。但是为了在这个项目中使用它,请确保将所有文件复制到您的主文件夹中的网站文件夹(/~<username>)。编辑/etc/apache2/httpd.conf文件以更改以下突出显示的代码:

<Directory /usr/share/web>
AllowOverride None
        Options MultiViewsFollowSymlinks
        Order allow,deny
        Allow from all
        Header Set Cache-Control no-cache
</Directory>

到以下:

<Directory /usr/share/web>
AllowOverrideAll
 Options MultiViewsFollowSymlinks
        Order allow,deny
        Allow from all
        Header Set Cache-Control no-cache
</Directory>

您还需要以相同的方式更改/etc/apache2/<username>.conf中的条目。

Windows

您需要在 Windows 上下载并安装 Apache;可以从httpd.apache.org/docs/2.2/platform/windows.html下载。请注意,您需要将以下代码片段添加到conf/httpd.conf中,该文件位于找到 Apache 应用程序的文件夹内:

<Directory "/apache/htdocs/">
AllowOverride All
Options None
Order deny, allow
</Directory>

Linux

如果您使用 Ubuntu,可以在help.ubuntu.com/8.04/serverguide/C/httpd.html找到友好的文档。要启用.htaccess文件,用于配置您的 Apache 服务器,您需要编辑/etc/apache2/sites-available/default,从以下代码片段中:

<Directory /var/www/>
Options Indexes FollowSymLinksMultiViews
AllowOverride None
   Order allow,deny
allow from all
   # Uncomment this directive is you want to see apache2's
   # default start page (in /apache2-default) when you go to /
   #RedirectMatch ^/$ /apache2-default/
</Directory>

到以下代码片段:

<Directory /var/www/>
Options Indexes FollowSymLinksMultiViews
AllowOverrideAll
   Order allow,deny
allow from all
   # Uncomment this directive is you want to see apache2's
   # default start page (in /apache2-default) when you go to /
   #RedirectMatch ^/$ /apache2-default/
</Directory>

配置 Apache

我们的 HTML5 Boilerplate 文件夹中包含一个名为.htaccess的文件。由于文件名以.开头,因此在 Finder/Windows 资源管理器或其他文件管理工具中列出文件时,.htaccess可能不会显示出来,如下面的截图所示:

配置 Apache

但是,如果您启用了操作系统上的隐藏文件显示,您将能够看到这个文件。

现在所需的就是将我们的网站文件(包括.htaccess文件)移动到我们刚刚设置的服务器上。Apache 会在所有文件夹中寻找.htaccess文件(除非通过配置设置告知不要这样做),因此将我们的.htaccess文件放在站点的父文件夹中就可以了。

一般来说,使用.htaccess文件进行测试并不是一个坏主意。但是,如果您想让您的网站真正快速,最好将配置直接放在 Apache 服务器的主配置文件(httpd.conf)中。不幸的是,并非所有的托管提供商都允许这样做。

如果您可以访问 Apache 服务器的主配置文件(httpd.conf),您应该从 HTML5 Boilerplate 的.htaccess文件中复制配置,并将其放在httpd.conf中的Directory标签内,如下面的代码片段所示:

<Directory /path/to/website/root>
[htaccess rules]
</Directory>

然后,您应该删除.htaccess文件,因为指令已经在服务器的主配置文件中了。

开箱即用的功能

HTML5 Boilerplate 的.htaccess文件提供的大多数优势并不是立即显而易见的。如果您的网站流量较低,且不会发出太多网络请求,您可能不会注意到使用 HTML5 Boilerplate 的.htaccess文件会有显著的差异。但是,当您出现高活动量的峰值(这并不罕见!)或突然有很多您网站所需的图像和视频的网络请求时,HTML5 Boilerplate 的.htaccess会自动帮助您。

只要您将.htaccess文件放在项目文件夹中,或者按照前面指示的设置 Apache 的主配置文件,所有这些功能都可以立即使用。

删除 ETags

实体标签ETags)验证浏览器缓存中的组件(如图像、文件等)是否与服务器上的组件匹配。不幸的是,ETags 带来的害处大于好处。大多数服务器默认启用 ETags,这就是为什么 HTML5 Boilerplate 的服务器配置文件阻止服务器提供它们的原因,如下面的代码片段所示:

<IfModule mod_headers.c>
  Header unset ETag
</IfModule>
FileETag None

注意

Steve Souders 深入探讨了为什么 ETags 无法解决它们设计的问题以及为什么您应该删除它们,网址为developer.yahoo.com/blogs/ydn/posts/2007/07/high_performanc_11/

Gzip 组件

Gzip是最流行的压缩方法。通过使用 Gzip 压缩文件,您可以确保文件在低带宽连接下更快地传输。有时,节省的文件大小高达 70%,使其成为一个很好的性能配置默认值。

让我们看看没有.htaccess Gzip 功能时我们的文件有多大。为了做到这一点,我们只需注释掉该部分,如下面的代码片段所示:

#<IfModule mod_deflate.c>
#
#  # Force deflate for mangled headers developer.yahoo.com/blogs/ydn/posts/2010/12/pushing-beyond-gzipping/
#  <IfModule mod_setenvif.c>
#    <IfModule mod_headers.c>
#      SetEnvIfNoCase ^(Accept-EncodXng|X-cept-Encoding|X{15}|~{15}|-{15})$ ^((gzip|deflate)\s*,?\s*)+|[X~-]{4,13}$ #HAVE_Accept-Encoding
#      RequestHeader append Accept-Encoding "gzip,deflate" env=HAVE_Accept-Encoding
#    </IfModule>
#  </IfModule>
#
#  # HTML, TXT, CSS, JavaScript, JSON, XML, HTC:
#  <IfModule filter_module>
#    FilterDeclare   COMPRESS
#    FilterProvider  COMPRESS  DEFLATE resp=Content-Type $text/html
#    FilterProvider  COMPRESS  DEFLATE resp=Content-Type $text/css
#    FilterProvider  COMPRESS  DEFLATE resp=Content-Type $text/plain
#    FilterProvider  COMPRESS  DEFLATE resp=Content-Type $text/xml
#    FilterProvider  COMPRESS  DEFLATE resp=Content-Type $text/x-component
#    FilterProvider  COMPRESS  DEFLATE resp=Content-Type $application/javascript
#    FilterProvider  COMPRESS  DEFLATE resp=Content-Type $application/json
#    FilterProvider  COMPRESS  DEFLATE resp=Content-Type $application/xml
#    FilterProvider  COMPRESS  DEFLATE resp=Content-Type $application/xhtml+xml
#    FilterProvider  COMPRESS  DEFLATE resp=Content-Type $application/rss+xml
#    FilterProvider  COMPRESS  DEFLATE resp=Content-Type $application/atom+xml
#    FilterProvider  COMPRESS  DEFLATE resp=Content-Type $application/vnd.ms-fontobject
#    FilterProvider  COMPRESS  DEFLATE resp=Content-Type $image/svg+xml
#    FilterProvider  COMPRESS  DEFLATE resp=Content-Type $image/x-icon
#    FilterProvider  COMPRESS  DEFLATE resp=Content-Type $application/x-font-ttf
#    FilterProvider  COMPRESS  DEFLATE resp=Content-Type $font/opentype
#    FilterChain     COMPRESS
#    FilterProtocol  COMPRESS  DEFLATE change=yes;byteranges=no
#  </IfModule>
#
#  <IfModule !mod_filter.c>
#    # Legacy versions of Apache
#    AddOutputFilterByType DEFLATE text/html text/plain text/css application/json
#    AddOutputFilterByType DEFLATE application/javascript
#    AddOutputFilterByType DEFLATE text/xml application/xml text/x-component
#    AddOutputFilterByType DEFLATE application/xhtml+xml application/rss+xml application/atom+xml
#    AddOutputFilterByType DEFLATE image/x-icon image/svg+xml application/vnd.ms-fontobject application/x-font-ttf #font/opentype
#  </IfModule>
#
#</IfModule>

现在,让我们通过浏览器开发者工具中的网络工具来查看通过网络传递到我们浏览器的文件的大小(在本例中是 Chrome 开发者工具):

Gzip 组件

现在,让我们通过从.htaccess中删除行首的#来启用 Gzip 的适当规则。注意下面的截图中的差异:

Gzip 组件

如果您想了解更多关于 Gzip 的信息,第四章, Smaller Components, Book of Speed, Stoyan Stefanov,网址为www.bookofspeed.com/chapter4.html,将是一个很好的起点。

使用 Expires 头文件进行更好的缓存控制

服务器可以告诉浏览器它们可以将文件保存在缓存中的时间有多长。这对于不经常更改的静态文件非常有用,并且将减少页面加载时间。HTML5 Boilerplate 的.htaccess文件有一组默认值适用于大多数静态文件,如下面的代码片段所示:

<IfModule mod_expires.c>
ExpiresActive on

# Perhaps better to whitelist expires rules? Perhaps.
ExpiresDefault                          "access plus 1 month"

# cache.appcache needs re-requests in FF 3.6 (thanks Remy ~Introducing HTML5)
ExpiresByType text/cache-manifest       "access plus 0 seconds"

# Your document html
ExpiresByType text/html                 "access plus 0 seconds"

# Data
ExpiresByType text/xml                  "access plus 0 seconds"
ExpiresByType application/xml           "access plus 0 seconds"
ExpiresByType application/json          "access plus 0 seconds"

# Feed
ExpiresByType application/rss+xml       "access plus 1 hour"
ExpiresByType application/atom+xml      "access plus 1 hour"

# Favicon (cannot be renamed)
ExpiresByType image/x-icon              "access plus 1 week"

# Media: images, video, audio
ExpiresByType image/gif                 "access plus 1 month"
ExpiresByType image/png                 "access plus 1 month"
ExpiresByType image/jpg                 "access plus 1 month"
ExpiresByType image/jpeg                "access plus 1 month"
ExpiresByType video/ogg                 "access plus 1 month"
ExpiresByType audio/ogg                 "access plus 1 month"
ExpiresByType video/mp4                 "access plus 1 month"
ExpiresByType video/webm                "access plus 1 month"

# HTC files  (css3pie)
ExpiresByType text/x-component          "access plus 1 month"

# Webfonts
ExpiresByType application/x-font-ttf    "access plus 1 month"
ExpiresByType font/opentype             "access plus 1 month"
ExpiresByType application/x-font-woff   "access plus 1 month"
ExpiresByType image/svg+xml             "access plus 1 month"
ExpiresByType application/vnd.ms-fontobject "access plus 1 month"

# CSS and JavaScript
ExpiresByType text/css                  "access plus 1 year"
ExpiresByType application/javascript    "access plus 1 year"
</IfModule>

这告诉服务器在每个类型的文件被访问后立即缓存请求,缓存时间由文本"access plus…"指定。例如,考虑以下代码片段:

# CSS and JavaScript
ExpiresByType text/css                  "access plus 1 year"
ExpiresByType application/javascript    "access plus 1 year"

这个片段让服务器告诉浏览器请求 CSS 和 JavaScript 文件时,要至少缓存这些文件一年,除非用户故意清除他们的缓存。

注意

Yahoo 关于加速网站的最佳实践详细解释了 Expires 头文件的作用,网址为developer.yahoo.com/performance/rules.html#expires

自定义 404 页面

HTML5 Boilerplate 提供了一个名为404.html的自定义 404 页面。但是,除非服务器知道在找不到资源时每次都要提供此文件,否则永远不会被使用。HTML5 Boilerplate 的.htaccess文件有一个配置,告诉服务器按如下方式使用此文件:

ErrorDocument 404 /404.html

确保使用完整路径引用404.html。例如,在 Mac 上,如果您将其托管在您的<username>文件夹下的网站文件夹中,则完整路径将是/~<username>/404.html

以下截图显示了当使用 HTML5 Boilerplate 的.htaccess文件时,浏览器如何呈现默认的 HTML5 Boilerplate 404 页面:

自定义 404 页面

强制使用最新的 IE 版本

Internet Explorer 利用meta标签来决定是否应该以兼容模式呈现站点,还是使用最新的渲染引擎来呈现它。

Google Chrome 发布了一个名为Chrome Frame的插件,可以从developers.google.com/chrome/chrome-frame/下载,如果安装在用户的计算机上,当用户使用较旧版本的 Internet Explorer 时,将提供现代浏览器的体验。当您的页面在较旧版本的 Internet Explorer 上被查看时,您的网站可以选择使用这个插件。要自动选择使用这个插件,将", chrome=1"附加到http-equiv meta标签的content属性值。

这个标签可以在 HTML 文件本身中设置,这就是 HTML5 Boilerplate 所做的,如下面的代码片段所示:

<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">

然而,由于 HTML5 Boilerplate 在html标签周围使用了条件注释,IE 将以兼容视图而不是 Chrome Frame 来呈现 HTML。因此,在html标签周围使用带有条件注释的meta标签是行不通的。HTML5 Boilerplate 的.htaccess文件将其设置为 HTTP 头,如下面的代码片段所示:

<IfModule mod_headers.c>
  Header set X-UA-Compatible "IE=Edge,chrome=1"
  # mod_headers can't match by content-type, but we don't want to send this header on *everything*...
<FilesMatch "\.(js|css|gif|png|jpe?g|pdf|xml|oga|ogg|m4a|ogv|mp4|m4v|webm|svg|svgz|eot|ttf|otf|woff|ico|webp|appcache|manifest|htc|crx|oex|xpi|safariextz|vcf)$" >
    Header unset X-UA-Compatible
</FilesMatch>
</IfModule>

这将强制 IE 尊重发送的 HTTP 头,并使用最新的渲染引擎,而不管meta标签陈述的是什么。您还可以设置 IE 使用任何您喜欢的渲染引擎。我们在附录中深入讨论了这个功能,你是专家,现在怎么办?,在什么是 meta x-ua-compatible?一节下。

注意

我们经过了大量详细的测试和评论,这些测试和评论为我们推荐使用这种方法设置 IE 兼容模式提供了信息,这些信息可以在 Github 的Issue 跟踪器上找到,网址为github.com/h5bp/html5-boilerplate/issues/378

使用 UTF-8 编码

字符编码是一种以字节序列表示文本数据的方式。不同的脚本有不同的标准,例如希腊语、日语等,但是创建 HTML 规范的标准机构 W3C 强烈推荐在 Web 上提供的所有文本都使用UTF-8作为事实上的编码方案,以确保所有浏览器都能正确呈现您的文本数据。.htaccess文件以以下方式设置它:

# Use UTF-8 encoding for anything served text/plain or text/html
AddDefaultCharset utf-8
# Force UTF-8 for a number of file formats
AddCharset utf-8 .css .js .xml .json .rss .atom

注意

Edward Z. Yang 在htmlpurifier.org/docs/enduser-utf8.html#whyutf8上写了一篇信息丰富的文章,解释了为什么 UTF-8 是字符编码的最佳选择;如果您对这个话题感兴趣,这篇文章值得一读。

提供正确的 MIME 类型

作为 HTTP 头发送的多用途互联网邮件扩展MIME)类型有助于浏览器决定如何处理发送的内容。例如,浏览器需要知道文件是样式表还是可下载的文本文档。服务器发送资源时返回的 MIME 类型 HTTP 头提供了这些信息。HTML5 Boilerplate 的.htaccess文件确保服务器在提供内容时提供正确的 MIME 类型。

例如,在我们的塞内加尔音乐节网站中,我们需要让浏览器理解我们的 Web 字体是字体文件而不是乱码文本。在我们的 HTML5 Boilerplate.htaccess文件中,以下行确保服务器返回正确的 MIME 类型,以便浏览器可以做到这一点:

AddType application/vnd.ms-fontobjecteot
AddType application/x-font-ttfttfttc
AddType font/opentypeotf
AddType application/x-font-woffwoff

注意

有关 MIME 类型的更多信息可以在Mozilla 开发者网络上找到,网址为developer.mozilla.org/en/Properly_Configuring_Server_MIME_Types#What_are_MIME_types.3F

阻止访问隐藏文件夹

如果您使用版本控制系统VCS)来管理网站的代码,则用于管理版本的隐藏文件夹(.git.svn)可能也存在于您的生产服务器中。您不希望任何人访问这些文件并找到可能被用来黑客攻击您的网站的任何信息。HTML5 Boilerplate 通过.htaccess文件阻止服务器提供对这些文件的内容的请求,如以下代码片段所示:

# Block access to "hidden" directories whose names begin with a period. This
# includes directories used by version control systems such as Subversion or Git.
<IfModule mod_rewrite.c>
RewriteCond %{SCRIPT_FILENAME} -d
RewriteCond %{SCRIPT_FILENAME} -f
RewriteRule "(^|/)\." - [F]
</IfModule>

阻止访问备份和源文件

例如,如果您的数据库在服务器上备份,例如database.sql.bak,您也不希望任何人访问,也不希望访问日志文件或任何源文件,例如用于 logo 的 Photoshop 文件 - 我们知道这种情况经常发生!.htaccess文件中的以下代码阻止访问这些文件:

# Block access to backup and source files
# This files may be left by some text/html editors and
# pose a great security danger, when someone can access them
<FilesMatch "(\.(bak|config|sql|fla|psd|ini|log|sh|inc|swp|dist)|~)$">
  Order allow,deny
  Deny from all
  Satisfy All
</FilesMatch>

这告诉服务器查找以以下任何扩展名结尾的文件:<filename>.bak<filename>.config等等,如果是这样,拒绝处理对这些文件的请求。它将返回403 Forbidden错误。

启动重写引擎

在进行任何 URL 重写之前,Apache 服务器要求您启动重写引擎。HTML5 Boilerplate 的.htaccess文件通过以下代码片段启用了这一点:

<IfModule mod_rewrite.c>
  Options +FollowSymlinks
RewriteEngine On
# RewriteBase /
</IfModule>

如果您的站点在子文件夹中,请删除RewriteBase行前的#并将其设置为从根目录到子文件夹的完整路径。

防止不存在的重定向文件夹出现 404 错误

在 Apache 中,如果您希望重定向从不存在的路径请求的 URL 到另一个路径,您需要禁用MultiViews

例如,如果您收到对http://example.com/beaches/10的请求,并且希望将其内部重定向到http://example.com/index.php?q=10,并且beaches文件夹不存在于您网站的根文件夹中,Apache 将抛出错误。HTML5 Boilerplate 的.htaccess文件通过使用以下代码语句防止这种情况发生:

Options -MultiViews

其他自定义

提供了许多其他自定义选项,但它们都被注释掉,因为它们需要仔细考虑,有时可能会产生意想不到的后果。

抑制或强制 URL 开头的“www。”

大多数人没有意识到http://example.comhttp://www.example.com在搜索引擎中被视为两个不同的站点。您可以强制重写 URL 以使用 www 或非 www。我更喜欢非 www URL,因为它比较短!

HTML5 Boilerplate 的.htaccess文件为您提供了这两种选择。默认情况下,配置会强制服务器将对http://www.example.com的请求重写为http://example.com。如果您喜欢另一种方式,可以让服务器将对http://example.com的请求重写为http://www.example.com,如以下步骤所述:

  1. 注释掉以下代码片段中显示的默认选项:
# Option 1:
# Rewrite "www.example.com -> example.com"
<IfModule mod_rewrite.c>
  RewriteCond %{HTTPS} !=on
  RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
  RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L]
</IfModule>
  1. 现在注释掉的默认部分应该看起来像以下代码片段:
# Option 1:
# Rewrite "www.example.com -> example.com"

# <IfModule mod_rewrite.c>
#  RewriteCond %{HTTPS} !=on
#  RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
#  RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L]
#</IfModule>

您可能已经注意到,我们所做的就是在每行前添加一个#字符和一个空格。

  1. 现在,我们将通过取消注释来启用第二个选项。通过取消注释更改以下代码片段:
# Option 2:
# To rewrite "example.com -> www.example.com" uncomment the following lines.
# Be aware that the following rule might not be a good idea if you
# use "real" subdomains for certain parts of your website.

# <IfModule mod_rewrite.c>
#   RewriteCond %{HTTPS} !=on
#   RewriteCond %{HTTP_HOST} !^www\..+$ [NC]
#   RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
# </IfModule>
  1. 取消注释的代码部分应该看起来像以下代码片段:
# Option 2:
# To rewrite "example.com -> www.example.com" uncomment the following lines.
# Be aware that the following rule might not be a good idea if you
# use "real" subdomains for certain parts of your website.

<IfModule mod_rewrite.c>
RewriteCond %{HTTPS} !=on
RewriteCond %{HTTP_HOST} !^www\..+$ [NC]
RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</IfModule>

我们所做的就是删除以<IfModule mod_rewrite.c>开头并以</IfModule>结尾的行前的#字符和空格。

无论您想使用哪个选项,请确保您不要同时启用这两个选项,因为这将阻止 Apache 提供您的页面。

从 iFrames 设置 cookies

IE 通常会阻止从 IFrame 中设置的 cookies。如果您需要设置这样的 cookies,特别是如果您有广告或社交网络插件,您需要发送隐私偏好平台项目P3P)标头。

.htaccess文件中查找与本节标题相同的注释,并更改以下行:

# <IfModule mod_headers.c>
#   Header set P3P "policyref=\"/w3c/p3p.xml\", CP=\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\""
# </IfModule>

在以下代码片段中:

<IfModule mod_headers.c>
  Header set P3P "policyref=\"/w3c/p3p.xml\", CP=\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\""
</IfModule>

注意

Eric Law 详细介绍了 IE 的 cookie 策略,可以在blogs.msdn.com/b/ieinternals/archive/2009/08/20/wininet-ie-cookie-internals-faq.aspx上阅读。

PHP 安全默认值

如果你正在使用 PHP,HTML5 Boilerplate 的.htaccess文件中有很多配置选项,可以使你的 PHP 安装更安全。如果你使用 PHP,你可以使用与抑制或强制 URL 开头的"www。"一节中概述的相同过程打开它们。

鉴于我们的网站不使用 PHP,我们不需要打开它们。

停止广告 Apache 版本

你可以防止 Apache 广告其版本,以减少恶意程序员利用特定版本的漏洞的可能性。以下是 Apache 版本的广告方式:

停止广告 Apache 版本

这个先前的截图显示了 Apache 版本号作为 HTTP 头发送到浏览器。

注意

你可以使用大多数浏览器自带的开发者工具来验证 HTTP 头。在这种情况下,我们使用 Chrome 的开发者工具资源选项卡。关于如何使用这个工具的更多信息,请参考 Chrome 的帮助中心developers.google.com/chrome-developer-tools/docs/network

这需要从服务器的主配置文件中进行配置,我们无法从.htaccess文件中进行配置。因此,让我们从 HTML5 Boilerplate 的.htaccess文件中删除以下指令,并替换为在/etc/apache2/httpd.conf中找到的指令(如果你使用 Windows 或 Linux,则该文件的路径将不同):

ServerTokens Prod

在将配置值应用到 Apache 服务器的主配置文件后,下面的截图显示了 Apache 发送的无版本 HTTP 头:

停止广告 Apache 版本

允许在特定 JS 和 CSS 文件中进行合并

有时,当请求发出时,你可能希望服务器将多个脚本或样式表文件合并为一个响应。请注意,这样做并不会加快页面加载速度,因为服务器需要自己的时间将这些文件拼接在一起。

这是我建议你在其他解决方案都失败时最后考虑的选项。理想情况下,你永远不应该这样做。

要做到这一点,首先取消.htaccess文件中的以下行:

#<FilesMatch "\.combined\.js$">
#  Options +Includes
#  AddOutputFilterByType INCLUDES application/javascript application/json
#  SetOutputFilter INCLUDES
#</FilesMatch>
#<FilesMatch "\.combined\.css$">
#  Options +Includes
#  AddOutputFilterByType INCLUDES text/css
#  SetOutputFilter INCLUDES
#</FilesMatch>

改为以下代码片段:

<FilesMatch "\.combined\.js$">
  Options +Includes
AddOutputFilterByType INCLUDES application/javascript application/json
SetOutputFilter INCLUDES
</FilesMatch>
<FilesMatch "\.combined\.css$">
  Options +Includes
AddOutputFilterByType INCLUDES text/css
SetOutputFilter INCLUDES
</FilesMatch>

然后,在js文件夹中,创建一个名为script.combined.js的文件。

在文本编辑器中打开script.combined.js文件,并使用以下语法将所有应该合并并输出到script.combined.js文件中的文件:

#   <!--#include file="<path/to/file.js>" -->
#   <!--#include file="<path/to/another-file.js>" -->

如果你想要动态合并样式表,你可以这样做。在css文件夹中创建一个名为style.combined.css的文件。

在文本编辑器中打开style.combined.css文件,并使用以下语法将所有应该合并并输出到style.combined.css文件中的文件:

#   <!--#include file="<path/to/file.css " -->
#   <!--#include file="<path/to/another-file.css>" -->

正如我之前提到的,这样做会使 Apache 对这些请求的响应变慢。你应该使用一个构建脚本来连接文件(我们将在第七章中研究构建脚本,使用构建脚本自动部署)。所以只有在没有其他选择的情况下取消这个设置。

在 CSS 的鼠标悬停效果中停止 IE 的屏幕闪烁

当你使用背景图片在链接上悬停时发生变化,IE 会出现闪烁。你可以通过更改.htaccess文件中的以下行来防止这种情况发生:

# BrowserMatch "MSIE" brokenvary=1
# BrowserMatch "Mozilla/4.[0-9]{2}" brokenvary=1
# BrowserMatch "Opera" !brokenvary
# SetEnvIfbrokenvary 1 force-no-vary

改为以下代码片段:

BrowserMatch "MSIE" brokenvary=1
BrowserMatch "Mozilla/4.[0-9]{2}" brokenvary=1
BrowserMatch "Opera" !brokenvary
SetEnvIfbrokenvary 1 force-no-vary

防止 SSL 证书警告

如果您只想在安全连接上提供您的网站,您需要获取一个安全套接字层SSL)证书,浏览器将使用该证书来识别您的网站。如果证书上的域与传入请求上的域不匹配,例如,您为https://secure.example.com拥有 SSL 证书,而在该域上托管的页面上加载的资产是从https://example.com提供的,但所有文件都托管在同一个 Apache 服务器上;那么浏览器将抛出警告,并通知用户无法验证网页的真实性。

您可以确保对没有 SSL 证书的域的请求被重定向到您拥有 SSL 证书的域。如果需要,您可以取消注释以下代码片段:

# <IfModule mod_rewrite.c>
#   RewriteCond %{SERVER_PORT} !⁴⁴³
#   RewriteRule ^ https://example-domain-please-change-me.com%{REQUEST_URI} [R=301,L]
# </IfModule>

以下是代码片段:

<IfModule mod_rewrite.c>
RewriteCond %{SERVER_PORT} !⁴⁴³
RewriteRule ^ https://example-domain-please-change-me.com%{REQUEST_URI} [R=301,L]
</IfModule>

请注意,https://example-domain-please-change-me.com的 URL 需要指向您拥有 SSL 证书的域。

注意

有关 SSL 和 SSL 证书的更多详细信息,请参阅 Linux 文档项目中的tldp.org/HOWTO/SSL-Certificates-HOWTO/x64.html

这涵盖了 HTML5 Boilerplate 的.htaccess文件提供的所有可选功能。让我们看看跨域策略以及如何设置它们。

您应该了解的跨域策略

当来自一个域的页面(例如http://example.com)需要来自另一个域(例如http://foo.com)的数据时,HTTP 请求被称为跨域请求。默认情况下,大多数浏览器不允许跨域请求数据,无论是数据还是 Flash 资产,以防止恶意访问。

但是,您可以在服务器上设置一个跨域策略文件(在上一个示例中,是从http://foo.com提供服务的服务器),允许浏览器访问这些资源。

Flash 需要在名为crossdomain.xml的文件中指定此策略文件,您可以在其中指定哪些域可以从服务器请求资产。

此文件包含在 HTML5 Boilerplate 中,默认情况下启用最严格的策略。如果您确实希望使用最不严格的策略,可以取消注释该选项,并注释掉最严格的选项。

注意

在放宽限制之前,确保充分了解允许跨域请求访问资产的影响。

您还可以通过设置 HTTP 标头来进行跨域 AJAX 请求,或限制对图像或字体的访问。这被称为跨域资源共享CORS)策略。

跨域 AJAX 请求

只有在请求页面与请求数据的 URL 位于同一域上时,才能进行 AJAX 请求。CORS 是 HTML5 的一个新功能,允许您从任何域进行 AJAX 请求,前提是已经给予了请求域的权限。通过在服务器上设置一个 HTTP 标头,您可以克服这个限制。让我们看看如何做到这一点。

以下是您可以进行的跨域请求的示例:

var CORSRequest = new XMLHttpRequest();
CORSRequest.onload = function(e){
  // Process returned data
}
CORSRequest.open('GET', 'http://nimbupani.com/data.json');
CORSRequest.send( null );

我们注意到浏览器会抛出错误,显示访问被禁止,如下面的截图所示:

跨域 AJAX 请求

现在,在我们托管在nimbupani.com上的.htaccess文件中,我们将取消注释以下指令:

#  <IfModule mod_headers.c>
#    Header set Access-Control-Allow-Origin "*"
#  </IfModule>

让我们再试一下我们的代码。啊哈!现在可以了!

这是最不严格的设置,可以允许任何域在您的服务器上进行 AJAX 请求。由于这个原因,非常容易进行大量的请求,也可以假装是您的网站并欺骗访问者等。请谨慎使用此设置。

启用 CORS 的图像

通常,浏览器允许从任何其他域链接所有图像。这称为热链接。在en.wikipedia.org/wiki/Inline_linking上了解更多信息。如果一个高流量的网站链接到托管在您服务器上的资产,您的托管提供商甚至可能因为带宽的过度使用对您处以罚款(或者您的网站可能会崩溃!)。如果您想要阻止这种情况,例如,如果您不希望http://example.com使用指向您服务器上图像的img元素的src属性,您可以通过更改.htaccess文件中的以下行来启用更严格的策略:

Header set Access-Control-Allow-Origin "*" env=IS_CORS

到以下行:

Header set Access-Control-Allow-Origin "http://example.com" env=IS_CORS

在这里,用只允许访问该图像的域名替换http://example.com。服务器将阻止任何其他域访问您域上的图像。

如果您希望多个域访问您的图像,您将不得不编写一个复杂的正则表达式比较原点,如下面的代码片段所示:

SetEnvIf Origin »
    "^http(s)?://(.+\.)?(example-1\.com|example-2\.com)$" origin_is=$0
  Header always set Access-Control-Allow-Origin %{origin_is}eenv=origin_is

在这种情况下,用您的域替换example-1\.com(注意在.com之前放置斜杠),同样适用于example-2\.com

Webfont 访问

大多数情况下,您将在与您将使用它们的相同域上托管字体。如果您在单独的域中托管字体,Firefox 将不会在没有正确的 HTTP 标头的情况下请求它们。这个指令已经在.htaccess文件中默认启用。如果您想要限制访问,您需要将这些行从以下内容更改:

<IfModule mod_headers.c>
  <FilesMatch "\.(ttf|ttc|otf|eot|woff|font.css)$">
    Header set Access-Control-Allow-Origin "*"
  </FilesMatch>
</IfModule>

到以下代码片段:

<IfModule mod_headers.c>
  <FilesMatch "\.(ttf|ttc|otf|eot|woff|font.css)$">
    Header set Access-Control-Allow-Origin "http://example.com"
  </FilesMatch>
</IfModule>

用您希望特别允许访问 Webfonts 的域名替换http://example.com

注意

如果您想要了解 CORS 启用的图像、Webfont 和 AJAX 请求的工作原理,并了解与crossdomain.xml的区别,您应该阅读code.google.com/p/html5security/wiki/CrossOriginRequestSecurity上的 HTML5security 项目 wiki 页面。

使用其他服务器配置文件

我们已经看到了如何使用 Apache.htaccess文件中提供的功能。但是还有其他类型服务器的配置文件的存储库,如 Ngnix、Node、Google App Engine、IIS 和 Lighttpd。以下表格包含配置文件名及其对应的服务器软件:

配置文件名 服务器软件
.htaccess Apache Web 服务器在httpd.apache.org/docs/2.2/howto/htaccess.html上。
Web.config IIS Web 服务器在learn.iis.net/page.aspx/376/delegating-configuration-to-webconfig-files/上。
Node.js Node Web 服务器从nodejs.org
Ngnix.conf Ngnix 服务器在wiki.nginx.org/Configuration上。
Lighttpd.conf Lighttpd 服务器在redmine.lighttpd.net/projects/lighttpd/wiki/TutorialConfiguration上。
App.yamlgae.py Google App Engine 在code.google.com/appengine/docs/python/config/appconfig.html上。

这些服务器的配置文件可在github.com/h5bp/server-configs上找到。

web.config

HTML5 Boilerplate 的web.config文件用于配置在 IIS7 服务器或更高版本上运行的站点的选项。

.htaccess文件一样,将其放在您网站的根文件夹中,即可被识别并用于配置 IIS7 服务器。

lighttpd.conf

与其他配置文件一样,将其放在 Lighttpd 服务器的根文件夹中以配置服务器。

nginx.conf

Nginx 是一个轻量级服务器,受到使用 Ruby on Rails 框架的网站的欢迎。

.htaccess文件一样,将此文件放在您网站的根文件夹中。此外,确保nginx-mime.types也在根文件夹中。这个文件是 Ngnix 所必需的,以确保它发送每个文件的正确 MIME 类型。

node.js

对于node.js配置文件,使用方式不同。配置文件假定您正在使用 Express/Connect 框架来管理应用程序的资源请求。在服务器端应用程序代码中,您可以使用以下内容启动服务器:

var h5bp = require('h5bp'); 
var app = express.createServer();
app.use(h5bp.server());
app.listen(3000);

这需要您使用 Node Package Manager(NPM)安装h5bp包和相同的express包。h5bp包有一系列配置,将在服务器启动时使用。如果您只想使用一些特定的配置,可以将它们作为选项传递给服务器函数,如下面的代码片段所示:

app.use(h5bp.server({
server: true,
setContentType: true,
removeEtag: true
});

Google App Engine

有些网站也是从 Google App Engine(code.google.com/appengine/)提供的,这需要您的网站后端使用 Java、Python 或 Go 编写。

您需要确保app.yaml文件位于您网站的根文件夹中。

以下表格包含 HTML5 Boilerplate 服务器配置中所有功能的摘要:

功能名称 Apache Nginx IIS Lighttpd Node.js Google App Engine
ETags
Gzip
过期头
自定义 404 页面
强制使用最新的 IE 版本
使用 UTF-8 编码
提供正确的 MIME 类型
阻止访问隐藏文件夹
阻止访问备份和源文件 是(仅~&.inc
停止广告服务器信息
启动重写引擎
防止不存在的重定向文件夹出现 404 错误
抑制或强制 URL 开头的“www。”
从 iFrames 设置 cookies
PHP 安全默认值
停止广告 Apache 版本
允许在 JS 和 CSS 文件中进行串联
在 CSS 滚动时停止 IE 中的屏幕闪烁
防止 SSL 证书警告
跨域 AJAX 请求
支持 CORS 的图像
Webfont 访问

摘要

我们深入研究了在几个服务器和配置文件上提供页面的内部工作。我们查看了一些默认提供的良好配置以及一些可选配置,您可以通过仔细理解来启用它们。

现在我们的网站几乎准备好出门了,我们将看一些其他方法来使它变得更好。

第六章:让您的网站更好

网站设计和开发的性质是这样的,不是所有的优化和建议都适用于所有情况。在本章中,我们将看看各种可用的优化工具以及它们最适合的情况,以使 HTML5 Boilerplate 网站加载和呈现更快。

为 Internet Explorer 找到最佳体验

Internet Explorer 8 及以下版本对标准和一致的呈现支持非常混乱。根据使用 Internet Explorer 访问您的网站的用户数量,您可能会或不会花费精力优化 Internet Explorer。

IE 的移动优先样式

媒体查询是 CSS 功能,允许您根据特定媒体特征的值应用不同的规则集。例如,如果浏览器的最小宽度为500像素,您可以使所有的h1元素变成红色,如下面的代码所示:

@media only screen and (min-width: 500px) {
h1 { color: red; }
}

然而,IE6、IE7 和 IE8 不理解媒体查询,通常用于根据不同的屏幕宽度调整宽度。因此,它们永远不会呈现出您为与某个媒体查询断点匹配的屏幕宽度的浏览器创建的优化样式(在上面的片段中为min-width: 500px)。在我们的 Sun and Sand Music Festival 网站中,我们在三个不同的媒体查询中有样式规则,如下面的代码片段所示:

@media only screen and (max-width: 300px){ /*CSS rules */ }

@media only screen and (max-width: 750px) { /*CSS rules */ }

@media only screen and (max-width: 1150px) { /*CSS rules */ }

这意味着 IE6、IE7 和 IE8 将呈现样式,就好像这些查询不存在一样!如果您指定的设备宽度规则在最后较小,那么这些规则很可能会覆盖较大设备宽度的规则,导致 Internet Explorer 8 及以下版本上的设计不够理想。

理想情况下,在这种情况下,您只希望 IE 呈现所有样式,并且用户可以滚动,如果必要的话,以便最大宽度的样式规则始终适用。为此,我们可以创建一个单独的ie.css文件,它将呈现main.css中的所有规则,除了这些规则将不再包含在媒体查询中。

手动完成这项工作很困难,几乎不可能维护。然而,Nicolas Gallagher 写了一个他发明的优雅解决方案,使用 Sass 来导入每个媒体查询断点的单独样式表,并将它们编译成两个单独的样式表;一个没有媒体查询(ie.css),另一个有媒体查询(main.css);我们将在下面看到这个。

ie.scss

ie.scss的代码片段如下:

@import "300-up";
@import "750-up";
@import "1150-up" /* Make sure largest is last */

main.scss

main.scss的代码片段如下:

@import "base";
@media (min-width:300px) {
    @import "300-up"; }
@media (min-width:750px) {
    @import "750-up"; }
@media (min-width:1150px) {
    @import "1150-up"; }

请注意,您需要在与main.scssie.scss相同的父文件夹中分别命名为300-up.scss750-up.scss1150-up.scss的每个文件。

index.html页面的head标签中,您现在可以编写以下代码:

<!--[if (gt IE 8) | (IEMobile)]><!-->
<link rel="stylesheet" href="/css/style.css">
<!--<![endif]-->

<!--[if (lt IE 9) & (!IEMobile)]>
<linkrel="stylesheet" href="/css/ie.css">
<![endif]-->

注意

Jake Archibald 还提供了一个更容易编写的解决方案,使用 Sass 在jakearchibald.github.com/sass-ie/。它利用了 Sass 3.2 的新功能,并且main.scssie.scss的组合略有不同。这需要对 Sass 有深入的了解,这超出了本书的范围。

在 IE6 和 IE7 中使用 jQuery 打印

IE6 和 IE7 不支持所有其他浏览器支持的:after伪选择器。这意味着我们的打印样式表,提供所有链接与链接文本一起打印的功能,在 IE6 和 IE7 中将无法工作。您可以简单地使用 jQuery 代码来克服这个问题。

注意

Bill Beckelman 在他的博客beckelman.net/2009/02/16/use-jquery-to-show-a-links-address-after-its-text-when-printing-in-ie6-and-ie7/上写了一篇关于这个问题的文章。IE 支持自己的专有onbeforeprintonafterprint事件,可以用于我们的优势。根据 Bill Beckelman 的工作,我们可以编写我们自己简单的 jQuery 代码来在 IE6 和 IE7 中打印链接 URL。

首先,我们检查window.onbeforeprint是否存在,因为这将表明此代码正在一个 IE 浏览器上执行。我们还想验证此浏览器是否支持生成的内容,因为我们只需要在不支持时使用此代码。以下代码片段检查window.onbeforeprint事件是否存在:

if (Modernizr.generatedcontent == false &&window.onbeforeprint !== undefined) {

然后,我们设置函数在onbeforeprintonafterprint发生时执行,如下所示的代码:

window.onbeforeprint = printLinkURLs;
window.onafterprint = hideLinkURLs;

然后,我们编写以下函数:

functionprintLinkURLs() {
$("a[href]").each(function() {
$this = $(this);
$this.data("originalText", $this.text());
$this.append(" (" + $this.attr("href") + ")");                
});
}

functionhideLinkURLs() {
  $("a[href]").each (function() {            
     $(this).text($(this).data("originalText"));
  });
}

在 Internet Explorer 中为禁用的表单元素设置样式

直到 9 版本,Internet Explorer 没有办法指示表单字段是否被禁用,除了使用该字段中的文本的颜色。有时,一个字段只是一个图标而不是文本(或者可能是一个空的输入文本框),在这种情况下,几乎不可能分辨哪些按钮被禁用,哪些没有。

对于 Internet Explorer 7 及以上版本,只需在main.css中添加以下规则,即可使禁用的字段显示方式与启用的字段明显不同:

.lt-ie9 input[type='text'][disabled], 
.lt-ie9 textarea[disabled] {
background-color: #EBEBE4;
}

如果您需要支持 Internet Explorer 6,则确保在具有disabled属性设置的表单元素上添加一个名为disabled的类,并将上一个规则修改为以下内容:

.lt-ie9 input.disabled, 
.lt-ie9 textarea.disabled {
background-color: #EBEBE4;
}

抑制 IE6 图像工具栏

在 IE6 中,当鼠标悬停在所有图像上时,都会显示工具栏。您可以通过在index.html文件的head标签中添加以下代码来禁用它们:

<metahttp-equiv="imagetoolbar" content="false">

使用工具更轻松地编写 CSS3

CSS3 处于前沿。一些属性需要所谓的供应商前缀。例如,3D 变换属性perspective在不同的浏览器中实现如下:

-webkit-perspective //Safari, Chrome
-ms-perspective // Internet Explorer
perspective // Firefox

就在不久之前,Firefox 将此属性实现为-moz-perspective,但后来放弃了对-moz-前缀的支持。

正如您将意识到的那样,很难跟踪哪个浏览器需要前缀,哪个浏览器不需要,而且不太可行的是,每次浏览器添加或删除对前缀的支持时,都要定期更新我们创建的所有网站。

为了使这更容易,我们可以使用没有这些前缀的抽象,这样一个具有哪个属性需要哪个前缀的更新索引的工具可以将它们转换为所需的最终 CSS。

这正是 Sass(sass-lang.com)或 Less(lesscss.org)提供的。Sass 是一种语言,带有一个编译器,将用 Sass 编写的代码转换为 Ruby 中的 CSS。Less 是一种类似的语言,但是用 JavaScript 编写。

在这两种情况下,这些语言都是 CSS 语法的扩展,这意味着您可以将现有的 CSS 文件复制到 Sass 或 Less 文件中,并将它们编译为纯 CSS 文件,而不会出现任何错误。

这些语言提供的额外功能包括使用 mixin、变量、函数等。

对于 Sass,Compass是一个额外的框架,提供了一个在compass-style.org/reference/compass/css3中找到的 CSS3 mixin 的库。Less 有许多选项;最受欢迎和经常更新的可以在 Twitter Bootstrap 中找到,在twitter.github.com/bootstrap/less.html#mixins中可用。以下部分向您展示如何在 Sass 和 Less 中创建使用 CSS 变换的规则。

Sass

Sass 的代码片段如下:

.btn-arrow {
  @include transform(scale(2));
}

Less

Less 的代码片段如下:

.btn-arrow {
.scale(2);
}

输出的 CSS

输出的 CSS 将如下所示:

.btn-arrow {
-webkit-transform: scale(2);
     -moz-transform: scale(2);
      -ms-transform: scale(2);
       -o-transform: scale(2);
transform: scale(2);
}

将 HTML5 Boilerplate CSS 转换为 Sass 或 Less

您通常只需将main.css文件重命名为main.scssmain.less,然后开始使用它作为基本的 Sass 或 Less 文件。要将这些文件编译为相应的 Less 或 Sass 文件,您可以使用 GUI-based 浏览器刷新软件,它会自动编译这些文件,比如LiveReload(livereload.com/)或Codekit(incident57.com/codekit)。

如果您熟悉命令行,可以安装 Less 或 Sass,并运行它们各自的命令行解释器将文件编译为纯 CSS。

如果您希望使用纯 Sass 或 Less 文件(而不是main.css文件的内容)开始,还有 HTML5 Boilerplate 的分支将样式表转换为 Sass。我们将在以下部分看到其中的两个。

HTML5 Boilerplate Compass 扩展

有一个可用于与 Compass 一起使用的 Compass 扩展,位于github.com/sporkd/compass-html5-boilerplate。请注意,它的更新频率不如在 HTML5 Boilerplate 中找到的main.css文件。这是广泛模块化的,并将main.css文件拆分为多个 Sass 文件。结果 CSS 文件中的 CSS 注释也被删除。

HTML5 Boilerplate Sass 分支

有一个 Sass 分支的main.css经常更新,网址为github.com/grayghostvisuals/html5-boilerplate/tree/h5bp-scss,您可以使用它,如果您只想要一个基本的 Sass 文件来开始。这个版本使用 Sass 变量,但不会将文件拆分为单独的文件。

不幸的是,HTML5 Boilerplate 没有最新的 Less 分支。但是,您可以将main.css重命名为main.less,然后将其用作 Less 文件。

打印注意事项

如果您的网页可能会被打印,您可能希望考虑使用可打印的颜色。一些浏览器认为一些颜色太浅,无法打印,并会强制使用较深的颜色进行打印;merttol.com/articles/code/too-light-for-print.html上有关于这个有趣怪癖的更多细节。

附录,您是专家,现在怎么办?,详细介绍了打印样式背后的推理和原理。

查找和使用 polyfills

大多数 HTML5 和 CSS3 功能在不同浏览器中具有不同级别的支持,因此,要么使用 JavaScript 代码在不支持这些功能的浏览器中模拟这些功能,要么提供一个可变的视图。这些代码片段称为 polyfills。

我帮助维护html5please.com,这是一个关于一些流行的 HTML5 和 CSS3 功能的 polyfills 的主观列表。

要注意的是,在不支持许多功能的浏览器上使用大量 polyfills 会带来性能损失。

当您使用 polyfills 时,请确保使用 Modernizr 的load函数,就像我们在第四章中为 Sun and Sand 音乐节网站的音频 polyfill 所做的那样。这将防止在支持您想要使用的功能的浏览器上不必要地加载 polyfills。

在 Modernizr Wiki 上提供了所有类型 polyfills 的全面列表,网址为github.com/Modernizr/Modernizr/wiki/HTML5-Cross-browser-Polyfills

加快您的网站速度

如果您的页面使用了大量资源,比如图片,那么也许预取这些资源会更明智,这样您的页面加载速度会更快。DNS 预取就是一种方法。

DNS 预取

DNS 预取通知浏览器页面加载过程中提前引用的其他域名资源,以便它可以解析这些域名的 DNS 解析。

浏览器必须在域名服务器(DNS)上查找域名,以确定其在互联网上的位置。有时,它必须经过多层域名服务器,这可能非常缓慢,而且并不总是一致的。通过使用 DNS 预取,即使在用户点击链接或加载资源之前,也会对特定域名的 DNS 解析进行处理,并且资源可以更快地获取。

谷歌表示,这可以节省大约 200 毫秒的时间,用于托管在外部域名上的资源。

如果您将资产托管在像亚马逊的 S3 这样的内容交付网络(CDN)上,甚至是引用 Google 的 API 或 Microsoft 的 API CDN,那么在预取这些文件时会更快。

通过在 HTML 文件的head标签中编写以下代码来调用 DNS 预取:

<link rel="dns-prefetch" href="//image.cdn.url.example.com">

理解预取的浏览器将立即开始尝试解析href属性中的链接的 DNS。以下是它在 Amazon S3 上的样子:

<link rel="dns-prefetch" href="//s3.amazonaws.com">

目前,Firefox 3.5 及更高版本,Safari 5 及更高版本,以及 IE9 及更高版本支持 DNS 预取。

使您的站点在搜索引擎上更加可见

尽管您网站的内容最重要,但确保其他一切都支持更好地在搜索引擎上显示内容也很重要。以下部分解释了一些您可以做到这一点的方法。

引导搜索蜘蛛到您的站点地图

站点地图通知搜索引擎站点内页面的存在,否则这些页面是无法发现的;也许它们在站点的其他页面或外部站点上都没有链接。

一些 CMS 提供插件来生成站点地图,列在code.google.com/p/sitemap-generators/wiki/SitemapGenerators,或者您可以按照www.sitemaps.org/protocol.html上的指南自己编写一个。

一旦编写了站点地图,您可以通过添加以下内容,让搜索引擎蜘蛛在爬行您的网站时发现它:

<linkrel="sitemap" type="application/xml" title="Sitemap" href="/sitemap.xml">

您还可以将站点地图提交给各个搜索引擎,而不是在 HTML 页面中链接到站点地图,如果您希望尽可能减小页面大小。

实施 X-Robots-Tag 标头

您可能会有一个暂存服务器,例如staging.example.com,用于您的站点example.com。如果外部站点链接到暂存服务器上的文件(比如您在论坛上询问某些功能不起作用并链接到暂存服务器),即使域名不在robots.txt文件中,或者没有robots.txt文件,它也可能被搜索引擎索引。

为了防止这种情况,您可以通过将以下代码片段附加并取消注释的方式,将X-Robots-Tag HTTP 标头标签添加到暂存服务器上的.htaccess文件中:

# ------------------------------------------------------------
# Disable URL indexing by crawlers (FOR DEVELOPMENT/STAGE)
# ------------------------------------------------------------

# Avoid search engines (Google, Yahoo, etc) indexing website's content
# http://yoast.com/prevent-site-being-indexed/
# http://code.google.com/web/controlcrawlindex/docs/robots_meta_tag.html
# Matt Cutt (from Google Webmaster Central) on this topic:
# http://www.youtube.com/watch?v=KBdEwpRQRD0

# IMPORTANT: serving this header is recommended only for
# development/stage websites (or for live websites that don't
# want to be indexed). This will avoid the website
# being indexed in SERPs (search engines result pages).
# This is a better approach than using robots.txt
# to disallow the SE robots crawling your website,
# because disallowing the robots doesn't exactly
# mean that your website won't get indexed (read links above).

# <IfModulemod_headers.c>
#   Header set X-Robots-Tag "noindex, nofollow, noarchive"
#   <FilesMatch "\.(doc|pdf|png|jpe?g|gif)$">
#     Header set X-Robots-Tag "noindex, noarchive, nosnippet"
#   </FilesMatch>
# </IfModule>

尾部斜杠重定向

搜索引擎将文件夹 URL http://example.com/foohttp://example.com/foo/视为两个不同的 URL,因此会将内容视为彼此的副本。为了防止这种情况,重写 URL,要么将http://example.com/foo改为http://example.com/foo/,要么将http://example.com/foo/改为http://example.com/foo

我们这样做的方法是编辑 Apache 服务器的.htaccess文件,并添加以下重写规则(有关如何编辑.htaccess文件的详细信息,请参见第五章,“自定义 Apache 服务器”)。

选项 1:将 example.com/foo 重写为 example.com/foo/

以下代码片段帮助我们将example.com/foo重写为example.com/foo/

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !(\.[a-zA-Z0-9]{1,5}|/|#(.*))$
RewriteRule ^(.*)$ $1/ [R=301,L]

选项 2:将 example.com/foo/重写为 example.com/foo

以下代码片段帮助我们将example.com/foo/重写为example.com/foo

RewriteRule ^(.*)/$ $1 [R=301,L]

如果您有现有的重写规则,请执行以下步骤,以确保正确设置重写规则。不这样做可能会导致不正确的重定向和 404 错误。

  • 备份:在开始添加重定向之前,备份您要添加重定向的.htaccess文件。这样,如果因为.htaccess文件中的错误而无法访问您的站点,您可以快速返回到备份文件。

  • 不要附加或替换现有的重写规则:不要附加或替换您正在使用的 CMS 的现有规则,而是将它们合并在一起。

  • 观察重写规则的顺序:确保您先添加斜杠,然后再添加可能重写末尾路径的现有规则。

  • 确认RewriteBase路径:如果您的网站在子文件夹中,请确保为您的重写规则设置了正确的RewriteBase路径。如果您有一个有效的RewriteBase路径,请不要删除它。

注意

最后,考虑从 Google 的SEO 入门指南中实施指南,网址为googlewebmastercentral.blogspot.com/2008/11/googles-seo-starter-guide.html

处理没有 JavaScript 的用户

HTML5 Boilerplate 提供了一个名为no-js的类,当 Modernizr 在html标签上检测到 JavaScript 时,它会被替换为一个名为js的类。使用这个类名,你可以为禁用 JavaScript 时网站的外观制定样式。

在我们的 Sun and Sand Festival 网站上,当 JavaScript 未启用时,点击Day 2链接不会产生任何效果。

你可以通过以下方式查看在各种浏览器上禁用 JavaScript 时网站的工作方式:

  • Firefox:进入偏好设置,点击内容,然后取消勾选启用 JavaScript复选框。

  • Chrome:下载Chrome Web Developer扩展,并在扩展内禁用 JavaScript。

  • Safari:在开发菜单上点击禁用 JavaScript菜单项。当你在 Safari 的偏好设置窗格的高级选项卡上勾选显示开发工具栏时,你就可以看到开发菜单。

  • Internet Explorer:在设置菜单中点击Internet 选项,然后点击自定义级别,勾选在 Active scripting 中禁用菜单。

  • Opera:点击快速偏好设置,取消选择启用 JavaScript选项。

让我们确保在 JavaScript 不可用时选项卡不会渲染,并确保整个列表同时显示,如下面的截图所示:

处理没有 JavaScript 的用户

我们可以通过编辑main.css来利用no-js类来实现这一点。首先,我们需要删除选项卡导航,如下面的代码所示:

.no-js .t-tab__nav {
display: none;
}

然后,我们需要确保这两个列表在特定情况下是静态定位,而不是绝对定位在彼此下方,如下面的代码所示:

.no-js .t-tab__body {
position: static;
}

我们需要确保在Day 2的特定情况下不应用hidden类,这样我们就可以一次看到所有的艺术家,如下面的代码所示:

.no-js .t-tab__body.hidden {
display: block !important;
visibility: visible;
}

现在,当你重新启用 JavaScript 时,你会注意到选项卡导航出现了,一切都按你的预期运行。

优化你的图片

你添加到页面上的每个资源都是对服务器的额外请求,也是浏览器在宣布页面完成之前额外的网络请求。网络请求通常是页面加载中最慢的组件。这在移动设备上特别明显,当在 3G 甚至更低的连接上浏览网站时。你的文件越小,它们就会越快地到达浏览器。

如果可以避免使用大图片,最好不要使用。

8 位 PNG 文件

如果考虑使用 GIF 格式的图片,应该始终使用 PNG。PNG 格式的图片要轻得多,体积也小得多。此外,8 位 PNG 文件的体积要小得多。

如果你使用 PNG 格式的图片,应该使用带有完整 alpha 通道的 PNG-8,这样可以兼容 IE6。确保验证最终输出,以确保它们不会太粗糙或像素化。

图片优化工具

HTML5 Boilerplate 中有构建工具可以优化图片,我们将在下一章中进行讨论。还有一些独立的工具也值得一看,当你想要一次压缩一堆图片时。如果你希望上传你的图片并对其进行优化,可以在smushit.com/ysmush.it/上进行。

ImageAlpha

如果你有 24 位 PNG 图片,可以使用从pngmini.com下载的工具将它们转换为带有完整 alpha 通道的 8 位 PNG 文件。这个工具只适用于 Mac OS X。

pngquant.org上列出了适用于其他操作系统的图形用户界面和命令行工具。

ImageOptim

如果您想一次优化各种格式的图像,ImageOptim将是您最佳的选择。您可以从imageoptim.com下载。这也仅适用于 Mac OS X,并利用多个工具执行这些优化。

如果您想在其他系统上使用类似的东西,您可以为每种图像格式下载您需要的特定工具。以下表格列出了一些流行图像格式的工具:

格式 工具
动画 GIF Gifsiclewww.lcdf.org/gifsicle/
JPEG Jpegtranjpegclub.org/
PNG Pngcrushpmt.sourceforge.net/pngcrush/``Imageworsenerentropymine.com/imageworsener/``Optipngoptipng.sourceforge.net/``PNGOUT advsys.net/ken/utils.htm

如果您想了解更多关于使用这些优化工具的信息,请阅读 Stoyan Stefanov 关于网络图像优化的幻灯片,网址为www.slideshare.net/stoyan/image-optimization-for-the-web-at-phpworks-presentation。关于 PNG 和 JPEG 图像格式还有更多巧妙的优化方法,可以在Smashing Magazine上找到详细信息,网址分别为www.smashingmagazine.com/2009/07/15/clever-png-optimization-techniqueswww.smashingmagazine.com/2009/07/01/clever-jpeg-optimization-techniques/

使用图像精灵

对于每个资源进行网络请求需要很长时间。为了使这些更小,您可以将多个图像文件合并为一个单一的图像文件,只需请求一次,并且可以缓存很长时间,以便页面加载速度显著加快。如果您的页面将在互联网连接非常低带宽的设备上查看,这将特别有用。

这意味着,您可以将多个图像合并为一个大图像,并在所有选择器上使用 CSS 背景属性,其中这些图像将被使用。让我们将所有艺术家的图像转换为一个大精灵,并将图像元素替换为背景图像。

以下是我们的最终精灵:

使用图像精灵

让我们替换index.html中的图像元素,就像以下这样:

<img width="100" height="100" class="t-media__aside t-image--artist" src="img/artist-tinariwen.png">

使用以下内容:

<i class="t-artist__image artist-tinariwen"></i>

我们为每位艺术家都这样做。然后,在我们的style.css中,我们添加以下代码片段:

.t-artist__image {  
background: url(../img/artists-image.png) top left no-repeat, 
url(../img/bg-artist.png) no-repeat center center;
float: left;  
display: block;  
}
.artist-asa { background-position:  -0px -0px, 0 0; }
.artist-kidjo { background-position:  -0px -100px, 0 0; }
.artist-kuti { background-position:  -100px -0px, 0 0; }
.artist-sangre { background-position:  -100px -100px, 0 0; }
.artist-tinariwen { background-position:  -200px -0px, 0 0; }
.artist-toure { background-position:  -200px -100px, 0 0; }

最终页面没有发生任何变化,只是我们现在将这些图像的网络请求数量减少到 1 个而不是 6 个。通过优化最终的精灵,我们甚至可以使这个请求更快。

生成精灵似乎是很多工作,但有许多工具可以帮助完成这项工作。

从 Adobe Photoshop 中的 CSS 精灵

使用arnaumarch.com/en/sprites.html中记录的说明,您可以使用 Photoshop 中的脚本文件选择一个图像文件夹,并生成使用这些文件中的图像定位和校正为背景图像的相关 CSS 文件。

在使用此工具时,有一些需要注意的事项,如下所述:

  • 确保文件夹只包含您想要添加到精灵中的图像

  • 生成的 CSS 文件位于用于创建精灵的文件夹内

  • 生成的精灵在 Adobe Photoshop 中打开,您需要在将其保存到所选位置之前裁剪它

使用 Compass 的 CSS 精灵

Compass——Sass 的框架——可以在编译时将您的图像拼接在一起,并在您的 Sass 文件中引用这些图像,然后在生成的 CSS 文件中将其转换为精灵。

您只需要确保在图像文件夹中设置一个文件夹,以便为每个图像设置正确的名称,如下列表所述(摘自 Compass 文档):

  • images/my-icons/new.png

  • images/my-icons/edit.png

  • images/my-icons/save.png

  • images/my-icons/delete.png

名称my-icons可以是您喜欢的任何名称。然后在 Sass 文件中,使用以下代码:

@import "my-icons/*.png";
@include all-my-icons-sprites;

在上一步中使用的名称与my-icons相同。完成!Compass 会生成一个包含以下代码的 CSS 文件:

.my-icons-sprite,
.my-icons-delete,
.my-icons-edit,
.my-icons-new,
.my-icons-save   { background: url('/images/my-icons-s34fe0604ab.png') no-repeat; }

.my-icons-delete { background-position: 0 0; }
.my-icons-edit   { background-position: 0 -32px; }
.my-icons-new    { background-position: 0 -64px; }
.my-icons-save   { background-position: 0 -96px; }

现在,在您的标记中使用适当的类名,以向您的元素添加适当的图像。

SpriteMe

SpriteME,可在spriteme.org/上获得,是一个书签工具,可分析页面上使用的图像并将其制作成精灵。如果您有现有站点要转换为使用精灵,这将是一个很好的起点。

增强 Google Analytics

Google Analytics可以跟踪多种数据类型,以下是一些易于明显的增强,您可以对您的分析数据进行的。

添加更多跟踪设置

Google Analytics 提供了许多可选设置来进行跟踪,您无需在.push()方法上使用;而是可以直接附加到初始数组上。而不是以下内容:

var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-XXXXX-X'']);
_gaq.push(['_trackPageview']);

您可以执行以下操作:

var _gaq = [['_setAccount', 'UA-XXXXX-X'],['_trackPageview']];

匿名化 IP 地址

在一些国家,不得将个人数据转移到法律不那么严格的司法管辖区之外(即从德国到欧盟之外)。因此,使用 Google Analytics 脚本的网站管理员可能需要确保不会将个人(可跟踪的)数据传输到美国。您可以使用_gat.anonymizeIp选项来实现。使用时看起来像这样:

var _gaq = [['_setAccount', 'UA-XXXXX-X'], ['_gat._anonymizeIp'], ['_trackPageview']];

在 Google Analytics 中跟踪 jQuery AJAX 请求

史蒂夫·施瓦茨写道,您可以在plugins.js中使用的代码,可以让您跟踪 jQuery AJAX 请求,网址是www.alfajango.com/blog/track-jquery-ajax-requests-in-google-analytics。以下代码片段显示了该脚本:

/*
 * Log all jQuery AJAX requests to Google Analytics
 * See: http://www.alfajango.com/blog/track-jquery-ajax-requests-in-google-analytics/
 */
if (typeof _gaq !== "undefined" && _gaq !== null) {
  $(document).ajaxSend(function(event, xhr, settings){
    _gaq.push(['_trackPageview', settings.url]);
  });
}

在 Google Analytics 中跟踪 JavaScript 错误

如果您想要使用 Google Analytics 在页面上跟踪 JavaScript 错误,可以使用以下脚本来实现,在index.html页面中定义了 Google Analytics 变量_gaq之后添加:

(function(window){
var undefined, 
link = function (href) {
var a = window.document.createElement('a');
a.href = href;
return a;
    };
window.onerror = function (message, file, row) {
var host = link(file).hostname;
    _gaq.push([
      '_trackEvent',
      (host == window.location.hostname || host == undefined || host == '' ? '' : 'external ') + 'error',
message, file + ' LINE: ' + row, undefined, undefined, true
    ]);
  };
}(window));

总结

在本章中,我们看了如何为 Internet Explorer 的用户提供更好的体验。我们还简要考虑了一些工具,可以帮助我们编写更高效、更健壮的样式表,更易于在 CSS 的最新发展中进行维护。我们看了如何使用 polyfills 编写加载更快、更安全的页面。我们详细了解了在禁用 JavaScript 时如何渲染 Sun and Sand 网站,并将艺术家的图像拼接成精灵并保存在多个网络请求中。

在下一章中,我们将看看如何使用 HTML5 Boilerplate 提供的构建脚本来自动部署我们的网站。

第七章:使用构建脚本自动化部署

我们准备部署我们的网站了!但在我们这样做之前,我们应该确保我们最小化了所有脚本和优化了图像,这样这些页面就可以在全球任何地方尽可能快地加载。我们可以通过在命令行执行脚本来自动化这些任务。让我们看看我们有以下哪些选项。

构建脚本

一旦你的项目完成,你想要生成剥离注释并优化快速加载的文件。在软件项目中通常使用软件构建系统来实现类似的目标。HTML5 Boilerplate 的构建脚本提供了针对典型网页开发项目所需的任务范围。

脚本只能在您确认您的项目已准备好部署并且已经经过充分测试后使用。构建脚本只是自动化了去除注释、优化文件和确保文件适合生产的过程。

目前 HTML5 Boilerplate 贡献者积极维护有两种构建脚本;这些在下一节中探讨。

Ant 构建脚本

Ant 构建脚本是一组在 Apache Ant 构建系统(ant.apache.org/)之上工作的文件,这个系统自从 HTML5 Boilerplate 的早期版本以来就一直存在。它提供了各种选项,如下所述:

  • 发布文件到测试、开发和生产环境

  • 使用JSHintJSLint检查你的脚本文件的语法和代码质量,或使用CSSLint检查你的样式表

  • 合并并压缩所有 JavaScript 文件到一个文件中,并更新 HTML 页面,引用这个新文件

  • 通过删除注释、空白字符并压缩内联样式和脚本来清理和整理 HTML 标记

  • 合并并压缩所有样式表,并更新 HTML 页面,引用新文件,而不是多个 CSS 文件

  • 编译样式预处理器文件,如 Less 或 Sass,生成最终的 CSS 样式表,并更新 HTML 页面中的引用

  • 使用来自optipng.sourceforge.net/的 OptiPNG 和来自jpegclub.org/jpegtran/的 JPEGTran 分别优化img文件夹内的 PNG 和 JPEG 图像

  • 使用来自github.com/jsdoc3/jsdoc的 JSDoc3 从你的脚本构建文档

Node 构建脚本

一个新的基于 Node 的构建脚本,位于nodejs.org/,正在积极开发中。虽然它还没有用于生产,但它提供了很多与 Ant 构建脚本相似的任务,还有一些以下描述的新特性:

  • 合并并压缩所有 JavaScript 文件到一个文件中,并更新 HTML 页面,引用这个新文件

  • 合并并压缩所有样式表,并更新 HTML 页面,引用新文件,而不是多个 CSS 文件

  • 通过删除注释、空白字符并压缩内联样式和脚本来清理和整理 HTML 标记

  • 使用 OptiPNG 和 JPEGTran 分别优化img文件夹内的 PNG 和 JPEG 图像

监视项目文件的变化,并在它们发生变化时自动运行构建脚本并在浏览器中重新加载打开的页面。

使用哪个构建脚本?

根据你熟悉的平台,你可以选择一个而不是另一个。这两个构建脚本都足够稳定,可以用来部署你的生产文件,所以你的选择取决于你最习惯使用哪个。

如果你已经安装了 Ant,那么 Ant 构建脚本可能是一个明显的选择。如果你发现自己经常使用 Node 或者在你的项目中使用它,那么 Node 构建脚本可能是一个好的起点。在本章中,我们将查看如何使用这两个工具,这样你就可以熟练掌握它们中的任何一个。

使用 Ant 构建脚本

首先,通过在你的命令行工具中输入以下内容来确认你的系统上是否安装了 Ant:

ant–version

如果你还没有安装 Ant,请在进行下一步之前先安装它。

注意

Ant 默认安装在 Mac 上,而在大多数 Linux 平台上作为软件包安装。对于 Windows,安装 Ant 稍微复杂一些。你需要从www.oracle.com/technetwork/java/javase/downloads/index.html安装 Java SDK,然后下载WinAntcode.google.com/p/winant/并将其安装程序指向Program Files/Java/jre6/bin/

接下来,你需要安装ant-contrib ,这是一个为 Ant 提供了许多功能的工具,HTML5 构建脚本使用了这些功能。WinAnt 在你使用它在 Windows 上安装 Ant 时会自动安装这个工具。然而,对于 Linux 用户,你可以使用yum 作为软件包来安装它。在 Mac 上,你可以安装 MacPorts (www.macports.org/install.php),然后在你通常的命令行工具(通常是终端)中输入以下内容:

sudo port install ant-contrib

最后,确保图像优化工具已安装。对于 Mac 用户,你需要确保你有jpegt ran (www.ijg.org/)和optipng (optipng.sourceforge.net/)安装在你的路径上。你可以通过在你的命令行终端中输入以下内容来安装这两个文件:

sudoport install jpeg optipng

注意

PATH是一个环境变量,它包含了一系列文件夹,当您输入一个命令时,命令行界面会在这些文件夹中搜索。你可以从www.cs.purdue.edu/homes/cs348/unix_path.html了解如何添加文件夹到路径。

如果你在 Windows 上,Ant 构建脚本项目中包含了这些图像工具所需的二进制文件供你安装。

安装构建脚本

在终端(或你的命令行工具)中,我们将导航到我们的项目文件夹并使用 Git 安装构建脚本,如下面的屏幕截图所示:

安装构建脚本

现在我们必须将构建脚本的文件夹名称从ant-build-script更改为build,然后才能继续。这可以通过使用以下命令来完成:

mv ant-build-script build

完成后,让我们使用以下命令导航到构建脚本文件夹:

cd build

现在,让我们执行构建脚本!打开你的命令行工具并输入以下内容:

ant build

如果你正确设置了你的构建脚本文件夹,那么你应该得到以下屏幕:

安装构建脚本

然后,在任务执行后,你应该得到以下输出:

安装构建脚本

现在,你有一个全新的发布文件夹,其中存储了优化后的文件。让我们打开发布文件夹中的index.html页面,在 Chrome 浏览器中使用 Chrome 开发者工具的网络标签,观察加载的文件及其相关大小,看看所有已经优化的内容。

请注意,你必须打开网络标签来记录正在请求的文件。

缩小后的图片文件

网络标签记录了所有用于index.html的图片。我们可以看到,在发布文件夹中用于index.html页面的图片明显比原来的大小要小。

在以下屏幕截图中,屏幕截图的底部部分显示了发布文件夹中的图片列表,这些图片明显比我们原始项目中使用的图片要小(列表在屏幕截图的顶部部分):

缩小后的图片文件

缩小后的 CSS 文件

我们注意到,在我们使用构建脚本之前,我们的 CSS 文件叫做main.css,大约有 21KB,但在使用构建脚本后,文件被重命名,现在几乎是原来大小的一半,如下屏幕截图所示:

缩小后的 CSS 文件

缩小且更少的 JS 文件

执行构建脚本后,你会注意到main.jsplugin.js已经合并成了一 个。他们不仅被合并在一起,而且被压缩了,导致最终脚本文件的大小更小。

通过构建脚本生成的index.html页面仅调用以下屏幕截图底部部分所示的四种 JavaScript 文件,与原来放在文件夹顶部的五种 JavaScript 文件相比:

缩小且更少的 JS 文件

文件中没有注释

发布文件夹中的 HTML、CSS 和 JS 文件没有包含 HTML5 Boilerplate 文件中的注释。

构建选项

Ant 构建脚本有一些默认不执行的任务,但当你需要时可以为你提供。以下各节解释了这些任务允许你做什么。

压缩标记

默认情况下,Ant 构建脚本在优化时不会从index.html页面中移除空白字符;如果你也想移除 HTML 文件中的空白字符并对其进行压缩,你可以执行以下操作:

ant minify

防止图片优化

当执行构建脚本时,你会注意到脚本花在优化图像上的时间最长。如果你仅仅是为了测试最终的生产准备文件而执行构建脚本,那么你就不需要优化图像。在这种情况下,你应该执行以下命令:

ant text

使用 CSSLint

CSS Lint(csslint.net)是一个开源的 CSS 代码质量工具,它对你的代码进行静态分析,并标记出无效或可能导致问题的样式规则。要在你项目的 CSS 文件上使用 CSS Lint,只需输入以下内容:

ant csslint

通常,你会看到一大堆警告。CSS Lint 有很多你可以设置的选项。要做到这一点,打开build中的config文件夹内的project.properties文件。通过使用以下命令取消注释这一行:

#tool.csslint.opts =

=符号后输入你想与 CSS Lint 一起使用的所有选项并保存。你可以在github.com/stubbornella/csslint/tree/master/src/rules中找到可以使用的各种选项。

使用 JSHint

JSHint(jshint.com)是一个由社区驱动的工具,用于检测你的 JavaScript 代码中的错误和潜在问题,并强制执行你的团队的编码约定。要对你的 JavaScript 文件执行 JSHint,去到你的项目并执行以下操作:

ant jshint

执行后,我们会看到一大堆错误被列出来,针对我们的main.js。 corrected file 包含在本章的代码中。一旦纠正,你还会注意到有一大堆错误被抛出,针对plugin.js中的代码。这是因为我们使用了平滑滚动插件的压缩代码。让我们用项目仓库中的未压缩代码替换它,项目仓库的地址是github.com/kswedberg/jquery-smooth-scroll/blob/master/jquery.smooth-scroll.js

现在,我们得到一大堆错误,所有的错误都在告诉我们需要使用更严格的比较运算符。让我们为当前项目关闭这个选项。我们可以通过打开build文件夹内的config文件夹中的project.properties文件并取消注释以下允许你使用自己的 JSHint 选项的行来实现:

#tool.jshint.opts

改为以下代码片段:

tool.jshint.opts = maxerr=25,eqeqeq=false

注意

更多关于选项的信息可以在 JSHint 网站上的jshint.com找到。

我们的错误消失不见了!

设置 SHA 文件名

合并和压缩后的 CSS 和 JS 文件名被设置为唯一生成的字符串,这确保了当新的生产构建部署到服务器时,这些文件的高速缓存本地副本永远不会被加载。默认情况下,文件名中使用的字符数为7。你可以通过改变build文件夹中config文件夹内的project.properties中的以下行来将其设置为更小或更大的数字:

#hash.length = 7

取消注释上一行,然后将7改为你喜欢的字符数,使用以下语法:

hash.length = <number of characters you prefer>

使用 Drupal 或 WordPress

为了确保这些 Ant 构建脚本能如预期般为 Drupal 工作,需要做出一些小修改。请注意,对 HTML 页面进行压缩的帮助不大,因为 Drupal 或 WordPress 会生成大部分的标记。

更新 build.xml

你需要对 build.xml 文件进行一次小修改,以使其能与 Drupal 或 WordPress 的文件结构协同工作。

在文件中寻找 <echo message="Minifying any unconcatenatedcss files..."/>。就在那行代码之后,更改以下内容:

<filesetdir="${dir.source}/${dir.css}/" excludes="${concat-files}" includes="**/*.css"/>

以下内容需要更新:

<filesetdir="${dir.source}/${dir.css}/" excludes="${concat-files}, ${dir.build.tools}/**/*.css, ${dir.intermediate}/**/*.css, ${dir.publish}/**/*.css" includes="**/*.css"/>

设置项目配置属性

build 文件夹中的 config 文件夹里的 project.properties 文件中,加入以下代码:

dir.css = .
dir.images = images
file.root.stylesheet = style.css

设置 JS 文件分隔符

WordPress 或 Drupal 主题需要你将你的标记分割到不同的文件中(例如,对于 WordPress 就是 footer.php,对于 Drupal 就是 footer.tpl.php)。你需要知道以下代码位于以下哪个文件中:

<!-- scripts concatenated and minified via build script -->
<scriptsrc="img/plugins.js"></script>
<scriptsrc="img/main.js"></script>
<!-- end scripts -->

使用文件名(例如,footer.php)在 project.properties 文件中设置 file.root.page 属性,使用以下代码:

file.root.page = <name of file>

本章的代码中提供了一个经过修改的构建脚本的示例 Drupal 和 WordPress 主题。

使用 Node 构建脚本

Node 构建脚本与 Ant 构建脚本的不同之处在于:

  • 它具有普遍的安装性,不需要从一个项目复制到另一个项目。

  • 所有项目都应该使用 Node 构建脚本进行初始化。在一个已经开始的项目中添加它要麻烦得多。

Node 构建脚本需要 Node 环境,所以通过输入以下命令验证你是否已经安装了 Node:

node -v

如果你还没有安装 Node,可以从 nodejs.org/ 安装(或者通过 github.com/joyent/node/wiki/Installing-Node.js-via-package-manager 使用包管理器安装)。

使用 Grunt

Grunt (gruntjs.com/) 是一个基于 Node 的命令行构建工具,这个 Node 构建脚本就是基于它开发的。Node 构建脚本提供了可插入到 Grunt 中的 HTML5 Boilerplate 优化的任务。

这需要你在项目文件夹内使用一个 package.json 文件和一个 grunt.js 文件,这可以在你初始化项目时设置。

安装 Node 构建脚本

在你的命令行工具中,首先通过输入以下命令来安装 Node 构建脚本包:

npm install https://github.com/h5bp/node-build-script/tarball/master -g

Node 构建脚本也可以作为更大构建设置的一部分使用。如果你倾向于以不同的方式使用它,请在这里查看所有可能的使用方式:github.com/h5bp/node-build-script/wiki/install

安装后,你可以通过初始化来创建你的 HTML5 Boilerplate 项目文件夹。

初始化你的项目

你可以选择不同的选项来为你自己设置项目文件夹。让我们用这个来设置一个临时的项目,学习如何使用这个脚本启动你的 HTML5 Boilerplate 项目。

创建一个文件夹,你的 HTML5 Boilerplate 项目应该放在这里。使用命令行工具导航到该文件夹,并输入以下命令:

h5bpinit

这将开始为你设置一整套命令行交互,供你选择。它主要用于设置将由 Grunt 使用的包管理信息。

一旦你这样做,你有三个选项可以选择开始设置你想要的文件;这些选项如下:

  • [D]efault:HTML5 Boilerplate 的标准文件集合。

  • [C]ustom:获取所有标准文件,可以选择重命名js/css/img/文件夹。如果你的文件将被用作其他系统(如 Drupal 或 WordPress)的模板,你可能希望这样做。

  • [S]illy:提示重命名 HTML5 Boilerplate 中的每个文件夹/文件。除非你是语义完美主义者,否则你不太可能使用这个选项。

在你选择想要进行的安装类型之后,还会问更多问题。注意,如果你按Enter,括号内显示的默认值将被设置。

这将然后从 Github 仓库下载 HTML5 Boilerplate 的最新版本,作为你的起点。

使用 Node 构建脚本与现有项目一起工作

不可能不可能使用脚本与现有项目一起工作,只是有点繁琐。项目正在进行中,以实现在github.com/h5bp/node-build-script/issues/55中使用此脚本,但在此之前,以下是我们如何与我们的 Sun and Sand 网站一起使用它的方法:

  1. 首先,创建一个临时文件夹,然后从命令行执行 Node 构建脚本,按照早前的部分描述初始化一个空项目。

  2. 然后,只将package.jsongrunt.js复制到你的项目文件夹中。

你可以在nimbu.in/h5bp-book/chapter-7-node-init/文件夹中查看实际的代码来看到这个操作。

使用 Node 构建脚本构建你的项目

在命令行工具中导航到你在上一节初始化的 Sun and Sand 项目文件夹,并输入以下命令:

h5bpbuild:default

这将合并文件,结果与 Ant 构建脚本一样,发布在publish文件夹中。你也可以像使用 Ant 构建脚本一样使用这些其他的构建选项。

文本

如果你想在构建项目时省略图像压缩,请使用以下命令:

h5bpbuild:text

最小化

如果你还想最小化 HTML 文件,请使用以下命令:

h5bpbuild:minify

结果与 Ant 构建脚本找到的结果类似;下面的屏幕截图显示了压缩过程的结果:

最小化

有一些额外的选项是 Ant 构建脚本所没有的。

服务器

这将打开一个本地服务器实例,你可以立即预览你的网站。当想测试使用协议相关 URL 链接到文件的页面时,这个功能很有用。要实现这一点,只需在你的命令行工具中进入你的项目文件夹,并输入以下命令:

h5bp server

你会看到为publish文件夹和intermediate文件夹都启动了服务器,如下面的屏幕截图所示:

服务器

然后,打开http://localhost:3001来查看发布的网站。

连接

使用这个命令,你可以看到在你做出项目中的任何资产更改后,它会在打开的浏览器中自动刷新页面。这节省了你手动刷新页面以查看更改的麻烦。要实现这一点,只需在你的命令行工具中进入你的项目文件夹,并输入以下命令:

h5bp connect

与 Drupal 或 WordPress 一起使用

使用 Node 构建脚本初始化一个 HTML5 Boilerplate 项目,然后将其转换为为 Drupal 或 WordPress 构建的模板是相当简单的。首先,确保在执行h5bp init时选择Custom选项。然后,在设置文件夹时,将inc设为样式表所在的文件夹,将images设为包含模板图片的文件夹的名称。当你再次被提示时,输入相同的值,项目框架将会为你生成。确保你用你的模板文件替换index.html

一旦完成上述步骤,打开你项目文件夹中的grunt.js文件,并确认通过以下代码,样式表的文件夹被设置为父文件夹:

css: {
      'style.css': ['*.css']
    },

确保只有 JavaScript 文件和样式表在文件名前加上 SHA 文件名,通过编辑或删除被重命名的图片来实现。这可以通过以下代码完成:

rev: {
js: 'js/**/*.js',
css: '*.css',
},

脚本还需要知道images文件夹的新位置。我们可以通过设置图像的源和目标文件夹来实现,如下面的代码片段所示:

img: {
dist: {
src: 'images',
dest: 'images'
      }
    },

下一步

一旦我们对publish文件夹中的生产文件感到满意,然后我们可以将其移动到我们的托管提供商那里,以替换使我们的网站运行的文件。

理想情况下,你会使用版本控制系统来做这件事,这样在极不可能的情况下更新使得某些页面无法访问时,你可以快速回滚更新。

如果你只是为 Drupal 或 WordPress 创建一个模板,那么将此移动到服务器上的 WordPress 文件夹中,该服务器位于版本控制系统之下可能会有所帮助。

或者,你可以压缩你的项目,然后将文件复制到服务器上,在那里它们可以被解压缩并使用。Node 构建脚本提供了一个这样做选项。在你的命令行工具中进入你的项目文件夹,并输入以下命令:

h5bptar –-input publish –-output <project-name>.tgz

使用能最好地描述你项目的名称,而不是<project-name>。然后,将<project-name>.tgz文件复制到你的服务器上,并将其解压到你希望文件所在的文件夹。

总结

在本章,我们学习了如何使用 HTML5 Boilerplate 团队提供的两种构建脚本。我们还查看了如何将它们都与 Drupal 或 WordPress 模板一起使用。我们还探讨了文件构建完成后我们可以做什么。

在下一章,我们将探讨一些高级任务,你现在知道如何使用 HTML5 Boilerplate 创建和部署项目后,可以尝试这些任务。

附录 A.你现在是一名专家,接下来做什么?

我们已经准备好我们的网站了。我们学会了如何编写它的代码,使用构建脚本来构建它,以及将其部署到生产环境中,这样它就能顺利上线。你已经有效地掌握了 HTML5 Boilerplate 的学习。如果你对成为一个更好的网页开发者感兴趣,你可以花时间去了解网络相关的其他有用部分!让我们一起探索其中的一些。

为你的代码编写单元测试

我们为我们的网站编写了一些 JavaScript 代码。虽然浏览器会告诉我们代码是否编写错误,但没有办法告诉我们代码是否如预期工作。也许有些边缘情况我们没有考虑到。代码应该尽可能健壮,并处理所有预期的用例和大多数错误条件。你可以通过编写测试来测试你的代码调用的每个函数,从而确保这是可能的。

单元测试可以被认为是你的代码中最小的可测试部分。当你编写单元测试时,你确保代码的每个部分都正确运行。开始编写单元测试的最简单方法是使用测试套件。

QUnit.js是一个流行的基于浏览器的测试套件,用于在浏览器中测试你的代码。让我们在我们的为阳光与沙滩音乐节网站编写的代码中使用它。

创建测试环境

让我们在我们的项目中创建一个tests文件夹。

然后,我们从code.jquery.com/qunit/qunit-1.9.0.js下载QUnit.js,并从code.jquery.com/qunit/qunit-1.9.0.css下载相关的 CSS 文件qunit.css。这些文件的最新版本可以在github.com/jquery/qunit找到。

我们现在通过在tests文件夹中创建一个tests.html页面来创建一个测试环境,并具有以下代码:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Tests for Sun n' Sand Festival Code</title>
<link rel="stylesheet" href="qunit-1.9.0.css">
</head>
<body>
<div id="qunit"></div>
<div id="qunit-fixture"></div>
<script src="img/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="img/jquery-1.7.2.min.js"><\/script>')</script>
<script src="img/qunit-1.9.0.js"></script>
<script src="img/main.js"></script>
<script src="img/test.js"></script>
</body>
</html>

在这段代码中,我们包括了我们的main.js文件,这个文件是我们网站所使用的。我们将测试我们为显示阵容而编写的标签代码。

现在,我们将创建一个test.js文件,我们将在其中编写我们代码的所有测试。

由于我们的测试依赖于用于标签的标记,让我们从index.html中复制不含内容的标记到tests.html

如果我们按原样执行这个测试,我们会得到一个全局失败的错误。如果你打开浏览器开发者工具的控制台,你应该会看到以下的错误:

Uncaught TypeError: Object [object Object] has no method 'smoothScroll'

这是因为我们从main.js中调用插件,但我们在这里没有包含这些插件,因为我们不是在测试它们。我们可以在 QUnit 没有被使用的情况下,只测试插件和框架的存在,如以下代码片段所示:

if(window.QUnit == undefined) {
  $('.js-scrollitem').smoothScroll();
  if(Modernizr.svg === false) {
    $('img[src$=".svg"]').each(function() {
      this.src = /(.*)\.svg$/.exec(this.src)[1] + '.png';
    });
  }

  if (Modernizr.generatedcontent === false && window.onbeforeprint !== undefined) {
    window.onbeforeprint = printLinkURLs;
    window.onafterprint = hideLinkURLs;
  }

  Modernizr.load({
    test: Modernizr.audio,
    nope: {
      'mediaelementjs': 'js/vendor/mediaelement/mediaelement-and-player.min.js'
},
    callback: {
    'mediaelementjs': function() {
      $('audio').mediaelementplayer();
    }
  } 
 });
}

确保你移除生产代码中的条件—if(window.QUnit == undefined)

现在,让我们写一个测试,以确认当一个导航标签被点击时,正确的类被应用于它,使用以下的代码片段:

$('.js-tabitem').each(function() {
  var $this = $(this);
  $this.trigger('click');
  test( "navigation tabs", function() {
    ok($this.hasClass('t-tab__navitem--active'), 
   'The clicked navigation item has the correct active class applied');
  });
});

test()函数是 QUnit 测试套件中可用的函数。第一个参数是文本的标题,第二个参数是你想要执行的实际测试函数。

我们还使用ok(),这是 QUnit 测试套件中的一个断言。断言是单元测试的基本元素,在这里你测试你的代码执行结果是否返回期望的值。QUnit 有不同种类的断言,具体请参阅api.qunitjs.com/category/assert/

ok()函数中,我们传递给这个函数的第一个参数是一个表达式,该表达式计算结果为真或假。第二个参数是在断言执行时你希望显示的信息。

现在,让我们通过以下代码段来测试非活动导航项是否不包含使导航项显示为活动的类名:

$('.js-tabitem').not(this).each(function() {
  ok(!$(this).hasClass('t-tab__navitem--active'),
    'Inactive item does not have active class');
});

现在让我们执行这些测试!在你的浏览器中打开tests.html页面。你应该会看到类似下面的截图:

创建测试环境

你还可以执行更复杂的测试!详细了解 QUnit 请访问他们的在线食谱本qunitjs.com/cookbook/

你应该知道的神秘默认设置

为了得出 HTML5 Boilerplate 中的默认设置,进行了大量的研究。了解不同浏览器的行为以及我们为何选择这些默认设置是非常有趣的。

元 UTF-8

meta元素代表页面的任何元数据信息。在<head>元素中设置<meta charset="utf-8">将确保在没有关于页面编码的其他信息时,浏览器以 UTF-8 编码解析页面。

需要注意的是,大多数浏览器只在页面的前 512 字节内寻找字符编码元数据。因此,如果你在<head>元素中有大量的数据,你需要确保这个元元素出现在其他一切之前。

在没有charset编码信息的情况下,浏览器必须猜测应应用哪种charset编码。HTML5 规范概述了所有浏览器必须实现的嗅探算法,具体请参阅www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html#encoding-sniffing-algorithm。不幸的是,旧版浏览器有自己猜测字符编码的机制。

在 Internet Explorer 7 及以下版本的情况下,默认的字符编码偏好通常设置为Auto Select。这意味着浏览器扫描页面的内容以检测最适合的字符编码。在 Internet Explorer 中,如果在页面的前 4096 个字符内找到一个 UTF-7 字符串,它将假设页面使用 UTF-7 编码,你的页面将变得容易受到使用 UTF-7 编码的跨站脚本攻击。因此,在index.html页面顶部使用meta元素声明。

请注意,如果你的服务器发送了一个编码不同的 HTTP 头,那么这将优先考虑。确保你的服务器设置为在 HTTP 头中提供正确的charset编码。

HTML Doctype

在 HTML 和 CSS 标准化之前,大多数标记和样式在任何一个浏览器中都无法一致地渲染。但是当我们有了关于标记应该如何编写的标准,越来越多的开发者开始采用这些标准时,浏览器不得不面对的问题是在互联网上的哪些页面符合这些标准,哪些页面不符合。

文档类型(Doctype)的发明是为了让开发者能够通知浏览器使用较新的标准模式来渲染页面。没有 Doctype 声明,浏览器将使用所谓的怪异模式(浏览器以前在标准成为可接受做法之前渲染页面的方式)来渲染页面。在 IE6 中,在 Doctype 上方有一个注释或 XML 命名空间声明会导致页面也以怪异模式渲染。在 2000 年代初建议使用带有 XML 命名空间声明的 XHTML Doctype 时,这将在 Internet Explorer 中引起重大问题。

并非所有的 Doctype 声明都在标准模式下渲染。使用标准模式的最简单方法是使用最小的推荐 Doctype,<!doctype html>。在 Doctype 声明中可以使用任何大写或小写的混合(例如,<!DoCtYpE hTmL>)。

清除解决方案的详细信息

clearfixCSS 类用于确保浮动元素适合其父容器。这个想法的第一次探索发生在 2002 年,并在www.positioniseverything.net/easyclearing.html的文章中进一步阐述。

clearfix选择器按照以下方式工作:

.clearfix:after {
  content: ".";
  display: block;
  height: 0;
  clear: both;
  visibility: hidden;
}
.clearfix { zoom: 1; } /* IE 5.5/6/7 */

这种方法最大的问题是,边距在所有浏览器上的一致性坍缩。Theirry Koblentz 在www.tjkdesign.com/lab/clearfix/new-clearfix.html上写了更多关于它。

蒂埃里·科布伦茨在 2010 年更新了这种方法,引入了:before:after伪元素的使用,在www.yuiblog.com/blog/2010/09/27/clearfix-reloaded-overflowhidden-demystified/的一篇文章中进行了更新。这两个伪元素如下所示:

.clearfix:before,
.clearfix:after {
  content: ".";
  display: block;
  height: 0;
  overflow: hidden;
}
.clearfix:after {clear: both;}
.clearfix {zoom: 1;} /* IE < 8 */

使用两个伪元素防止了在使用clearfix类时不一致的边距合并问题。

2011 年,尼古拉斯·加利亚尔发现了一种替代方法,如果我们的目标浏览器是 IE6 及以上版本和其他现代浏览器,将大大减少clearfix类的代码行数,他在nicolasgallagher.com/micro-clearfix-hack/的文章中解释了这一点。尼古拉斯的代码如下所示:

.cf:before,
.cf:after {
    content: " ";
    display: table;
}

.cf:after {
    clear: both;
}

/**
 * For IE 6/7 only
 * Include this rule to trigger hasLayout and contain floats.
 */
.cf {
    *zoom: 1;
}

在这种方法中,使用display: table会在伪元素内创建一个匿名表格单元(有关这意味着什么的更多信息可以在规范www.w3.org/TR/CSS2/tables.html#anonymous-boxes中找到),这防止了顶端边距的合并。content属性不需要任何内容在其中工作,但这种方法使用一个空格字符来克服当在可编辑元素上使用时的 Opera 错误。

这就是clearfix类的发展过程!正如你所看到的,为了制作可能跨越主要浏览器平台的最佳clearfix类,进行了大量的研究和开发。

打印样式做什么?

HTML5 Boilerplate 样式表带有一组在用户打印您的页面时非常有用的默认样式。设计一个页面在打印时的外观是我们在设计网页时大多数不会考虑的事情,而 HTML5 Boilerplate 为您提供了一组良好的默认值,因此您大多数时候不需要考虑(然而,这样做是一个好的实践)。

打印媒体查询

我们将所有的打印样式内嵌在一个名为“print”的 CSS 媒体查询中。当用户选择打印页面时,这个媒体查询会被匹配,在这种情况下应用这些样式规则。我们在下面的代码片段中展示了所有的规则都声明在@media print查询内:

@media print {
  a, a:visited { text-decoration: underline; }
  /* More Styles below */
}

优化颜色和背景

然后我们确保优化页面,使其在打印时最易读,并确保我们不会浪费太多的打印墨水打印不必要的图片、颜色和文字。这意味着我们确保移除所有背景图片或图片,这些图片对于所有元素来说只是稍微不同的白色或透明色。我们还确保所有的颜色都是黑色,因为这意味着打印机不需要混合任何墨水,因此可以更快地打印。我们还移除了阴影,因为这会使文字更难读。

我们针对这些更新的最后一条规则如下:

* {
        background: transparent !important;
        color: #000 !important; /* Black prints faster: h5bp.com/s */
        box-shadow:none !important;
        text-shadow: none !important;
    }

更好的链接

现在很少有设计师使用 text-decoration: underline 来为页面上的链接设置样式。通常,人们使用颜色来指示某物是链接。然而,在打印时,下划线更容易辨认,尤其是当你无法控制打印机和渲染它们的颜色时。因此,我们让所有链接(活动或已访问)通过以下代码片段使用下划线样式:

    a,
    a:visited {
        text-decoration: underline;
    }

在打印时提供实际链接的参考也会很有帮助,因为用户如果从打印的页面阅读并希望访问链接,没有办法导航到该链接。我们通过在 CSS 中使用 attr() 函数来实现。attr() 返回当前规则将应用于的元素的属性的值。在这种情况下,由于我们将其应用于链接,我们可以使用 attr() 来获取链接的 href 属性的值并打印它们。当它们作为 content 属性的值使用时,使用空格字符将字符串连接在一起。我们还希望确保如果链接有标题,我们也打印出来,因为标题只有在悬停在链接上时才可见。所有这些在 CSS 中表达出来就像以下的代码片段:

    a[href]:after {
        content: " (" attr(href) ")";
    }

    abbr[title]:after {
        content: " (" attr(title) ")";
    }

但是,这意味着即使是链接到同一页面其他位置的链接或用于 JavaScript 操作(带有 javascript: 前缀)的链接也会以同样的方式呈现!所以,我们需要确保我们不对这些链接这样做。

为此,我们使用属性选择器,它允许我们选择具有以特定值开始、结束或包含的属性的元素。通过使用选择器 a[href^="javascript:"]:after,我们确保我们只选择具有 href 属性的链接的 :after 伪元素,该属性的值以 javascript: 字符串开头。

同样,我们也选择所有 href 属性以 # 字符开头的链接,因为这意味着这样的链接是内联链接,链接到同一页面内的另一个位置。

然后我们确保对 these links 中的 pseudo-elements 不渲染任何内容。规则看起来像以下的代码片段:

    .ir a:after,
    a[href^="javascript:"]:after,
    a[href^="#"]:after {
        content: "";
    }

请注意,这些规则不适用于 IE6,如果必须在 IE6 中提供此功能,您可能需要使用提供此功能的 JavaScript。

在同一页面内渲染所有代码和引用

有时,您的打印页面可能包含引用或代码,作为读者,当代码(或引用)本可以在一个页面内无任何中断地包含时,需要不断参考之前的页面是很烦人的。为此,我们可以使用 CSS page-break-inside 属性,它允许您告诉浏览器您更愿意让这些元素在两页之间断开还是保持在同一页面上。下面的代码片段显示了此代码:

pre,
    blockquote {
        border: 1px solid #999;
        page-break-inside: avoid;
    }

请注意,Firefox 不支持 page-break-inside,但在所有其他浏览器中都可以使用。

更好地渲染表格

默认情况下,将标题放在thead标签内将确保当表格跨两页时,标题会重复。然而,目前只有 Firefox 和 Opera 支持这一点。在 IE 中,你可以这样做,但你必须明确指出,如下面的代码片段所示:

    thead {
        display: table-header-group; /* h5bp.com/t */
    }

更好地渲染图像

理想情况下,我们想要防止表格行和图像跨页断裂,因此我们使用现在熟悉的page-break-inside属性来告诉浏览器我们的偏好,如下面的代码片段所示:

    tr,
    img {
        page-break-inside: avoid;
    }

当图像超出页面或打印时被裁剪而在网站上以完整形式显示时,它也不太好看。因此,我们将最大宽度限制为与页面本身一样宽,不超过此宽度,如下面的代码片段所示:

    img {
        max-width: 100% !important;
    }

页面边距

@page规则允许你在打印时修改页面的属性。除了 Firefox 之外,所有浏览器都支持这个规则。这个规则将页边距设置为每页0.5 cm,如下面的代码片段所示:

    @page {
        margin: 0.5cm;
    }

孤儿和寡妇的最优设置

孤儿是指出现在页面底部的文本行。寡妇是指出现在页面顶部的那些。我们确保文本行不要以留下比所需更少的行在底部或顶部的方式断裂。这将创造一个更易读的体验。以下代码片段用于此目的:

    p,
    h2,
    h3 {
        orphans: 3;
        widows: 3;
    }

保持标题与内容在一起

如果标题出现在一页的底部,而其对应的内容却出现在下一页,这将使得内容难以阅读。为了告诉浏览器避免这样做,我们可以使用page-break-after设置,如下面的代码片段所示:

    h2,
    h3 {
        page-break-after: avoid;
    }
}

协议相关 URL 是什么?

在 HTML5 Boilerplate 中,当我们提到 jQuery 时,我们是这样提到的:

<script src="img/jquery.min.js">
</script>

请注意,我们没有在 URL 前面加上httphttps;相反,它以//开头。这些被称为协议相关 URL,当你想在 HTTP 或 HTTPS 环境中使用一个协议无关的资源时,它们很有用。

当你使用 HTTPS 提供页面时,浏览器在页面加载使用 HTTP 协议的资产和资源时会抛出警告和错误。为了防止这种情况,你需要确保你使用 HTTPS 协议来请求所有资产。如果你使用相对 URL 来引用页面所在的父文件夹中的资产,这通常不是问题。然而,如果你在引用像 jQuery 的 CDN URL(前面提到)这样的外部 URL,那么你需要确保在页面使用 HTTPS 协议时使用https,而在页面使用 HTTP 协议时使用http前缀。

而不是用 JavaScript 来做这个决定,简单地省略协议可以确保浏览器在请求那个外部 URL 时使用当前的协议。在这种情况下,如果这个页面以 HTTPS 的形式提供,即https://example.com,那么请求的 URL 将是ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js

您可以在paulirish.com/2010/the-protocol-relative-url/了解更多关于这个内容。

使用条件注释

历史上,IE6、IE7 和 IE8 是拥有最多 bug 和样式渲染不一致的浏览器。有多种方法可以向 IE8 及以下版本提供样式,以下是其中几种。

浏览器样式 hack

最常用的技术是在 CSS 样式规则中使用 hack,这些规则只针对一个浏览器。

对于 IE6 及以下版本,使用以下代码片段:

* html #uno  { color: red }

对于 IE7,使用以下代码片段:

*:first-child+html #dos { color: red }

对于 IE8,使用以下代码片段:

@media \0screen {
   #tres { color: red }
}

还有更多针对两个或更多浏览器(或排除两个或更多浏览器)的 hack,全部列在paulirish.com/2009/browser-specific-css-hacks/这篇文章中。

这些 hack 的问题在于,首先它们利用浏览器解析技术的漏洞。如果浏览器修复了这些解析错误,它们可能就无法工作。幸运的是,我们不必担心 IE6 和 IE7 等旧浏览器。

这些 hack 也不易读,如果没有注释,就无法理解它们针对哪些浏览器。

这些方法的优势在于你可以保持你的样式规则在一起,而且你不需要为需要 hack 的浏览器提供单独的样式表。

服务器端浏览器检测

当它们向服务器发起请求时,浏览器会随请求发送一个 User Agent 字符串。服务器可以根据它们对 User Agent 字符串的解释提供不同的资源。例如,如果一个浏览器用以下的 User Agent 字符串将自己标识为 IE6:

Mozilla/4.0 (compatible; MSIE 6.0; Windows XP)

然后,服务器可以回传一个不同的样式表给 IE6。虽然这看起来是一个简单、容易的解决方案,但问题出现在浏览器撒谎的时候。历史上,浏览器从未准确声称自己是哪个浏览器,因此,很可能会向一个浏览器发送错误的样式表。

这也涉及到一点服务器端的处理开销,以根据浏览器的 User Agent 设置处理请求,因此这不是向 IE8 及以下版本提供不同样式表的理想方式。

基于条件注释的样式表

条件注释是 IE9 及以下版本能理解的具有特殊语法的 HTML 注释。以下是一个条件注释的示例:

<!--[if lt IE 9]>
<p>HTML Markup here</p>
<!--<![endif]-->

所有浏览器(除了 IE9 及以下版本)都会忽略这些条件注释内的内容。IE9 及以下版本会尝试解释这些注释内的if条件,并根据 IE 浏览器的版本号是否与if条件中的版本号匹配来选择性地渲染内容。

之前的示例将在所有 8、7、6 及以下版本的 IE 上渲染p标签。

条件注释完美地针对老版本的 IE,HTML5 Boilerplate 就是这么做的。使用它们有两种方法。第一种是基于匹配条件注释输出一个单独的样式表,如下面的代码片段所示:

<!--[if lt IE 9]>
<link rel="stylesheet" href="/css/legacy.css">
<![endif]-->

这将使 IE8 及以下使用legacy.css,其他浏览器将忽略这段代码。

独立样式表的问题在于,在开发样式时,您需要针对两个不同的样式表,偶尔 IE 特定的样式表可能会被遗忘。

有些人只为 IE8 及以下提供一个非常基础的体验,如下面的代码片段所示:

<!--[if ! lte IE 6]><!-->
/* Stylesheets for browsers other than Internet Explorer 6 */
<!--<![endif]-->
<!--[if lte IE 6]>
<link rel="stylesheet" href="http://universal-ie6-css.googlecode.com/files/ie6.1.1.css" media="screen, projection">
<![endif]-->

但 HTML5 Boilerplate 更喜欢一个更可读且针对性的方法,使用类名向所有浏览器提供最佳可能的样式,我们接下来会看到。

基于条件注释的类名

前一个条件注释方法的迭代将是基于条件注释在根元素上附加类名,如下面的代码片段所示:

<!--[if IE 8]>
<html class="no-js lt-ie9">
<![endif]-->

然后,在您的样式表中,您可以使用它在 IE8 及以下设置样式,如下所示:

.lt-ie9 h1 { color: red }

您可以在paulirish.com/2008/conditional-stylesheets-vs-css-hacks-answer-neither/上阅读更多关于这个解决方案的信息。

这个解决方案不需要单独的样式表,但允许你编写可读的类名,表明样式表中为何存在该样式规则。这是我们在 HTML5 Boilerplate 中采用的解决方案,并推荐使用。

什么是元标签 x-ua-compatible?

x-ua-compatible是一个头部标签,用于定义 Internet Explorer 如何渲染您的页面。它声明了 Internet Explorer 应使用哪种模式来渲染您的页面。这主要针对那些在 Internet Explorer 9 及以后版本中因对标准支持更好而断裂的老网站。它可以以两种方式设置。

HTML 页面中的元标签

在这种情况下,我们只需在 HTML 页面的<head></head>标签之间添加一个meta标签,如下所示:

<head>
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" >
</head>

HTTP 头响应自服务器

在 Apache 中,在.htaccess文件中编写以下内容,会使服务器对那个父文件夹的任何请求发送X-UA-Compatible HTTP 头作为响应:

LoadModule headers_module modules/mod_headers.so
Header set X-UA-Compatible "IE=EmulateIE7"

我们推荐这种设置其值的方法,因为 HTTP 头值会覆盖通过meta标签设置的任何值。此外,在html元素上使用 IE 条件注释的meta标签会导致忽略这个meta标签。X-UA-Compatible头可以有以下值。

Edge

这将使用可用的最新渲染模式。例如,在 Internet Explorer 10 中,它将是 IE10。我们总是希望使用最新的渲染模式,因为这意味着我们能够访问最新的、最符合标准的浏览器版本。这就是为什么它是 HTML5 Boilerplate 中的默认选项。

IE9

这将只使用 IE9 模式来渲染页面。例如,当您使用这种模式时,如果这个页面在 Internet Explorer 10 中被查看,它将使用 IE9 模式来渲染页面。

IE8

这将渲染页面,好像它是在 Internet Explorer 8 上查看的一样。

IE7

这种模式会以 Internet Explorer 7 以标准模式渲染内容的方式渲染页面。

模拟 IE9

这种模式告诉 Internet Explorer 使用<!DOCTYPE>指令来确定如何渲染内容。标准模式下的指令在 IE9 模式下显示,怪异模式下的指令在 IE5 模式下显示。所有模拟模式与之前的模式不同,都尊重<!DOCTYPE>指令。

模拟 IE8

这种模式告诉 Internet Explorer 使用<!DOCTYPE>指令来确定如何渲染内容。标准模式下的指令在 IE8 模式下显示,怪异模式下的指令在 IE5 模式下显示。与 IE8 模式不同,模拟 IE8 模式尊重<!DOCTYPE>指令。

模拟 IE7

这种模式告诉 Internet Explorer 使用<!DOCTYPE>指令来确定如何渲染内容。标准模式下的指令在 Internet Explorer 7 的标准模式下显示,而在 IE5 模式下显示怪异模式下的指令。与 IE7 模式不同,模拟 IE7 模式尊重<!DOCTYPE>指令。对于许多网站来说,这是首选的兼容性模式。

IE5

这种模式会以 Internet Explorer 7 在怪异模式下显示内容的方式渲染内容。您可以在 MSDN 文档msdn.microsoft.com/en-us/library/cc288325(v=VS.85).aspx上了解这些模式。

贡献

如果你喜欢这个项目到目前为止所看到的内容,你可能想要贡献!为 HTML5 Boilerplate 做出贡献在你的学习和理解中即使做出最小的更改也是有益的。贡献有两种方式,如下所述:

  • 报告问题

  • 提交拉取请求

报告问题

如果您在 HTML5 Boilerplate 的文件中发现了一个错误或者是不正确的内容,那么您可以提交一个问题,任何贡献者都可以查看并看看是否可以解决。

诀窍是找出是否是 HTML5 Boilerplate 的问题,或者是项目代码引起的。您可以通过开始安装 HTML5 Boilerplate 的干净版本并验证错误是否仍然发生来验证这是否是 HTML5 Boilerplate 的问题。

如果遇到 HTML5 Boilerplate 的问题,在提交问题时,请确保它没有被报告过。GitHub 问题页面github.com/h5bp/html5-boilerplate/issues列出了所有开放的问题。在顶部的搜索栏中搜索您遇到的问题。很可能它已经被修复,但修复还没有推送到稳定分支。

如果问题全新的,那么确保你通过一个减少的测试用例以一种明显的方式隔离问题(Chris Coyier 在css-tricks.com/reduced-test-cases/中撰写了关于减少测试用例的内容)。当你提交一个 bug 报告时,确保它易于理解,这样我们才能找到一个快速的解决方案。理想情况下,你的 bug 报告应该包含以下内容:

  • 一个简短且描述性的标题

  • 问题的概述以及此 bug 发生的浏览器/操作系统

  • 如果可能的话,重现 bug 的步骤

  • 一个减少的测试用例的 URL(你可以在jsfiddle.netcodepen.io上托管一个)

  • 可能引起 bug 的代码行以及其他与 bug 相关的信息

理想情况下,一个 bug 报告应该是自包含的,这样贡献者不需要再次与你联系以了解关于 bug 的更多信息,而可以专注于解决它。

按照这个流程提交一个 bug 报告本身就是了解如何找出你编写的标记、样式或脚本中错误的的学习过程。

拉取请求

如果你有关于如何改进 HTML5 Boilerplate 的想法,或者有修补现有问题的补丁,改进或新功能,你可以提交所谓的pull 请求。Pull 请求是一组你可以提交给 HTML5 Boilerplate GitHub 存储库进行审查的更改,以便可以让核心贡献者审查并如果认为有用的话将其合并到 HTML5 Boilerplate 中。

开始贡献的一个好方法是找到一个你认为可以解决的小问题,分叉 GitHub 项目(在help.github.com/articles/fork-a-repo上了解这意味着什么),在你的更改上工作并提交一个 pull 请求。

如果你的贡献改变了大量代码并极大地改变了项目的性质,首先考虑在 GitHub 项目上打开一个 issues。

以下是要开始创建拉取请求的步骤:

  • 分叉项目。

  • 克隆你的分叉(在终端中,输入git clone https://github.com/<your-username>/html5-boilerplate.git并按Enter)。

  • 在终端中添加一个上游远程(输入git remote add upstream https://github.com/h5bp/html5-boilerplate.git并按Enter)。

  • 从上游获取最新更改(例如,通过在终端中输入git pull upstream master并按Enter)。

  • 创建一个新的主题分支来包含你的功能、更改或修复(git checkout -b <topic-branch-name>)。

  • 确保你的更改遵守项目整个中使用的当前编码约定;也就是说,缩进、准确的注释等。

  • 将你的更改逻辑上分组提交;使用 Git 的交互式重置功能(关于此功能的更多信息请访问 help.github.com/articles/interactive-rebase)来在公开之前整理你的提交。请遵守这些 Git 提交信息指南(访问 tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html),否则你的拉取请求很可能不会被合并到主项目。

  • 将上游分支合并(或重置)到你的主题分支。

  • 将你的主题分支推送到你的分叉(git push origin <topic-branch-name>)。

  • 用清晰的标题和描述打开一个拉取请求。请提到你测试了哪些浏览器。

这可能看起来像是很多工作,但它使你的拉取请求显著更容易理解且更快合并。此外,你的代码成为了你所做工作的文档,任何想要知道为什么某个部分是这样的都可以回溯到你的提交并确切了解原因。

在 HTML5 样板代码上工作将帮助你开始采用协作开发的最佳实践,你可以将这些实践带回你的工作场所或任何其他协作工作中。

posted @ 2024-05-24 11:10  绝不原创的飞龙  阅读(11)  评论(0编辑  收藏  举报