接着讲最后一部分啦,咳咳咳,开始上课!
3. visible的block box
这种情况就复杂多了。
overflow为visible的block box(看第23条)是不具备建立block formatting context的能力,这就意味着它位于float box后面时本身的位置是不会变化的,但它的子孙box由于少了block formatting context这层围墙,位置会受到float box的影响。
我们将子孙box分为:inline box( 看第18条), 非inline box的inline-level box( 看第20条), 非visible的block-level box( 看第21条)以及visible的block-level box四种。(ps: float box 及 absolutely positioned box不在考虑范围内,原因请移步 这里。)不同的子孙box会进行怎样的围绕呢?上栗子!
3.1 子孙box为inline box
例一
<html>
<head>
<style type="text/css">
.parent{
width:500px;
height:auto;
margin:20px auto 0;
padding:10px;
line-height:30px;
font-family:"Times New Roman",Georgia,Serif;
border:solid 2px rgba(247, 79, 79, 0.56);
}
.float-child{
width:100px;
height:50px;
float:left;
margin-right:10px;
box-sizing:border-box;
background:rgba(247, 79, 79, 0.56);
}
.normal-child{
width:350px;
height:auto;
border:solid 1px rgba(247, 79, 79, 0.56);
margin-bottom:5px;
padding-left:5px;
}
</style>
</head>
<body>
<div class='parent'>
<div class='float-child'></div>
<div class='normal-child'>
I'm first visible block box after float box.---
<span>I'm grandson whose type is text. I'm grandson whose type is text. I'm grandson whose type is text. </span>
</div>
<div class='normal-child'>I'm second visible block box after float box</div>
<div class='normal-child'>I'm third visible block box after float box</div>
</div>
</body>
</html>
复制代码
效果如下:
可以看出,float box被其后的div中的文字包围,貌似成了第一个div.normal-child的子box,感觉好奇怪的样子。。。不行,我要验证一下!
为类normal-child加上margin:
margin-left:10px;
margin-top:10px复制代码
效果如下:
可以看出,float box还是原来的那个float box ! 没变!放心了~~那之前究竟是怎么回事呢(⊙_⊙)?
先普及一点渲染知识。一份html文档在浏览器上呈现出来有四个步骤:1. 生成DOM树;2. 生成渲染树;3. 渲染树展现到canvas上;4.canvas呈现到浏览器的窗口里。其中,在第3步骤中,普通流中的block-level box是先于float box渲染到canvas上的,这意味着block-level box有可能被float box遮挡住的(事实上,除非我们故意设置,否则block-level box是不会被float box遮挡的)。
对于本例,在第2步骤中,由于float box脱离了普通流(normal flow),div.normal-child在生成box时会假设float box不存在,并确定自己的位置为containing block的左上角。
接下来的第3步骤,div.normal-child会先展现到canvas上,接着float box也会展现到canvas上,问题来了!div.normal-child把它的位置占了!怎么办?float box会直接回到自己原本的位置,而div.normal-child里被float box遮挡的部分会自觉的流动到float box的旁边。我们上图中float box右边的文字部分就是重新流动的那部分。
好了,真相大白了!
接下来看其他情况吧。
3.2 子孙box为非inline box的inline-level box
例二
<html>
<head>
<style type="text/css">
.parent{
width:500px;
height:auto;
margin:20px auto 0;
padding:10px;
line-height:30px;
font-family:"Times New Roman",Georgia,Serif;
border:solid 2px rgba(247, 79, 79, 0.56);
}
.float-child{
width:100px;
height:50px;
float:left;
margin-right:10px;
box-sizing:border-box;
background:rgba(247, 79, 79, 0.56);
}
.normal-child{
width:350px;
height:auto;
border:solid 1px rgba(247, 79, 79, 0.56);
margin-bottom:5px;
padding-left:5px;
}
.normal-child span{
width:300px;
display:inline-block;
}
</style>
</head>
<body>
<div class='parent'>
<div class='float-child'></div>
<div class='normal-child'>
<span>I'm grandson. I'm grandson. I'm grandson. I'm grandson. </span>
</div>
<div class='normal-child'>I'm second visible block box after float box</div>
<div class='normal-child'>I'm third visible block box after float box</div>
</div>
</body>
</html>
复制代码
效果如下:
哎,文字并没有与float box同行耶。。其实道理和例一类似,只不过这次换inline-block了。display 为inline-block的box并不是一个inline box,因为它是以一个整体的形式参与到div.normal-child所建立的inline formatting context中的,这就使得它不能切割成几个部分去与float box并排同处,因而就是上图看到的效果。
3.3 子孙box为非visible的block-level box
例三
<html>
<head>
<style type="text/css">
.parent{
width:500px;
height:auto;
margin:20px auto 0;
padding:10px;
line-height:30px;
font-family:"Times New Roman",Georgia,Serif;
border:solid 2px rgba(247, 79, 79, 0.56);
}
.float-child{
width:100px;
height:50px;
float:left;
margin-right:10px;
box-sizing:border-box;
background:rgba(247, 79, 79, 0.56);
}
.normal-child{
width:350px;
height:auto;
border:solid 1px rgba(247, 79, 79, 0.56);
margin-bottom:5px;
padding-left:5px;
}
.normal-child div{
width:300px;
overflow:auto;
}
</style>
</head>
<body>
<div class='parent'>
<div class='float-child'></div>
<div class='normal-child'>
<div>I'm grandson. I'm grandson. I'm grandson. I'm grandson.
</div>
</div>
<div class='normal-child'>I'm second visible block box after float box</div>
<div class='normal-child'>I'm third visible block box after float box</div>
</div>
</body>
</html>
复制代码
本例只是将例二中的span换成了非visible的block-level box,大家先想想,结果会如何呢?
想好了没?
实际效果如下:
一模一样耶!
道理和例二一样哦。非visible的block-level box会建立一个坚固的block formatting context,因而当float box过来后,右边剩余空间不足,使得它不得不下移。
3.4 子孙box为visible的block-level box
大家看到这,有没有发现这几种情况的分类很熟悉~~~
从上篇开始,就围绕着float box的崇拜者有哪几类来展开,接着,又对崇拜者的子孙有哪几类进行展开。。。。。
有没有觉得这是递归!(不懂的同学请百度)
由于子孙box为visible的block-level box,那么子孙box并不会为自己的子孙建立一个block formatting context,于是我们又回到了子子孙box为inline box,子子孙box为非inline box的inline-level box等四种情况上了。。。
写成总结代码就是酱紫:
var box = float box之后的box;
while(null !== box){
switch(box){
case 'inline box':
文字围绕float box;
box =null;
break;
case '非inline box的inline-level box':
整个inline-level box围绕float box;
box =null;
break;
case '非visible的block-level box':
整个block-level box围绕float box;
box =null;
break;
case 'visible的block-level box':
box =box的子box;
break;
default:
box =null;
break;
}
}
复制代码
上述代码是对之前所有情况的一个总结,其实还有一种情况我们还没有考虑!
混搭
什么是混搭?
就是不同类型的box混在一块,一起去围绕float box。
还是用栗子解释吧!
例四 混搭
<html>
<head>
<style type="text/css">
.parent{
width:500px;
height:auto;
margin:20px auto 0;
padding:10px;
line-height:30px;
font-family:"Times New Roman",Georgia,Serif;
border:solid 2px rgba(247, 79, 79, 0.56);
}
.float-child{
width:100px;
height:350px;
float:left;
margin-right:10px;
box-sizing:border-box;
background:rgba(247, 79, 79, 0.56);
}
.normal-child{
width:auto;
height:auto;
border:solid 1px rgba(247, 79, 79, 0.56);
margin-bottom:5px;
padding-left:5px;
}
.non-visible{
overflow: auto;
}
.inline-block{
display: inline-block;
}
.non-visible,.inline-block{
width:350px;
}
.long-width{
width:450px;
}
</style>
</head>
<body>
<div class='parent'>
<div class='float-child'></div>
<span>I'm inline box after float box. </span>
<div class='inline-block'>I'm not a inline box,but a inline-level box after float box.</div>
<div class='normal-child'>
I'm visible block box after float box.---
<span>I'm inline box in visible block box. </span>
<span class='inline-block'>I'm not a inline box, but a inline-level box which is in visible block box. </span>
<div class='non-visible'>I'm a non-visible block box in a visible block box.</div>
</div>
<div class='normal-child non-visible'>
I'm non-visible block box after float box.---
<span>I'm inline box in non-visible block box. </span>
</div>
<div class='inline-block long-width'>I'm not a inline box,but a long-width inline-level box after float box.</div>
</div>
</body>
</html>
复制代码
float box之后一共有五个box,分别是inline box、非inline box的inline-level box、visible的block-level box、non-visible的block-level box以及宽度很长的非inline box的inline-level box。
其中visible的block-level box的宽度设为auto是为了让子box充分展示他们的特性;non-visible的block-level box及非inline box的inline-level box宽度设为350px,可以足够与float box并排;最后一个加长的非inline box的inline-level box是为了展示整体参与性;float box足够高,可以使得除最后一个box之外,其他box均与其并排。
我们来看看效果。
结果正如我所想的!出现混搭时,你可以将其看作单一类型围绕float box的组合。inline box中的文字会一排一排的去围绕,非inline box的inline-level box及non-visible的block-level box会在宽度允许的情况下与float box并排,visible的block-level box需要视子孙box而定,一旦出现哪个box因为宽度不允许而下移到float box之下,接下来的box均将位于float box之下。
稍微更新一下上面的总结代码,可得到
终极总结
var boxs = float box之后的box;
surroundFloatBox(boxs);
function surroundFloatBox(boxs){
if(0 === boxs.length){
return;
}
for(var i=0;i<boxs.length;i++){
var box = boxs[i];
while(null !== box){
switch(box){
case 'inline box':
文字围绕float box;
box =null;
break;
case '非inline box的inline-level box':
整个inline-level box围绕float box;
box =null;
break;
case '非visible的block-level box':
整个block-level box围绕float box;
box =null;
break;
case 'visible的block-level box':
surroundFloatBox(box的第一层子box);
break;
default:
box =null;
break;
}
}
}
}
复制代码
文字围绕现象总算讲完了,我也可以虚一口气了~
ps: 本文中的例子均是在chrome 上测试。