触发hasLayout引起的BUG

在IE6下面,很多显示的BUG都可以用触发hasLayout的方式去解决。但有种情况正好相反,触发hasLayout之后会产生显示的BUG。请看下面的代码:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<title>Demo</title>
	<style type="text/css">
		#div1 {
			background: red;
			margin: 10px;
			padding: 10px;
		}
		#div2 {
			background: gray;
			margin: 30px;
			padding: 10px;
		}
	</style>
</head>
<body>
	<div id="div1">
		<div id="div2">TEST</div>
	<div>
</body>
</html>

上面的代码在所有浏览器里是正常显示的,包括IE6。但是给#div1设定宽度之后(触发hasLayout),经过大量测试,在IE6下#div1上面的padding会消失。有兴趣的同学可以看这篇文章:IE7-/Win: Margin collapsing and hasLayout

目前解决的办法就是去掉#div1的宽度,然后在#div1外面套一层div,在这个新div上设定宽度。解决问题的代码:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<title>Demo</title>
	<style type="text/css">
		#con {
			width: 400px;
		}
		#div1 {
			background: red;
			margin: 10px;
			padding: 10px;
		}
		#div2 {
			background: gray;
			margin: 30px;
			padding: 10px;
		}
	</style>
</head>
<body>
	<div id="con">
		<div id="div1">
			<div id="div2">TEST</div>
		<div>
	</div>
</body>
</html>

IE6是支持!important的

由于本人最近沉迷于iPhone不能自拔,所以很久没有更新博客了。转入正题:

网上很多讲CSS HACK的教程都有这样的内容,如果想写一个让FF、IE7、IE8可以识别,并且IE6不能识别的CSS HACK,就用!important。造成的结果就是很多人以为!important在IE6下根本不支持,本人当时就是受害者之一。!important在CSS1中就有描述,链接如下:http://www.w3.org/TR/CSS1/#important。为什么会造成IE6不支持的假象呢,原因是IE6有BUG。在IE6中,下面的这段代码显示是不正确的。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Demo</title>
    <style type="text/css">
		div {
			width: 100px;
			height: 100px;
			background: red !important;
			background: yellow;
		}
	</style>
</head>
<body>
	<div></div>
</body>
</html>

在标准浏览器下,这个DIV应该是红色的,但在IE6下是黄色的。这个只能说是IE6的BUG,而不能说IE6完全不支持!important。如果把上面的代码改为:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Demo</title>
    <style type="text/css">
		div {
			width: 100px;
			height: 100px;
			background: red !important;
		}
		div {
			background: yellow;
		}
	</style>
</head>
<body>
	<div></div>
</body>
</html>

怎么样,可以正常显示了吧。同理,下面的代码在IE6下也可以正确显示的。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Demo</title>
    <style type="text/css">
		div {
			width: 100px;
			height: 100px;
			background: red !important;
		}
		#div1 {
			background: yellow;
		}
	</style>
</head>
<body>
	<div id="div1"></div>
</body>
</html>

结论:作为CSS优先级别的老大,!important是全浏览器兼容的。

消失的列表背景

IE6中设定了position: relative; float: left的容器下,如果存在着多个带有背景的列表,那么这些列表中有一部分会显示不正常,具体的表现为背景消失。例如下面的代码(请在IE6中查看):

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>TEST</title>
</head>
<style type="text/css">
	#container {
		position: relative;
		float: left;
	}
	#container li {
		background: red;
	}
</style>
<body>
	<div id="container">
		<ul>
			<li>Hello Kitty</li>
			<li>Hello Kitty</li>
			<li>Hello Kitty</li>
			<li>Hello Kitty</li>
			<li>Hello Kitty</li>
		</ul>
		<ul>
			<li>Hello Kitty</li>
			<li>Hello Kitty</li>
			<li>Hello Kitty</li>
			<li>Hello Kitty</li>
			<li>Hello Kitty</li>
		</ul>
		<ul>
			<li>Hello Kitty</li>
			<li>Hello Kitty</li>
			<li>Hello Kitty</li>
			<li>Hello Kitty</li>
			<li>Hello Kitty</li>
		</ul>
	</div>
</body>
</html>

解决的方法是给li也加上position: relative。这个BUG的具体描述,请参考:http://www.positioniseverything.net/explorer/ie-listbug.html

IE6,IE7中负缩进的问题

