从height:100%不支持聊聊CSS中的“死循环”
source link: https://www.zhangxinxu.com/wordpress/2016/09/talking-about-css-infinite-endless-loop/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
by zhangxinxu from http://www.zhangxinxu.com/wordpress/?p=5666
本文全文转载需购买版权(500¥),摘要引流则免费,具体参见这里
一、从为何height:100%无效的回答说起
大家应该都知道,如果元素没有格式化的高度值,子元素的height
百分比高度是不起作用的,常见的就是height:100%无效,而宽度就没有此问题,所以,新人经常会提出的一个问题是:“为何我的div设置了height:100%却没有效果?”
不知道大家有没有思考过这样一个问题。
然后,有同行就提出了这么一个看似很合理的解释,就是,“假如父元素height:auto且没有其他格式化高度,子元素支持height:100%,则很可能会出现高度死循环”。
什么意思呢?
例如:一个<div>
元素里面有一张vertical-align
为bottom
同时高度为192
像素的图片,此时,该<div>
高度就是192
像素,假设此时,插入一个子元素,高度设为100%
,如果此时height:100%
可以计算,则子元素应该也是192
像素。但是啊但是,我们的父元素height
值是auto
,岂不是现在高度要从原来的192
像素变成384
像素,然后height:100%
的子元素高度又要变成384
像素,父元素高度又双倍……死循环了!
实际上,这种解释是错误的,大家千万别被误导。
证据就是宽度也存在类似场景,但并没有死循环。例如下面这个例子,父元素采用“最大宽度”,然后有个inline-block
子元素宽度100%:
<div class="box"> <img src="1.jpg"> <span class="text">红色背景是父级</span> </div>
.box { display: inline-block; white-space: nowrap; background-color: #cd0000; } .text { display: inline-block; width: 100%; background-color: #34538b; color: #fff; }
如果按照上面“高度死循环”的解释,这里也应该“宽度死循环”,因为后面的inline-block
元素按照我们的理解应该会让父元素的宽度进一步变大。但是,实际上,并没有,宽度范围可能超出你的预期:
父元素的宽度就是图片加文字内容的宽度之和。
眼见为实,您可以狠狠地点击这里:宽度死循环不存在demo
二、为什么不会死循环
这需要了解浏览器渲染的基本原理。首先,先下载文档内容,加载头部的样式资源(如果有),然后按照从上而下,自外而内的顺序渲染DOM内容。套用本例就是,先渲染父元素,后渲染子元素,是有个先后顺序的。因此当渲染到父元素的时候,子元素的width:100%
并没有渲染,所以,宽度就是图片加文字内容的宽度;等渲染到文字这个子元素的时候,父元素宽度已经固定,此时的width:100%
就是已经固定好的父元素的宽度,宽度不够怎么办?溢出就好了,overflow属性就是为此而生的。
同样的道理,如果height
支持任意元素100%
,也是不会死循环的,和宽度类似,静态渲染,一次到位。
这就引申出另外一个问题,父选择器,大家有没有想过如果CSS支持了父选择器,会有什么后果?
后果之一,就是原先的一次渲染被破坏,子元素能够影响父元素的渲染,于是乎,“死循环”开始了,页面渲染会出现各种各样的死循环,现有的很多CSS规则会被颠覆,无限宽度反复渲染等问题就会出现。这就是为什么父选择器呼声那么高,却迟迟不支持的原因。
其实,在CSS中,不会死循环的例子还有很多,我再举一个很有意思的!
三、CSS padding百分比、滚动条与“死循环”
CSS的padding
属性值如果是百分比值,则无论是水平方向还是垂直方向都相对于宽度计算,这就埋下了一个看似会“死循环”的隐患,我们直接看一个例子。
一个div
有如下CSS:
.box { width: 200px; height: 199px; overflow: auto; } .child { padding: 50%; }
容器宽200px
高199px
,子元素padding:50%
,则此时,子元素的宽高应该都是200px
,但是,如果高度是200px
,父元素就会出现滚动条,因为父元素高度199px
不足200px
,但是,父元素出现滚动条,父元素的content box
的宽度就要减去滚动条的宽度,例如window 7下都是17像素,此时,子元素自然宽高也要随之降低,应该是183px
,但是,变成183px
后高度又小于了父元素的199px
,滚动条又会消失,子元素宽度又回到200px
,于是,一个看上去的死循环开始了……
但是,实际上,最终渲染是一次性的,如果父子元素分别给个背景色,则结果如下:
大家就见到了上图所示的“神奇的”一幕,也就是padding:50%
元素的宽度居然不是父元素的content box
宽度。
结果,父元素宽度还是原来的200px
,但是,子元素却是183px
,右侧和下方都留了看上去不能理解的空白间距。
眼见为实,您可以狠狠地点击这里:CSS padding百分比值“死循环”不存在demo
这就是CSS的一次渲染机制造成的效果。
这个例子也进一步证明了:CSS中,如果单纯是静态渲染,是没有死循环这种说说法的!
再如我们CSS :hover
某元素,让其到远离鼠标的地方,按照道理,远离了,应该不执行:hover
渲染要回到原地,实际上,远离了就远离,不会不断执行渲染的。
四、CSS中的无限循环
实际上,CSS中是有与“死循环”相关的关键字的,叫做infinite
,英菲尼迪,无限的意思,出现在CSS3 animation中,可以让动画无限循环,但是,“无限循环”并不等同于“死循环”。
五、结束语
一开始的问题“为何height:100%无效”究竟原因是什么呢?
这个其实可以从规范中找答案,具体是什么呢?我这里卖个关子,大家可以关心我日后的著作,其中会解释“为何height:100%无效”。
OK,最后一句话总结下本文的中心论点:CSS中没有死循环的说法。
感谢阅读,欢迎交流!
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK