前两天一个同事跟我说页面上有个问题:一个有滚动条的显示、隐藏 div 在 IE 8、IE 9 里每次重新显示的时候,滚动条总是跑回顶部。我查看源码,看到那东东上赫然出现了刺眼的 onmouseover 、onmouseout,我最不喜欢这里出现在这些了(作为前端开发者,你懂得!),第一印象可能是这里的问题。好吧,我改写一下。然而,当我把分离、简洁、可读性强的代码放上去后,依然是老样子。你可以用 IE 8 或 IE 9 查看这个 Demo。
莫非真的是我的样式引起的?经过再次检查以及在单独的页面测试下,最终得知是 IE 8、IE 9 的问题。当一个元素设置 display:none 后,scroll(scrollHeight、scrollLeft、scrollTop、scrollWidth)属性值变为 0,再设置为 display:block 后,元素的 scroll 属性值会变回设置 display:none 之前原本的值,但 IE 8、IE 9 却没有变回原有的值,依然是 0,所以就出现了滚动条跑回顶部这样的问题(即 scrollTop 值为 0)。使用 IE 9 的“开发人员工具”可以查看元素的 scroll 属性值的变化,如下图:
IE 9 开发人员工具并不能实时监控,如果进行了操作,需要点选其他元素然后再切换回元素才能重新获取最新的 DOM 信息。
当然也可以使用 JavaScript 来获取元素在各个状态下的 scroll 值,上面的 Demo 已经加入了该功能,或者你可以再次点击 Demo 页面查看。
那如何解决这个问题呢?我试着给 div 元素加一些解决 IE 常见问题的属性,如:zoom、:hover 等等,但没有效果,最后想到以下一些方法,这些方法都是“绕过” display:none 隐藏元素,以免 scroll 变成 0。
visibility 的属性 hidden 也能隐藏元素,上面的例子改为 visibility:hidden 隐藏后,用 IE 9 的开发人员工具可以看到 div 元素的 scroll 值没有变化,ok,问题解决了。与 display 不同的是,visibility 隐藏元素后,该元素仍然会占据原来的物理空间,如果这个物理空间对上下元素有影响的话,这个方法就不是“完美”的方法。但我们的 div 元素刚好是绝对定位,这个物理空间对上下元素没有影响,所以最终还是选用这个方法。查看此方法解决问题的 Demo。
隐藏元素也可以设置其 height 为 0,如果元素有 padding、border 等属性,应先清除或改变,使其不可见,待显示时再还原。关于 IE 6 在某些情况下设置 height:0 无效的问题不在本话题讨论范围内,就不再啰嗦。查看此方法解决问题的 Demo。
设置不透明度 opacity:0 同样能隐藏元素,但和 visibility 一样,仍会占据原来的物理空间。查看此方法解决问题的 Demo。
也许你还想到了给元素设置 position 属性,再设置一个较大的偏移值,让其便偏移出浏览器显示范围内,达到"隐藏"的效果。然而事实告诉我们,IE 8、IE 9 还是和 display 一副模样,所以这个方法行不通,你可以查看这个 Demo
这些方法没有太大技术含量,所以没有特别详细说明,具体可以查看对应的 Demo。如果您有其他更简单、完美、新颖的方法解决此问题,欢迎发表留言。
PS:这也会有问题,真是躺着也中枪!
Original article: IE8 IE9 display:none 引发的 scrollTop 问题
©2015 一起CSS. All Rights Reserved.