由锚点失效引发的hasLayout探究

最近在项目中遇到了一些与锚点相关的问题,由此引出hasLayout的一系列概念和方法,在此记录下来与大家一起分享。

一、锚点的相关问题


1.html map定位的名字问题。


[html]  view plain copy
  1. <div id="top">  
  2.     <img src="img/20120417/top.jpg" alt="80后游戏" width="950" height="710" border="0" usemap="#map1" />  
  3.     <map id="map1" name="map1">  
  4.     <area coords="222,176,19"  shape="circle" href="#bk01" title="超级玛丽"></area>  
  5.     <area coords="335,185,19"  shape="circle" href="#bk02" title="三国志"></area>  
  6.     <area coords="443,163,19"  shape="circle" href="#bk03" title="魂斗罗"></area>  
  7.     </map>  
  8. </div>  

大部分浏览器都支持map的name属性,而webkit内核的浏览器,如chrome和safari,不认识name,必须使用id,否则定位锚点消失。所以这里id和name都用。


2.锚点的hasLayout问题。


一般情况我们做页内导航都习惯用a标签,或者对图片采用map热点定位。然后设定一些锚点用于页面内部内容区块的快速定位,方便浏览者查找。为此需要html中添加代码<a name="abc"></a>或<a id="abc"></a>,这样锚点就设好了。
不管是以a标签链接做导航,还是采用map area定位,其在IE6下锚点都可能存在bug,具体行为就是点击后没有跳转,无法定位。

个人认为这是IE6的Layout没有被触发,这里就需要手动添加CSS代码去激发hasLayout,这里是经过本人测试的几种办法,也是一些最常用的方法:
方法1.由于a是内联元素,所以要使用宽高去触发,必须将其先转化为块级元素。
[css]  view plain copy
  1. .jumpAnchor{  
  2.     width:0;  
  3.     display:block;  
  4. }  

或者
[css]  view plain copy
  1. .jumpAnchor{  
  2.     height:0;  
  3.     display:inline-block;  
  4. }  

还有一个方法,就是直接在锚点所在a标签里添加文字或图片内容,让内容去撑开,自动去激发hasLayout。如<a id='anchor' name='anchor'>激发haslayout,我来撑开</a>,
方法2.使用zoom:1;来触发,这个方法的副作用少,不用为此写许多兼容各浏览器的hack。这是目前为止最常用、最安全、最节约成本的激发方式。在个别复杂的情况下,可以搭配使用position:relative;来达到触发hasLayout的目的。

3.锚点本身使用id与name属性的区别。

1)二者的适用范围不同。目标元素的id和name都可以作为锚点,蛋name属性本身具有局限性,而id属性适用于任何类型的目标元素。这里列出name属性适用的几个标签元素:a, map, applet, form, frame, iframe, img
2)二者定位的准确性不同。某些情况下用id存在定位偏移,而name可以准确定位。虽然有解决id定位偏移的方法,但是如果仅仅是作为锚点,建议尽量使用name属性。
3)name属性可以重复而id不可重复,经测试重复的name和独立的id都会定位到第一个,但是为了养成良好的编码习惯,应该避免这样的写法,保持id和name属性值的唯一性。
此外,还需要注意,尽量对这两个属性使用小写字母。虽然html本身不区分大小写,但是对于锚点,在IE下不区分大小写,大写小写是一样的属性值,而在火狐Firefox、谷歌Chrome下大小写就属于两个不同的属性值了。

其实,我们在项目实践中,都经历过形形色色的hasLayout问题。而这些问题又有绝大部分是IE这个大魔头引出的,主要是IE6和IE7。比如设置border边框显示边框断开,设置背景色不能正确显示,3px文本慢移,双边距,躲躲猫(peek-a-boo)。这些都是IE下面因此而生的bug。
插一句,IE6下面3px文本慢移出现的条件是:如果边框框邻近某浮动元素,则边框和浮动边缘之间会出现3px的间隙。在内容清除浮动之前,此间隙不会消失,内容框朝着浮动相反的方向“慢移”三个像素。而当左对齐文本邻近右浮动时,可能难以看到此间隙,但它确实存在,而且它可能导致紧密的布局中出现“浮动下降”。解决“3px文本慢移”的常用方法是:给浮动的盒子添加一个margin-right:-3px;(与浮动方向反方向)。

二、IE下hasLayout布局的触发机制

言归正转,为此,我们要认识hasLayout,了解它,然后才能更好的针对问题找出解决办法。

