分类目录归档:HTML

修复在IE6下img标签引用半透明png图片的bug

<!--[if lte ie 6]>
<script type="text/javascript">
    function correctPNG() {
        var images = document.getElementsByTagName('IMG');
        for (var i = 0, len = images.length; i < len; i++) {
            var img = images[i];
            if (img.className && img.className.indexOf('alpha-opacity') !== -1) {
                var imgID = (img.id) ? "id='" + img.id + "' " : "";
                var imgClass = (img.className) ? "class='" + img.className + "' " : "";
                var imgTitle = (img.title) ? "title='" + img.title + "' " : "title='" + img.alt + "' ";
                var imgStyle = "display:inline-block;" + img.style.cssText;
                if (img.parentElement.href) {
                    imgStyle = "cursor:hand; " + imgStyle;
                }
                var strNewHTML = "<span " + imgID + imgClass + imgTitle
                        + " style=\"" + "width:" + img.width + "px; height:" + img.height + "px;" + imgStyle
                        + "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader"
                        + "(src=\'" + img.src + "\', sizingMethod='scale');\"></span>";
                img.outerHTML = strNewHTML;
                --i;
                --len;
            }
        }
    }
    window.attachEvent("onload", correctPNG);
</script>
<![endif]-->

弹出窗口的兼容方案

<!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>
	<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
	<title>主页面</title>
	<style type="text/css">
	html, body {
		margin: 0;
		padding: 0;
	}
	body {
	}
	#div1 {
		height: 2000px;
	}
	#floatedLayer {
		position: fixed;
		_position: absolute;
	}
	</style>
</head>
<body>
	<div id="floatedLayer">
		<iframe src="demo.html" width="580" height="542" frameborder="no"></iframe>
	</div>
	<div id="div1"></div>
	<script type="text/javascript">
		var floatedLayer = document.getElementById("floatedLayer");
		function adjustPopupWin() {
			var height = document.documentElement.clientHeight,
				width = document.documentElement.clientWidth;				
			floatedLayer.style.left = Math.max((width - floatedLayer.offsetWidth) / 2, 0) + "px";
			floatedLayer.style.top = Math.max((height - floatedLayer.offsetHeight) / 2, 0) + "px";
		}
	</script>
	<!--[if IE 6]>
	<script type="text/javascript">
		function adjustPopupWin() {
			var height = document.documentElement.clientHeight,
				width = document.documentElement.clientWidth;
			floatedLayer.style.left = Math.max((width - floatedLayer.offsetWidth) / 2, 0) + document.documentElement.scrollLeft + "px";
			floatedLayer.style.top = Math.max((height - floatedLayer.offsetHeight) / 2, 0) + document.documentElement.scrollTop + "px";
		}
		window.onscroll = adjustPopupWin;
	</script>
	<![endif]-->
	<script type="text/javascript">
		window.onresize = adjustPopupWin;
		adjustPopupWin();
	</script>
</body>
</html>

自定义样式的input[type=range]

今天下午有人在群里提出个问题,能不能把自定义样式应用到HTML 5中的range元素上。晚上研究了一下,是可以实现上述的需求的。请用Chrome查看Demo。代码如下:

<!DOCTYPE html>
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
	<title>自定義樣式的input[type=range]</title>
	<style type="text/css"> 
	#range {
		width: 600px;
		height: 10px;
		background: rgba(60, 114, 230, .8);
		border: 1px solid #333;
		-webkit-border-radius: 5px;
		-webkit-appearance: none !important;
	}

	#range::-webkit-slider-thumb{
		width: 28px;
		height: 28px;	
		
		background: -webkit-gradient(
			linear,
			left top,
			left bottom,
			from(#fff),
			to(#ccc)
		);
		
		border: 1px solid #000;
		-webkit-box-shadow: 0 0 6px #000;
		-webkit-border-radius: 14px;
		-webkit-appearance: none !important;  
	}
	
	#result {
		border: 2px solid #ccc;
		width: 32px;
	}
	</style>
</head>
<body>
	<input type='range' min='0' max='1000' value='0' id='range' />
	<input type='text' id='result'/>
	<script type='text/javascript'>
	var result = document.getElementById('result');
	document.getElementById('range').onchange = function() {
		result.value = this.value;
	}
	</script>
</body>
</html>

代码中的”-webkit-appearance: none !important”很重要,要先把-webkit-appearance设置为none才能自定义样式。

阻止Firefox缓存input的值

在Firefox里面input的值会被缓存起来,刷新页面之后,会恢复成刷新之前的值。有的时候我们并不希望这么做,可以用autocomplete=”off”来阻止Firefox的默认机制。

