今天准备修改一下blog的样式,结果无意中发现一个问题。一个使用透明效果的CSS,在之前用VS2005做的一个项目里,IE和Firefox下面都工作正常,拿到博客园以后发现用IE7浏览没有效果,而Firefox正常。查了一下相关文章,发现对HTML了解太少了。
1. 问题表现
原来项目页面代码类似如下
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<style type="text/css" media="screen">
.mycss:hover
{
opacity:0.6; /*supported by current Mozilla, Safari, and Opera*/
-moz-opacity: 0.6; /*older Mozilla*/
-khtml-opacity: 0.6; /*older Safari*/
filter: alpha(opacity=60); /*older IE*/
filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100,FinishOpacity=15, Style=3, StartX=0, FinishX=100,
StartY=0,FinishY=16); /*supported by current IE*/
}
</style>
</head>
<body>
<div class="mycss" style="width:100px;height:16px;border:solid 1px red;">
<a href="#">WWWWWWWWWWWWWWWW</a>
</div>
</body>
</html>
在IE 7中,页面显示以及鼠标移动到div上面的效果如下,可以看到CSS有起作用(Firefox访问也正常)

在博客园中写的CSS跟上面完全一样,但因为博客园是用VS2003开发的,所以页面代码类似如下
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<style type="text/css" media="screen">
.mycss:hover
{
opacity:0.6; /*supported by current Mozilla, Safari, and Opera*/
-moz-opacity: 0.6; /*older Mozilla*/
-khtml-opacity: 0.6; /*older Safari*/
filter: alpha(opacity=60); /*older IE*/
filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100,FinishOpacity=15, Style=3, StartX=0, FinishX=100,
StartY=0,FinishY=16); /*supported by current IE*/
}
</style>
</head>
<body>
<div class="mycss" style="width:100px;height:16px;border:solid 1px red;">
<a href="#">WWWWWWWWWWWWWWWW</a>
</div>
</body>
</html>
上面这段代码IE 7访问时CSS透明效果没有作用,而Firefox访问正常。其实差别就在于DOCTYPE声明不一样。VS2005添加一个WebForm,DOCTYPE声明与第一段代码相同;VS2003的DOCTYPE则跟第二段代码一样。其实第二段代码把DOCTYPE改成下面任意一种,在IE 7中CSS的透明效果就会起作用。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Strict//EN">
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
2. DOCTYPE声明
| <!DOCTYPE |
html
|
PUBLIC
|
"-// |
W3C// |
DTD
|
HTML 4.01 Transitional// |
EN" |
"http://www.w3.org/TR/html4/loose.dtd"> |
| |
(1) |
(2) |
(3) |
(4) |
(5) |
(6) |
(7) |
(8) |
| <!DOCTYPE |
[Top Element] |
[Availability] |
"[Registration]// |
[Organization]// |
[Type] |
[Label]// |
[Language]" |
"[URL]"> |
| |
(1) |
(2) |
(3) |
(4) |
(5) |
(6) |
(7) |
(8) |
(1) Top Element: DTD中声明的最顶层元素,例如html。
(2) Availability: 指示标识符是公共标识符号(PUBLIC)还是系统资源(SYSTEM),例如本地文件、url等。
(3) Registration: 指示组织是否注册为ISO成员,+表示已经注册为ISO成员,-表示没有注册。W3C没有注册,所以使用-。
(4) Organization: 对于HTML、XHTML而言指维护DTD的组织标识符,W3C。
(5) Type: Public Text Class,引用对象的类型,对于HTML、XHTML而言为DTD。
(6) Label: Public Text Description,引用内容的唯一名称描述,Label里面可以包含一个版本号(4.01),可以包含一个Defintion(有三种Definition: Frameset, Strict, Transitional,下面会描述)。
(7) Language: 语言代码。
(8) URL: 引用DTD的url。
各个浏览器对HTML、CSS的处理,在细节上存在很多差异,为了向W3C标准靠近,并且HTML、CSS的标准也在不断的发展,因此同一个浏览器的不同版本之间,也会存在细节处理上的不一致性。现在浏览器使用DOCTYPE声明来决定该使用那种模式处理HTML、CSS,通常提到的有standards mode(标准模式,strict Mode)和quirks mode(兼容模式compliant mode)。标准模式指浏览器采用尽量靠近目前W3C规范的方式,支持目前版本的HTML、XHTML、CSS规范;兼容模式指浏览器按照以前的老版本的方式处理,以兼容那些旧版本的web应用。另外需要注意的是,虽然目前主要的浏览器都支持这两种模式,但都有差别,例如Firefox除了上面两种模式外,还有一个almost standards mode。
下面是HTML 4.01的DTD,分别为Strict, Transitional, Frameset
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">
XHTML 1.0的DTD,分别为Strict, Transitional, Frameset
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
3. IE 6 CSS增强、IE 7 CSS兼容性
References:
Cascading Style Sheet Compatibility in Internet Explorer 7、
CSS Enhancements in Internet Explorer 6
Label中的Definition三种类型:Frameset,支持FRAMESET文档;Transitional,支持除了FRAMESET以外其它所有元素;Strict,不支持W3C准备淘汰的元素、属性。这种描述有点让人糊涂,也无法跟标准standards mode、quirks mode对应上,至于具体的定义可以参考W3C标准。
下面这个表格是比较有用的
| Label | Definition | URL present | URL not present |
| No !DOCTYPE present |
|
Off |
Off |
| HTML (No Version Present) |
|
Off |
Off |
| HTML 2.0 |
|
Off |
Off |
| HTML 3.0 |
|
Off |
Off |
| HTML 3.2 |
|
Off |
Off |
| HTML 4.0 |
No Definition Present |
On |
On |
| HTML 4.0 |
Frameset |
On |
Off |
| HTML 4.0 |
Transitional |
On |
Off |
| HTML 4.0 |
Strict |
On |
On |
| XHTML |
|
On |
On |
| XML |
|
On |
On |
| Unrecognized !DOCTYPE |
|
On |
On |
其中On表示使用strict mode(standards mode),Off表示使用compliant mode(quirks mode)。URL present/URL not present表示DTD文档的url是否有在DOCTYPE中声明;Definition为空或者No Definition Present表示Definition没有定义。从IE 6开始支持这两种模式的切换,在strict mode下,IE尽量保持与W3C标准一致,而compliant mode下,IE将保持与以前的IE版本兼容。用这个表格,对照1中几种DOCTYPE可以知道,只有在strict mode下,IE 7才支持filter:progid:DXImageTransform.Microsoft.Alpha这个滤镜。让人奇怪的是,也只有在strict mode下,IE 7才支持filter: alpha(opacity=60),compliant mode下是不支持的,而这个写法是针对IE 5.5之前版本的。
在strict mode下面,两个比较重要的差异点:
a) Box的height、width计算问题

CSS标准中,width、height指图中Content的宽度、高度,而IE在计算宽度、高度时,将包括padding、border。
b) Box Modal问题
例如下面这段代码
<html>
<head></head>
<body>
<style type="text/css">
div{ width : 100px; height: 100px; border: thin solid red;}
blockquote { width: 125px; height: 100px;
margin-top: 50px; margin-left: 50px;
border: thin dashed black}
cite{ display: block;
text-align: right;
border: none}
p{ margin: 0;}
</style>
<div>
<blockquote>
<p>some text long enough to make it interesting.</p>
<cite>- anonymous</cite>
</blockquote>
</div>
</body>
</html>
在compliant mode下(<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">),页面显示为:

在strict mode下(<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Strict//EN">),页面显示为:

就是说complient mode下,box会自动扩展以容纳里面的内容,而W3C CSS标准中,box一旦指定宽度、高度,就不应当再发生变化,所以再strict mode下,div保持了给定的宽度、高度,而里面的内容自然的溢出到了div外面。