在IE6,IE7下面给display: inline-block的元素设置text-indent: -9999px会把这个元素以及后面的元素拉走。请在IE6和IE7下,查看演示

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<title>TEST</title>
	<style type="text/css">
		.bar {
			border: 1px solid;
			display: inline-block;
			height: 18px;
		}
		.bar .icon {
			display: inline-block;
			width: 16px;
			height: 16px;
			background: red;
			text-indent: -9999px;
		}
	</style>
	<!--[if lte IE 7]>
	<style type="text/css">
		.bar {
			display: inline;
		}
	</style>
	<![endif]-->
</head>
<body>
	<input type="text" />
	<div class="bar">
		<span class="icon"></span>
		<span>HELLO KITTY HELLO KITTY HELLO KITTY</span>
	</div>
</body>
</html>

在IE6,IE7下可以看到.bar里面的内容都没有了。最开始的想法是让.icon浮动来解决这个问题,可是用css hack给.icon加上float: left居然不起作用,.icon后面的文字仍然被拉走。这时候只好在blueidea求助,结果那里的版主(yoom)想法和我的一样,让.icon浮动,但是他比我多加了个display: block,最终这个BUG被修正了。正常情况下,span元素加上float之后就已经是block级别了,但就是这个display: block起了决定性的作用,按yoom的话说,真是无心插柳啊。

最终的CSS HACK为:

<!--[if lte IE 7]>
<style type="text/css">
	.bar {
		display: inline;
	}
	.bar .icon {
		display: block;
		float: left;
	}
</style>
<![endif]-->

IE6浮动引起的一些BUG

LI浮动之后换行

在一个没有设定宽度的浮动元素#floated里,有一个触发了hasLayout的子元素#content,并且#content没有设定宽度。那么#content和#floated会以100%的宽度呈现,占满这一行。例子:


(IE6的截图)

li {
	float: left;
	display: block;
}
li a {
	display: block;
	height: 30px;
	margin-right: 10px;
}
<ul>
	<li><a href="#">HELLO WORLD</a></li>
	<li><a href="#">HELLO WORLD</a></li>
	<li><a href="#">HELLO WORLD</a></li>
	<li><a href="#">HELLO WORLD</a></li>
	<li><a href="#">HELLO WORLD</a></li>
	<li><a href="#">HELLO WORLD</a></li>
</ul>