比如下面的代码,在刷新页面之后input的值全部为空。

<form>
<input autocomplete="off" type="text" /><br />
<input autocomplete="off" type="text" /><br />
<input autocomplete="off" type="text" /><br />
<input autocomplete="off" type="text" /><br />
</form>

为了方便也可以这样写:

<form autocomplete="off">
<input type="text" /><br />
<input type="text" /><br />
<input type="text" /><br />
<input type="text" /><br />
</form>

elem.style.left与elem.offsetLeft的区别

elem.style.left是元素的最左边(包括元素的margin-left)到offsetParent左边padding(包括左边padding)的距离。

用公式简单的表示一下两者的关系:elem.offsetLeft = elem.style.left + elem.style.marginLeft

在IE8下:
elem.offsetLeft = elem.style.left + elem.style.marginLeft + elem.offsetParent.borderLeftWidth

在IE7下:
elem.offsetLeft = elem.style.left + elem.style.marginLeft + elem.offsetParent.borderLeftWidth + elem.offsetParent.marginLeftWidth

在IE6下:
elem.offsetLeft = elem.style.left + elem.style.marginLeft + elem.offsetParent.paddingLeftWidth + elem.offsetParent.borderLeftWidth + elem.offsetParent.marginLeftWidth

记录一下,如何取得元素的”计算出的样式”。

function getCurrentStyle(elem, style) {
	return window.getComputedStyle
			? window.getComputedStyle(elem, null)[style]
			: elem.currentStyle[style];
}

星级评价

闲来无事,想做一个星级评价系统的UI,又不想用JavaScript。分析一下,只能从:hover这个伪类入手,但是IE6除了a标签,别的标签都不支持:hover伪类。所以问题就限定在怎么样用a标签来实现星级评价。

假设星级评价有5个等级,每个星星有20象素的高度和宽度。

最初的想法是用嵌套的方式去实现,但a标签是不能嵌套使用的。所以又想到了重叠的方式,比如等级5是100象素的宽度,等级4是80个象素,并且覆盖到等级5的上面。等级3是60个象素,覆盖到等级4的上面。以此类推,并且把这5个a标签左对齐,设置一下hover时的背景图片就搞定了。

CSS代码:

#rating {
  position: relative;
}
#rating a {
  display: block;
  height: 20px;
  position: absolute;
  left: 0;
  top: 0;
}
#rating a:hover {
  background: red;
}
#rank5 {
  width: 100px;
}
/* 每个rank都要设置宽度,很麻烦。省略不写了。 */

HTML代码:

<div id="rating">
  <a id="rank5" href="#"></a>
  <a id="rank4" href="#"></a>
  <a id="rank3" href="#"></a>
  <a id="rank2" href="#"></a>
  <a id="rank1" href="#"></a>
</div>

但是这样很麻烦,每个等级的a标签都要设置宽度。那么就结合一下嵌套和重叠的方法,每个等级再加入div标签做嵌套,实现自动适应宽度。

CSS代码:

#rating {
  width: 100px;
  height: 20px;
  background: transparent url(star_rating.gif) repeat;
}
#rating div {
  margin-right: 20px;       
}
#rating, #rating div
{
  zoom: 1; /* 如果不加这个,在IE6,7下你会很纠结 */       
  position: relative; 
}
#rating a {
  position: absolute;
  height: 20px;
  width: 100%;
}
#rating a:hover {
  background: transparent url(star_rating.gif) repeat;
  background-position: 0 -20px;
}     

HTML代码:

<div id="rating"> 
  <a href="#"></a>
  <div> 
    <a href="#"></a>
    <div> 
      <a href="#"></a>
      <div> 
        <a href="#"></a>
        <div> 
          <a href="#"></a>
        </div>
      </div>
    </div>
  </div>
</div>

解释一下,#rating这个div是等级5的容器,设定它的宽度为100象素,这时候它里面的div也都是宽100象素。然后它里面的div分别向右间隔20个象素,这样就变成了宽100px,80px,60px,40px和20px的五个div。再让a标签绝对定位重叠起来,并且让它们和容器一样的大小。设置好背景图片之后,一个星级评价的UI就完成了。

点我查看完整的演示

Inline elements的一些事

Inline elements的定义

Inline-level elements are those elements of the source document that do not form new blocks of content; the content is distributed in lines (e.g., emphasized pieces of text within a paragraph, inline images, etc.). Several values of the ‘display’ property make an element inline: ‘inline’, ‘inline-table’, ‘inline-block’ and ‘run-in’ (part of the time; see run-in boxes). Inline-level elements generate inline boxes.

replaced elements and non-replaced elements