首先,我们要了解Layout与hasLayout属性是什么?
Layout,意为“布局”,是IE/Windows下的特有概念,它决定了元素如何对其内容进行定位和尺寸计算,与其他元素的关系和相互作用,以及对应用还有使用者的影响。hasLayout为只读属性,对本身不具有Layout的元素,如果其Layout被动触发后是不可逆的。
hasLayout,是IE渲染引擎的一个内部组成部分。在IE中,一个元素计算大小和组织内容,要么对自身的内容进行计算大小和组织内容,要么依赖于父元素来计算尺寸和组织内容。为了调节这两个不同的概念,渲染引擎采用了hasLayout的属性,属性值可以为true或false。当一个元素的 hasLayout属性值为true时,我们说这个元素有一个布局(Layout)。

据不完全统计,默认具有haslyout的HTML标签元素有:<table>、<td>、<body>、<img>、<hr>、<input>、<select>、<textarea>、<button>、<iframe>、<embed>、<object> <applet>、<marquee>、< html>、< tr>、< th>、<fieldset>、< frameset>、<frame> 等。
当网页在IE中有异常表现时,可以首先通过尝试激发haslayout来确定是否为当前容器的Layout没有被激发造成。
接着,我们看如何来激发元素的hasLayout属性。以下是“寂寞贱客”
1、通过设置CSS能够获得的haslayout的属性有:display: inline-block;、height: (任何值除了auto);、float: (left或right);、position: absolute;、 width: (任何值除了auto);、writing-mode: tb-rl;、zoom: (除normal外任意值);、 min-height: (任意值);、 max-height: (除none外任意值);、min-width: (任意值);、max-width: (除none外任意值);、overflow: (除visible外任意值);、overflow-x: (除visible外任意值);、overflow-y: (除visible外任意值);、 position: fixed;(未完全统计)。
2、对于内联元素(默认即为内联的元素,如span,或display:inline; 的元素),width和height只在IE5.x下和IE6或更新版本的quirks模式下触发hasLayout。而对于IE6,如果浏览器运行于标准兼容模式(具有Doctype的模式)下,内联元素会忽略width或height属性,所以设置width或height不能在此种情况下令该元素具有layout。
3、zoom总是可以触发hasLayout,但是在IE5.0中不支持。
4、对IE6及更早版本来说,常用的方法被称为霍莉破解(Holly hack),即设定这个元素的height:1%;。需要注意的是,当这个元素的overflow属性为visible时,这个方法就失效了。曾经流行使用这种方法的时候,还没有出现IE7,而height属性在IE6下其实是按照"min-height"来解析的,所以只要对IE6进行hack,"* html{height:1%}"就可以触发hasLayout,同时又不产生副作用。后来出现的IE7仍然存在很多hasLayout的问题,但IE7已经能够正确识别height属性了,“height:1%”的方法已经不再适用了。
5、对IE7来说,最好的方法是设置元素的最小高度为0px(min-height0;)。

三、IE6下PNG24/PNG32不透明的解决方法


说完了锚点和hasLayout,还有一个常见的问题。我们知道在所有浏览器下都可以支持透明的png8图片,但是有时候是出于清晰度的要求,有时候是为了去除杂边(当然,杂边的消除方式,可以采用ps中添加与背景色一致的杂色而达到目的,不过某些情况下这好像不太现实,比如背景色不是纯色的时候),我们不得不选用位数更高的透明图片,常用的png-24和png-32的。


方法一: 定义CSS样式,给某元素应用这个样式后,其透明png背景图片就实现透明了。(注意CSS background背景图片的路径写法与_filter路径写法的区别,_filter属性路径是相对于html文件的位置。)
[css]  view plain copy
  1. .toTop a{  
  2.     height:165px;  
  3.     width:216px;  
  4.     background:url("../img/20120417/gototop.png"no-repeat scroll 0 0 transparent;  
  5.     position:fixed;  
  6.     top:70%;  
  7.     right:1%;  
  8.     _position:absolute;  
  9.     _top:expression(documentElement.scrollTop + 350 + "px");  
  10.     cursor:pointer;  
  11.     opacity:0.8;  
  12.     _backgroundnone/*针对IE6*/  
  13.     _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=noscale, src="img/20120417/gototop.png");/*针对IE6*/  
  14.     /*可以省略部分属性为_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='img/20120417/gototop.png'); */  
  15. }  



相关的讲解:
style="filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/test.png')"

