对html与body的一些研究与理解

这篇文章发布于 2009年09月18日,星期五,21:21,归类于 CSS相关。 阅读 158143 次, 今日 7 次 23 条评论

 

一、写在前面的

最近一直构思着写篇关于<html>标签的文章,虽说之前处理过<html>标签,也解决过不少棘手的问题,但是对其理解还不是很透彻,很多原理都是自己推测的。

在网上查阅相关资料想整合一下相关的信息,发现深入探讨<html>,与<body>的文章很少,只有在蓝色理想看到一篇“一叶千鸟”的这篇“正确认识html与body”有点价值,其余都没有什么相关的好文章。

而这里,我要讲述的与上面的交集并不多,只要是讲述一些关于<html><body>的各种表现,以及我自己对这些表现的合理的解释和并提供一些过去处理类似问题的经验,希望对大家能够有所帮助。

二、关于html与body的一些表现

1.背景色

一般情况下,我们css控制的最高节点就是body,例如设置:

body{background:#069;}

则浏览器界面就是完全的#068的背景色。这里看上去是<body>标签下的背景色起作用了,我到不这么认为,这里不是bodybackground起作用,而是body作为一个根节点起作用了,<html>标签未被激活,body担当类似于根节点的节点,其background背景色被浏览器俘获,浏览器界面背景色为background的背景色,以上是我的推论,这种推论不是我凭空想象出来的,而是有一定的根据的。看下面的一段css代码:

body{background:#069; margin:100px; border:30px solid #093;}

意思很简明:外边距100像素,边框30像素,背景色#069,按照对一般标签的理解,100像素的外边距应该不含有背景色的,然而显示的结果是(Firefox下表现与此类似):

IE6下body设置background颜色边框和边距后的表现

IE6下body设置background颜色边框和边距后的表现

还有一点可以证明我上面的推论,就是一旦设置了<html>节点的background背景色之后,<body>的背景色将失效。例如下面的简短代码:

html{background:#999;}
body{background:#069; margin:100px; border:30px solid #093;}

跟上面的想比,就是添加了html的背景色,结果(截自IE6,Firefox浏览器下表现一致):

html标签设置背景色后的样式表现

html标签设置背景色后的样式表现

结果是什么呢?<body>标签的满屏的背景色不见了,“失效”了。其实,在我看来,不是“失效”,是生效了。当<html>标签无背景样式时,<body>的背景色其实不是<body>标签的背景色,而是浏览器的。一旦html标签含有背景色,则<body>的背景色变成了正常的<body>标签(一个实实在在,普普通通标签)的背景色,而此时的<html>标签最顶级,背景色被浏览器获取,成为浏览器的背景色。

2.margin支持

从上面的实例可以看出,无论是IE6浏览器,还是Firefox浏览器,<body>margin属性是支持的,padding也是如此,那么对于<html>标签呢。如下测试代码:

html{background:#999;margin:100px; border:30px solid #093;}
body{background:#069; margin:100px; border:30px solid #093;}

html标签也增加了margin间距和30像素的边框,结果如下:
IE6下:

IE6浏览器下html对margin不敏感不支持

IE6浏览器下html对margin不敏感不支持

Firefox浏览器下:

Firefox浏览器下html标签支持margin外边距

Firefox浏览器下html标签支持margin外边距

这是缩放到500像素宽的图片,仔细看还是会发现IE6下margin没有起作用,顶边的是30像素的边框,Firefox下margin起作用了,可以看到30像素的边框外部还有一段间距。此图<html>标签背景色的全屏显示也进一步证明了我上面有关背景色显示原理的推论。

3.关于滚动条

打开一个空白页面,观察浏览器右侧,会发现IE浏览器会有一段滚动条的槽道,而Firefox浏览器下没有。

空白页面下IE和Firefox火狐浏览器左侧的滚动条与否

空白页面下IE和Firefox火狐浏览器左侧的滚动条与否

Firefox下没有滚动条,有时候会产生体验上的一些问题,比如:假设一个页面高度有限,无滚动条,当鼠标移到一个元素上,要显示一个浮动层,但是这个浮动层有一定的高度,加上鼠标位置偏低,一旦浮动层出现,说不定页面的高度被撑高并出现滚动条,这是在Firefox浏览器下就会产生页面的晃动,原因是滚动条的出现导致页面的宽度减小,布局发生一些偏移,而这种便宜造成的体验是不好的。如何避免呢?很多人会想到设置

body{overflow-y:scroll;}

Firefox下是出现了滚动槽了,但是IE下出现了两个滚动条,如下:

IE6下的双滚动条

可能有人会想到hack,no,no,no,其实仔细想一想,问题很简单。为什么IE会产生双固定条,里面那一个肯定是<body>的,那么外面的那一个呢?啊,或许您想到了,<html>标签的,就是说默认状态下,IE6下html有个overflow:scroll声明,证明很简单,您设置<html>标签overflow:hidden看滚动条是否没有了(我这里证明是没有了)。所以呢,只要在css中些写上:

html{overflow-y:scroll;}

就可以让IE和Firefox(包括chrome)浏览器默认产生滚动条的滚动槽了。

4.关于background的fixed固定定位

Firefox是支持background:fixed定位的,IE6只能说是半支持,好吧,这么说吧,可能不太严谨,就是背景图片固定的效果似乎只在根结点起作用。举个很简单的例子:
先看这段css代码:

body{background:url(../image/404.png) no-repeat fixed center center;}
div{height:2000px;}

HTML部分为:

<body><div></div></body>

其结果是无论IE6还是火狐浏览器下,背景图片都是固定的死死的,不错。但是,一旦<html>标签带着background属性参合进来,事情就要发生转变了。问题代码:

html{background:white;}
body{background:url(../image/404.png) no-repeat fixed center center;}
div{height:2000px;}

结果IE6下,背景不固定了,只看到背景图片随着滚动条上下移动而移动。演示页面

要解决这个问题呢,也是有办法的,就是将fixed属性值转移到html标签上就可以了。即:

html{background:white url(../image/404.png) no-repeat fixed center center;}
div{height:2000px;}

就可以了。

5.关于height:100%;

要想高度百分比起作用,一般来说,要满足两个条件:其一,父标签有高度可寻,就是向上遍历父标签要找到一个定值高度(bodyhtml另外讨论),如果中途有个heightauto或是没有设置height属性,则高度百分比不起作用;其二,标签本身的属性,如果inline属性的标签,如果没有浮动,zoom,或是绝对定位之类属性是不支持百分比高度的,blockinline-block属性可以说是高度百分比起作用的前提条件之一吧。

而这里要讲的是关于body和html的高度百分比显示的。

默认状态下,<body>不是高度100%显示的,不要看<body>定义background属性好像<body>就是满屏显示的,正如上面所推断的,此背景已非<body>之背景。用下面这个一测便知。

body{background:#039; border:50px solid #C00;}

看边框范围是否高度100%显示,答案是否定的。见下图(截自IE6,Firefox浏览器下表现一致):

body默认高度是不100%显示的

body默认高度是不100%显示的

那么<body>是否支持height:100%呢?经过我的测试,IE6支持,Firefox浏览器不支持。

要想让Firefox浏览器也支持<body>height:100%是简单的,就是设置<html>标签height:100%,一旦设置了height:100%则无论哪个浏览器下<body>都支持height:100%了,而<body>内部的容器也可以支持height:100%了。

前段时间看到百度的一道面试题,说什么透明层无论滚动与否都满屏显示,其实就是对<html><body>标签做一番手脚,两者高度100%显示,同时溢出隐藏(overflow:hidden),然后用一个<div>高度100%显示,溢出滚动。而这个透明层就使用绝对定位且与这个<div>平级,高宽100%显示,就可以使得无论怎么滚动这个透明覆盖层都是满屏显示的。这其实也就解决IE6下浮动层固定定位的经典方法。

6.关于html,body的css hack

不知不觉讲了不少了,这就算最后一条吧。

我见过的有关<html><body>标签的hack有这么几个,一个是* html body,一个是*+html,还有个是html > body,以及body:nth-of-type(1)。前者是经典的IE6 css hack,在当前主流浏览器中,就IE6支持,其含义是指在<html>标签外还有一个隐藏的幽灵标签,我也不知道什么东西,反正IE6认得它就行了。*+html据说只有IE7认得它。html > body也据说就IE7认识它,而body:nth-of-type(1)是针对chrome浏览器的hack,意思是说某某标签的第一个元素,因为一个页面就只有一个<body>标签,所以这个肯定会成立的,所以body:nth-of-type(1) div{height:1px;}这个hack就会起作用了。

7. 关于body overflow隐藏 (新增与2019-03-01)

单纯如下body overflow是无法隐藏高度不足一屏的元素的,例如:

body {
    height: 30px;
    overflow: hidden;
}
body > div {
    height: 300px;
    background-color: #cd0000;
}

此时body的子元素div依然保持300px高度的显示,如果想要隐藏,需要设置html的overflow:hidden

此现象出现原因和背景色类似。

  1. 如果html元素没有设置overflow属性,那么body元素的设置等同于设置在html元素上,否则,body元素的overflow属性按照普通元素渲染。
  2. html元素的overflow剪裁高度至少一个屏幕高度。

所以,上面CSS代码,只需要html元素设置任意不是 visible 值的overflow属性,都能触发body元素剪裁div,哪怕html元素的高度很高。

例如:

html {
    height: 400px;
    overflow: scroll;
}

此时body overflow生效。

于是,下面的现象也就理解了,即如果div高度很高,例如3000px,可以看到div元素在一屏高度的地方隐藏了:

body > div {
    height: 3000px;
    background-color: #cd0000;
}

这是因为html元素的overflow生效高度至少1屏。

三、最后的结语

技术无止境,css这东西真是很博大精深,即使我键盘敲了不知多少个小时,还是有些话没有说完。要是再结合JavaScript,demo展开说的话,可能要通宵才能说完。这里就先讲这些,点到为止。关于html和body这两个标签里面蕴含的知识是很多的,我这里全当抛砖引玉,更多的内容还需要您去研究去探索。

(本篇完)

分享到:


发表评论(目前23 条评论)

  1. 南山老幺说道:

    希望有机会张大大可以说一下document.documentElement 与 document.body 的不同和在各种浏览器下的表现。

  2. Todd_hua说道:

    强大

  3. 自带尴尬体说道:

    web新手一枚
    近日做网页发现一个棘手的问题 望哪位大神可以相助

    页面底部的一个显示在和外 该并没有设置margin,padding,float或者position

    把body 和 html的高度设置为100%后 该div 依旧在外面 被挤到下一屏

  4. html > body兼容所有浏览器说道:

    html > body兼容所有浏览器

  5. 林晨说道:

    我在mac的chrome下深入研究了一下window, html, body的overflow属性。得到结论:

    1. 显示元素中,根元素不是html,是window。
    2. window的overflow效果只有hidden和scroll。
    3. html不论overflow设置什么,最终效果均为visible。
    4. html为设置为hidden或scroll时,window的overflow取决于html;设置为visible时,window则取决于body的overflow属性
    5. html为visible时,body不论overflow设置什么,最终效果均为visible。

    原因:
    1. window会首先查找html的overflow属性,如果为scroll或者hidden,则据为己用,html的实际overflow效果则变为visible。
    2. 当html设置visible时,window则会查找body的overflow属性,与html一样,如果为scroll或者hidden,则据为己用,此时body的实际overflow效果变为visible。
    3. 当html和body均设为visible时,window不找他们俩的麻烦了,自己默默设定为scroll。这也是默认的情况。

  6. my说道:

    除了上面提到的body中存在的问题外,还发现一个新的问题,就是body标签对没有任何标签正文的影响,第一行的正文前面总是莫名其妙的多些空白,查资料也找不到原因,纠结!

  7. aochulai说道:

    测试了一下,在ipad的safari里,html和body都设为100%,body会很高,超出window.height,见鬼。

  8. Lisa说道:

    楼住写的很好,很有帮助,转载了。

  9. computer530说道:

    一般来讲,如果在标签中设置background-color属性,这种颜色就会充满整个浏览器窗口;但是如果在标签中也设置了背景色,那么body的背景色就只会填满内容区域。

    这段话是从《css实战手册》摘的,P137最后一段。
    博主关于背景色的实验,我认为是符合客观事实的。

  10. aber2006说道:

    确实博大精深 这篇文章非常好 顶一下

  11. afanti1987说道:

    经过测试,确实如此啊

  12. afanti1987说道:

    给body和html分别设置height:100%后,他们的实际高度是当前窗口的可视高度,而不管body内的内容有多少???

  13. hackxiaozhu说道:

    那个HTML与BODY的背景颜色,为什么在火狐里面 背景色变了 但是中间显示的全是绿色啊??

  14. MoLice说道:

    讨论html/body标签的文章确实很少,难得找到一篇了。
    看完还有个不太确定的问题:html标签是否代表浏览器窗口当前可见部分呢(也即是,html标签的宽高就是浏览器窗口内部可见部分的宽高?)?

  15. 千鸟说道:

    已经很多年没研究这个,当时发现这个问题随手记了下来,但没人关注。到目前为止各种支持都还不好,实用价值并不高,但对我们理解Web构成原理有极大的帮助。其实我相信随着HTML5&CSS3的普及,这块还有深挖的空间,拜托各位专业前段工程师了。
    “正确认识html与body”原文在 http://blog.rexsong.com/?p=183
    并已录入《设计网事》第141页。

  16. 鱼骨头说道:

    细心的实验,只是还是少了些body和html其他公用属性的测试
    IE6占比例越来越少了,不知微软的承诺的强制IE6退出何时能实现。
    hack还是少用,通不过标准测试对优化也是没有好处的。

  17. Zz说道:

    “body但当类似于根结点的结点”应该是“body担当类似于根结点的结点”;
    “而这种便宜造成的体验是不好的”应该是“而这种偏移造成的体验是不好的”;
    我实在是太无聊了,只能挑这种小错误出来,够可耻的吧。
    关于第五点中,百度的面试题,我想了半天也不行。透明层覆盖层是啥意思?也许我该动手试试。。。
    关于第六点中,这几个hack,真的不懂!不知道该什么情况下使用,谁能更详细的指点下?

    多谢分享!

  18. Ryan说道:

    经测试 FF3.6.8 / Chrome6.0 / Safari5 / Opera10 都支持body:nth-of-type(1) 了
    应该是版本更新造成的