An element whose content is outside the scope of the CSS formatting model, such as an image, embedded document, or applet. For example, the content of the HTML IMG element is often replaced by the image that its “src” attribute designates. Replaced elements often have intrinsic dimensions: an intrinsic width, an intrinsic height, and an intrinsic ratio. For example, a bitmap image has an intrinsic width and an intrinsic height specified in absolute units (from which the intrinsic ratio can obviously be determined). On the other hand, other documents may not have any intrinsic dimensions (for example, a blank HTML document).

User agents may consider a replaced element to not have any intrinsic dimensions if it is believed that those dimensions could leak sensitive information to a third party. For example, if an HTML document changed intrinsic size depending on the user’s bank balance, then the UA might want to act as if that resource had no intrinsic dimensions.

replaced elements的大概意思是那些有自己尺寸和比例的元素,比如img有自己的宽和高。img,input,textarea,select,object这些都是replaced elements,除了它们别的元素就是non-replaced elements。

Inline elements的宽和高

对于non-replaced的inline元素,设置width和height是没有作用的,不过此类元素的高度可以由line-height来指定。

Inline elements的padding和margin

对于non-replaced的inline元素,padding和margin作用方式是一样的,margin和padding只会在左右两个方向起到实际作用。如下面的例子,将a元素的padding设置了50px,只在左右留出了空白。

Lorem ipsum dolor sit amet consect etuer adipi scing elit sed diam nonummy nibh euismod tinunt ut laoreet dolore magna aliquam erat volut. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.

学习hasLayout

hasLayout是一个非常有必要理解的概念,大多IE下的显示错误,就是源于hasLayout。

什么是hasLayout?

hasLayout是Windows Internet Explorer(IE)渲染引擎的一个内部组成部分。在IE中,有两类元素:

  1. 元素对自身的内容进行计算大小和组织。
  2. 元素依赖于父元素来计算尺寸和组织内容。

当一个元素的hasLayout属性为true时,我们就说这个元素有一个布局,也就是这个元素对自己和可能的子孙元素进行尺寸计算和定位。

哪些元素拥有布局?

当一个元素有一个布局时,意味着这个元素需要花更多的代价来维护自身和里面的内容, 而不是依赖于祖先元素来完成这些工作。如果所有的元素都默认有布局,会对性能和内存使用上产生有害的影响。

以下元素默认拥有布局:

  • Images
  • Tables, TableRows, TableCells
  • HR
  • Input elements: text, button, file, select
  • Marquee
  • Framesets, Frames
  • Objects, applets, plugins
  • Absolute positioned elements
  • Floated elements
  • Inline-block elements
  • Filters (rotation, dropshadow, etc.)
  • Body (as well as HTML element in strict mode)

如何激发hasLayout?

  • Block level elements with width or height specified under strict mode
  • Any element with width/height specified under compat mode
  • Elements that have the Zoom property set
  • Elements that are in edit mode
  • Elements that host to a viewlinked behavior
  • Layout-flow is different from parent layout flow (rtl to ltr)
  • 设置position: absolute
  • 设置writing-mode: tb-rl
  • 设置float为left或right

zoom总是可以触发hasLayout,但是在IE5.0中不支持。

具有”layout”的元素如果同时display: inline,那么它的行为就和标准中所说的inline-block很类似了:在段落中和普通文字一样在水平方向和连续排列,受vertical-align影响,并且大小可以根据内容自适应调整。这也可以解释为什么单单在IE中内联元素可以包含块级元素而少出问题,因为在别的浏览器中 display: inline就是内联,不像IE一旦内联元素拥有layout还会变成inline-block。

hasLayout问题的调试与解决。

当网页在IE中有异常表现时,可以尝试激发hasLayout来看看是不是问题所在。常用的方法是给某元素css设定zoom: 1 。使用zoom: 1 是因为大多数情况下,它能在不影响现有环境的条件下激发元素的hasLayout。而一旦问题消失,那基本上就可以判断是 hasLayout 的原因。然后就可以通过设定相应的 css属性来对这个问题进行修正了。建议首先要考虑的是设定元素的width/height属性,其次再考虑其他属性。

对IE6及更早版本来说,常用的方法被称为霍莉破解(Holly hack),即设定这个元素的高度为1%。需要注意的是,当这个元素的 overflow属性被设置为visible时,这个方法就失效了。或者使用IE的条件注释。

对IE7来说,最好的方法时设置元素的最小高度为0(min-height:0;)。

hasLayout引起的常见bug。

  • IE6及更低版本的双空白边浮动(bug修复:display:inline;)
  • IE5-6的3像素偏移(bug修复:_height:1%;)
  • IE6的躲躲猫(peek-a-boo)(bug 修复:_height:1%;)