打印

RN8002: 各浏览器在 HTML 页面与页面中引入的外部 CSS 文件编码不一致时表现不同

作者:孙东国

标准参考

根据 CSS 2.1 规范的描述,应按照以下优先级来确定一个外部 CSS 文件的编码:

  1. HTTP 响应头中 "Content-Type" 字段的 "charset" 参数指定的编码。
  2. BOM 以及/或者 @charset 定义的编码。
  3. <link charset=""> 或其他链接机制提供的元数据(如果有的话)指定的编码。
  4. 引入该 CSS 文件的 HTML 或另一个 CSS 文件(如果有的话)中已确定的编码。
  5. 如果以上几步都没能确定编码,则假定其编码为 UTF-8。

关于上述内容的详细信息,请参考 CSS 2.1 规范 4.4 CSS style sheet representation 中的内容。

问题描述

如果一个外部 CSS 文件的编码与引入该文件的 HTML 文件的编码不一致,并且没有显式的声明该 CSS 文件的编码,在某些情况下会造成 CSS 的解析错误。

造成的影响

该问题将造成页面布局在一些浏览器中与预期的效果不符。

受影响的浏览器

所有浏览器

问题分析

对于一个未显式声明编码的 CSS 文件,浏览器会将其编码认为与引入该文件的文件的编码一致。在一些特定的情况下,将造成 CSS 代码解析异常。举例如下:

HTML 代码(编码为 UTF-8):

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<link rel="stylesheet" type="text/css"  href="css.css"/>
</head>
<body>
  <h1>内容文本</h1>
</body>
</html>

以上页面引入的 css.css 的代码(编码为 GB2312):

h1 {
  margin:0;
  width:100px;
  height:100px;
  background:blue;
  font:20px/100px "黑体";
  text-decoration:underline;
  color:red;
}

假设上述两个文件均为在 HTTP 响应头中设定编码,在各浏览器中表现如下:

IE6 其他浏览器
snapshot snapshot

可见,IE6 把 CSS 文件从“黑体”二字到规则结束的样式都没有起作用,其他浏览器中仅“黑体”二字解析错误。

产生这种差异的原因是各浏览器对与这种错误的容错方式不同。

按照规范的规定,在这种情况下,浏览器会认为 CSS 文件的编码与页面一致,即 UTF-8,但 GB2312 编码下的一个中文字符是 2 个字节,在 UTF-8 编码下则为 3 个字节,在把 GB2312 编码下的“黑体”二字当作 UTF-8 编码的文字来解析的时候,得到的是“����”,这并不是预期的值。正是这个值导致了样式定义在各浏览器中都无法按照预期被解析。

解决方案

当 HTML 文件或 CSS 文件要引入一个不同编码的 CSS 文件时,要明确声明被引入的 CSS 文件的编码。

如以上的举例,在 CSS 文件的开头加上一行1

@charset "GB2312";

或者在各文件的 HTTP 响应头中声明该文件实际使用的编码。

注:
1. 虽然 CSS 2.1 规范也允许在 LINK 标签上添加 'charset' 属性来指定编码,但 IE6 IE7 IE8(Q) 不支持。

参见

知识库

相关问题

测试环境

操作系统版本: Windows 7 Ultimate build 7600
浏览器版本: IE6
IE7
IE8
Firefox 3.6
Chrome 4.0.302.3 dev
Safari 4.0.4
测试页面: ...
本文更新时间: 2010-08-03

关键字

CSS 编码 外部文件