语法:
filter : progid:DXImageTransform.Microsoft.AlphaImageLoader ( enabled=bEnabled , sizingMethod=sSize , src=sURL )

enabled : 可选项。布尔值(Boolean)。设置或检索滤镜是否激活。 其中true : 默认值,滤镜激活。false : 滤镜被禁止。
sizingMethod : 可选项。字符串(String)。设置或检索滤镜作用的对象的图片在对象容器边界内的显示方式。
属性值:
crop : 剪切图片以适应对象尺寸。
image : 默认值。增大或减小对象的尺寸边界以适应图片的尺寸。
scale : 缩放图片以适应对象的尺寸边界。

src : 必选项。字符串(String)。使用绝对或相对 url 地址指定背景图像。假如忽略此参数,滤镜将不会作用。
属性值:
Enabled : 可读写。布尔值(Boolean)。参阅 enabled 属性。
sizingMethod : 可读写。字符串(String)。参阅 sizingMethod 属性。
src : 可读写。字符串(String)。参阅 src 属性。

说明:
在对象容器边界内,在对象的背景和内容之间显示一张图片。并提供对此图片的剪切和改变尺寸的操作。如果载入的是PNG(Portable Network Graphics)格式,则0%-100%的透明度也被提供。
PNG(Portable Network Graphics)格式的图片的透明度不妨碍你选择文本。也就是说,你可以选择显示在PNG(Portable Network Graphics)格式的图片完全透明区域后面的内容。


方法二: 此方法针对直接插入html中的图片。对该图片定义css样式。注意,要准备一个透明的小图片transparent.gif,不要太大否则太大太多影响页面加载性能。此例子中是必须放在和html相同目录下。

[html]  view plain copy
  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
  2. <html xmlns="http://www.w3.org/1999/xhtml">  
  3. <head>  
  4. <meta http-equiv="Content-Type" content="text/html; charset=gb2312" />  
  5. <title>IE6下背景不透明解决办法</title>  
  6. <style type="text/css">  
  7. .fixpng img {  
  8. azimuth: expression(  
  9. this.pngSet?this.pngSet=true:(this.nodeName == "IMG" && this.src.toLowerCase().indexOf('.png')>-1?(this.runtimeStyle.backgroundImage = "none",  
  10. this.runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + this.src + "', sizingMethod='image')",  
  11. this.src = "transparent.gif"):(this.origBg = this.origBg? this.origBg :this.currentStyle.backgroundImage.toString().replace('url("','').replace('")',''),  
  12. this.runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + this.origBg + "', sizingMethod='crop')",  
  13. this.runtimeStyle.backgroundImage = "none")),this.pngSet=true);  
  14. }  
  15.   
  16. </style>  
  17. </head>  
  18.   
  19. <body>  
  20. <div class="fixpng">  
  21. <img src="1.png" width="10" height="10" border="0"/>  
  22. <img src="2.png" width="20" height="20" border="0" />  
  23. <img src="3.png" width="30" height="30" border="0" />  
  24. </div>  
  25. </body>  
  26. </html>  


方法三:使用DD_belatedPNG插件,它不仅支持img,还支持backgrond-position与background-repeat.这是优于其他插件的功能.同时DD_belatedPNG还支持a:hover属性。
使用方法

1.下载DD_belatedPNG插件.下载地址http://dillerdesign.com/experiment/DD_belatedPNG/#download
2.在网页html中引用,如下:
[html]  view plain copy
  1. <!--[if IE 6]>  
  2.  <script type="text/javascript" src="js/DD_belatedPNG_0.0.8a-min.js" ></script>  
  3.  <script type="text/javascript">  
  4.      DD_belatedPNG.fix('#define,background');  
  5.  </script>  
  6. <![endif]-->  


说明:DD_belatedPNG.fix('CSS选择器, 应用类型');函数 DD_belatedPNG.fix() , 括号内参数分别为应用PNG的CSS选择器(支持ID选择器、类选择器)和应用类型(支持img和background两种)。
多个选择器多种类型的函数,可以连写为类似如 DD_belatedPNG.fix('#idname, .classname, .nav a:hover, img,background');

还有两种网络上的方法,未经测试,写在下面备用。