在上面的例子中,a元素触发了hasLayout,但是没有设定宽度,在IE6里会产生换行。
解决办法有下面几种:

  • 给a或者li明确的宽度。
  • 让a元素也浮动。(可能会带来新的BUG
  • 去掉height,也就是不触发hasLayout。(可能会带来新的BUG
LI中的浮动元素以阶梯的方式呈现

继续用上面的HTML做为例子,CSS变为:

ul {
	list-style: none;
}
li a {
	float: left;
	height: 30px;
	margin-right: 10px;
}

(IE6的截图)

在标准浏览器下,如果有足够的宽度,例子中所有的a元素会构成一行。但是在IE6下面,a元素是以阶梯的方式呈现。解决的办法有下面几种:

  • 给li加上display: inline;。
  • 让li也浮动。
浮动元素文本换行

上图中的li没有设置宽度,当容器的宽度不够时,正常情况下应该是li下沉,另起一行。但是在IE6下面却是li里面的文本换行,导致混乱的布局。下面是产生BUG的CSS:

ul {
	list-style: none;
}
li {
	float: left;
}
li a {
	margin-right: 10px;
}

(IE6的截图)

解决的办法有下面几种:

  • 加上white-space: nowrap;
  • 给浮动元素(上面的例子为li)一个确切的宽度值。
  • 在IE6下用hack,让li以inline-block的方式呈现。(如果display: inline-block不起作用,点击这里

(待续……)

断头台(Guillotine)

Guillotine是一个在IE6下的BUG。表现的形式为:当鼠标放在一些链接上,浮动元素的下部会被裁剪掉。请用IE6查看演示

如何触发

如果让Guillotine“正常工作”,要满足下面几点:

  1. 有一个block级的包含元素(#container),不要触发layout
  2. 在#container里有一个浮动的元素(#floated)。
  3. 在#float的后面有一些a标签,并且在a:hover里面要改变background。

其中第三点改变background很重要,经过测试如果不改变background,则在上面的条件下不会触发这个BUG。

如何修复

修复这个BUG有下面几个方法:

  1. 让#container触发layout。
  2. 在a:hover里面不要改变background。
  3. 在#container的后面添加一个清除浮动的元素。如:
    <div id="container">
    	<div id="floated">
    	...
    	</div>
    	<a href="#">断头台</a><br />
    	...
    </div>
    <div style="clear: both"></div>
    
  4. 在#floated的后面加上清除浮动的元素。(不推荐,会带来新BUG。)

Chrome中fieldset元素默认padding值的问题

在Chrome v4.1.249.1030中,fieldset的padding值默认为padding: 0.35em 0.75em 0.625em,导致fieldset的宽度总是比别的浏览器少4个左右的象素。而在firefox中默认值是padding:0.35em 0.625em 0.75em。虽然说这个问题用reset.css可以解决,但是数字这么相似,不知道是不是Chrome开发人员的疏忽呢?

用CSS3做个好看的按钮(2)

转载须写明出处,附带本文链接。关于文中的示例,请用Firefox 3.6、Chrome 4.x、Safari 4.x查看。

点击查看演示

上一篇文章中提到了用CSS3的gradient做按钮,后来朋友指出HTML用的标签太多,趁着有空又仔细的看了下官方文档,上面说到Mozilla currently only supports CSS gradients as values of the background-image property, as well as within the shorthand background. You specify a gradient value instead of an image URL. 原来gradient是代替background-image的,那么就可以用gradient做遮罩,然后再用background-color设定按钮背景色,这样就可以去掉三个标签。代码如下:

.button {
	position: relative;
	width: 160px;
	height: 40px;
	line-height: 40px;
	-moz-border-radius: 5px;
	-webkit-border-radius: 5px;
	border-radius: 5px;
	-moz-box-shadow: 0 1px 3px rgba(0, 0, 0, .5);
	-webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, .5);
	box-shadow: 0 1px 3px rgba(0, 0, 0, .5);

	background: -moz-linear-gradient(
		270deg,
		transparent,
		transparent 50%,
		rgba(0, 0, 0, .3) 50%
	);
	background: -webkit-gradient(
		linear,
		left top,
		left bottom,
		from(transparent),
		to(rgba(0, 0, 0, .3)),
		color-stop(.5 ,transparent),
		color-stop(.5 ,rgba(0, 0, 0, .3))
	);
}
.mask {
	top: 1px;
	left: 1px;
	right: 1px;
	bottom: 1px;
	position: absolute;

	text-align: center;
	color: #FFF;
	text-decoration: none;

	-moz-border-radius: 5px;
	-webkit-border-radius: 5px;
	border-radius: 5px;
	background: -moz-linear-gradient(
		270deg,
		rgba(117, 117, 117, .4),
		rgba(94, 94, 94, .4) 50%,
		transparent 50%
	);
	background: -webkit-gradient(
		linear,
		left top,
		left bottom,
		from(rgba(117, 117, 117, .4)),
		to(transparent),
		color-stop(.5 ,rgba(94, 94, 94, .4)),
		color-stop(.5, transparent)
	);
	border: 1px solid rgba(255, 255, 255, .3);
	border-bottom-color: rgba(255, 255, 255, .1);
}

点击查看演示

用CSS3做个好看的按钮

转载须写明出处,附带本文链接。关于文中的示例,请用Firefox 3.6、Chrome 4.x、Safari 4.x查看。

在线观看演示

在网上看到了一篇文章Liquid & Color Adjustable CSS Buttons,感觉里面的那些按钮很漂亮,作者是用半透明的PNG图片当遮罩,来实现好看的按钮。可惜我对美工那些东西一窍不通,照着里面的教程做PNG图片,搞了很久才弄出来,汗。于是我就想,能不能用CSS3来实现类似的效果呢,那个图片有个渐变,然后加上半透明的效果。现在最新的WebKit和Gecko都支持渐变的背景,而半透明用opacity就搞定了。下面就开始动手,先从制作按钮的遮罩层开始。

既然是遮罩层,那么肯定是浮动在按钮上面的(绝对定位),这里用top、left、right、bottom来调整高度和宽度来遮住按钮,加上上面说的渐变和透明。我们将遮罩分为上下两个部分,上面的用渐变背景,下面的只要用纯色就可以了(其实用一个遮罩也可以实现,但是没有办法让遮罩的边框也渐变,所以用两个)。代码是这样的:

.mask-t, .mask-b {
	position: absolute;
  -moz-box-sizing: border-box;
  -wekit-box-sizing: border-box;
  box-sizing: border-box;
}
.mask-t {
	top: 1px;
	left: 1px;
  right: 1px;
  bottom: 50%;

	-moz-border-radius: 5px 5px 0 0;
	-webkit-border-radius: 5px 5px 0 0;
	border-radius: 5px 5px 0 0;  

	background: -moz-linear-gradient(270deg,
    rgba(117, 117, 117, .4) 10%,
    rgba(94, 94, 94, .4) 30%
  );
	background: -webkit-gradient(
		linear,
		left top,
		left bottom,
		from(rgba(117, 117, 117, .4)), to(rgba(94, 94, 94, .4))
	);

  border: 1px solid rgba(255, 255, 255, .4);
  border-bottom: none;
}
.mask-b {
	top: 50%;
	left: 1px;
  right: 1px;
  bottom: 0;

	-moz-border-radius: 0 0 5px 5px;
	-webkit-border-radius: 0 0 5px 5px;
	border-radius: 0 0 5px 5px 0 0;  

  background: rgba(0, 0, 0, .3);

  border: 1px solid rgba(255, 255, 255, .3);
  border-top: none;
}

其实我也不是完全明白CSS3的gradient怎么用,怕讲错,所以这里就不解释了。做这个的时候,我是按照官方文档上的例子改的。

  1. Gecko的:https://developer.mozilla.org/index.php?title=en/CSS/-moz-linear-gradient
  2. WebKit的:http://webkit.org/blog/175/introducing-css-gradients/

OK,遮罩层已经做好了,接下来做按钮。按钮这个层要给遮罩提供定位,而且要设置按钮的大小、颜色,为了美观,我们给它加上圆角和阴影,这也是CSS3的内容。下面是代码:

.button {
	position: relative;
	background: red;
	width: 160px;
	height: 40px;
	line-height: 40px;

	-moz-border-radius: 5px;
	-webkit-border-radius: 5px;
	border-radius: 5px;

	-moz-box-shadow:0 1px 3px rgba(0, 0, 0, .5);
	-webkit-box-shadow:0 1px 3px rgba(0, 0, 0, .5);
	box-shadow:0 1px 3px rgba(0, 0, 0, .5);
}

改变.button的background就可以给按钮换颜色了。注意按钮的border-radius要设置成和遮罩层的一样,我试图给按钮加上overflow: hidden然后去掉遮罩的border-radius,尽管这样,遮罩的四个角还是会显示出来,为什么会这样还请高手指点。接下来,就是按钮的文字部分了,这个层要处在遮罩层的上方以便清楚的显示出文字。和遮罩层一样,设置绝对定位,高宽都设为100%,由于我们的文字层在文档流里处在遮罩层的后面,所以就不用再设z-index了。代码如下:

.text {
	position: absolute;
	width: 100%;
	height: 100%;
	top: 0;
	left: 0;
	text-align: center;
	color: #FFF;
	text-decoration: none;
}

到这里,我们的按钮就做好了。这个按钮的优点是不用图片,减少了HTTP连接数,当然也减少了流量。缺点是,这个按钮现在还没什么用,因为IE到目前为止不支持CSS3,虽然有滤镜,但不如用图片来得快。在这里祝愿IE被早日淘汰。

在线观看演示

去掉inline-block元素之间的水平空白

今天在做柱状图的时候,碰到这样的问题,我把每个柱子(li)都设置成display: inline-block,在标准浏览器下发现它们的水平方向上都有空白。用firebug看了一下,发现这个是浏览器加上去的。试了几个办法,都不是很理想,最后在这些柱子的容器(ul)上加了个word-spaceing: -1em就搞定了。

代码如下:

<!doctype html>
<html>
	<head>
		<title>柱状图</title>
		<style type="text/css">
			ul {
				margin: 0;
				padding: 0;
				word-spacing: -1em;
			}
			ul li {
				display: inline-block;
				height: 300px;
				width: 30px;
				position: relative;
			}
			ul li {
				*display: inline;

			}
			.title, .prog {
				position: absolute;
				text-align: center;
				width: 100%;
			}
			.title {
				background: yellow;
				bottom: 0;
				height: 20px;
			}
			.prog {
				background: red;
				bottom: 20px;
			}
		</style>
	</head>
	<body>
		<ul>
			<li><span class="title">Mon</span><span style="height: 80%" class="prog">80</span></li>
			<li><span class="title">Tue</span><span style="height: 10%" class="prog">10</span></li>
			<li><span class="title">Wen</span><span style="height: 70%" class="prog">70</span></li>
			<li><span class="title">Thu</span><span style="height: 30%" class="prog">30</span></li>
			<li><span class="title">Fri</span><span style="height: 60%" class="prog">60</span></li>
			<li><span class="title">Sat</span><span style="height: 50%" class="prog">50</span></li>
			<li><span class="title">Sun</span><span style="height: 40%" class="prog">40</span></li>
		</ul>
	</body>
</html>