方法四:本方法也只对直接插入的图片有效,对背景图无效。
[html]  view plain copy
  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
  2. <html xmlns="http://www.w3.org/1999/xhtml">  
  3. <head>  
  4. <meta http-equiv="Content-Type" content="text/html; charset=gb2312" />  
  5. <title>IE6下png背景不透明解决办法</title>  
  6. <script language="JavaScript">  
  7. function correctPNG() // correctly handle PNG transparency in Win IE 5.5 & 6.  
  8. {  
  9.     var arVersion = navigator.appVersion.split("MSIE")  
  10.     var version = parseFloat(arVersion[1])  
  11.     if ((version >= 5.5) && (document.body.filters))  
  12.     {  
  13.        for(var j=0; j<document.images.length; j++)  
  14.        {  
  15.           var img = document.images[j]  
  16.           var imgName = img.src.toUpperCase()  
  17.           if (imgName.substring(imgName.length-3, imgName.length) == "PNG")  
  18.           {  
  19.              var imgID = (img.id) ? "id='" + img.id + "' " : ""  
  20.              var imgClass = (img.className) ? "class='" + img.className + "' " : ""  
  21.              var imgTitle = (img.title) ? "title='" + img.title + "' " : "title='" + img.alt + "' "  
  22.              var imgStyle = "display:inline-block;" + img.style.cssText  
  23.              if (img.align == "left") imgStyle = "float:left;" + imgStyle  
  24.              if (img.align == "right") imgStyle = "float:right;" + imgStyle  
  25.              if (img.parentElement.href) imgStyle = "cursor:hand;" + imgStyle  
  26.              var strNewHTML = "<span " + imgID + imgClass + imgTitle  
  27.              + " style=\"" + "width:" + img.width + "px; height:" + img.height + "px;" + imgStyle + ";"  
  28.              + "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader"  
  29.              + "(src=\'" + img.src + "\', sizingMethod='scale');\"></span>"  
  30.              img.outerHTML = strNewHTML  
  31.              j = j-1  
  32.           }  
  33.        }  
  34.     }      
  35. }  
  36. window.attachEvent("onload", correctPNG);  
  37. </script>  
  38. <style type="text/css">  
  39. <!--  
  40. body {  
  41. background-color: #9999CC;  
  42. }  
  43. -->  
  44. </style>  
  45. </head>  
  46.   
  47. <body>  
  48. <img src="1.png" width="10" height="10" border="0"/>  
  49. <img src="2.png" width="20" height="20" border="0" />  
  50. <img src="3.png" width="30" height="30" border="0" />  
  51. </body>  
  52. </html>       


方法五:纯js实现方法。
[javascript]  view plain copy
  1. <script type="text/javascript">  
  2. // 修复 IE 下 PNG 图片不能透明显示的问题  
  3. function fixPNG(myImage) {  
  4. var arVersion = navigator.appVersion.split("MSIE");  
  5. var version = parseFloat(arVersion[1]);  
  6. if ((version >= 5.5) && (version < 7) && (document.body.filters))  
  7. {  
  8.      var imgID = (myImage.id) ? "id='" + myImage.id + "' " : "";  
  9.      var imgClass = (myImage.className) ? "class='" + myImage.className + "' " : "";  
  10.      var imgTitle = (myImage.title) ? "title='" + myImage.title   + "' " : "title='" + myImage.alt + "' ";  
  11.      var imgStyle = "display:inline-block;" + myImage.style.cssText;  
  12.      var strNewHTML = "<span " + imgID + imgClass + imgTitle  
  13.   
  14.    + " style=\"" + "width:" + myImage.width  
  15.   
  16.    + "px; height:" + myImage.height  
  17.   
  18.    + "px;" + imgStyle + ";"  
  19.   
  20.    + "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader"  
  21.   
  22.    + "(src=\'" + myImage.src + "\', sizingMethod='scale');\"></span>";  
  23.      myImage.outerHTML = strNewHTML;  
  24. } }  
  25.   
  26. window.οnlοad=function(){  
  27.          document.getElementById("top").style.height=screen.height/5+"px";  
  28.           
  29. }//  
  30. </script>  



引用方法如下:
<img src="logo.png" width="" height="" border="0" οnlοad="fixPNG(this)" />

更多相关文章请参考《 你必须知道--IE中的hasLayout  》http://blog.csdn.net/rhinemetal/article/details/6233277
最新让IE6支持PNG24背景透明最佳解决方法 》http://hi.baidu.com/lzc10086/blog/item/ad38d32f645e82704ec22616.html

IE6下png背景不透明问题的综合拓展》http://apps.hi.baidu.com/share/detail/34680089


转自:http://blog.csdn.net/freshlover/article/details/7478684

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值