浮动模型
实际上在CSS中就三大模型,盒子模型、层模型、浮动模型;其中浮动模型最恶心,哈哈!
但是浮动模型语法最简单:就一个属性float:可选值为left、right;但是这个属性可以引发很多的问题
1 <style type="text/css"> 2 *{ 3 margin:0px; 4 padding:0px; 5 } 6 .wrapper{ 7 width:300px; 8 height:300px; 9 border: 1px solid black; 10 } 11 .content{ 12 width:100px; 13 height:100px; 14 background-color:black; 15 } 16 </style> 17 </head> 18 <body> 19 <div class="wrapper"> 20 <div class="content">1</div> 21 <div class="content">2</div> 22 <div class="content">3</div> 23 </div> 24 </body>
代码正常情况下是没问题的,效果如下:
如果我给里面的div都加上浮动float:left,则代码和效果如下所示:
1 <style type="text/css"> 2 *{ 3 margin:0px; 4 padding:0px; 5 } 6 .wrapper{ 7 width:300px; 8 height:300px; 9 border: 1px solid black; 10 } 11 .content{ 12 float:left; 13 color:#fff; 14 width:100px; 15 height:100px; 16 background-color:black; 17 } 18 </style> 19 </head> 20 <body> 21 <div class="wrapper"> 22 <div class="content">1</div> 23 <div class="content">2</div> 24 <div class="content">3</div> 25 </div> 26 </body>
当然如果我们加的CSS样式是float:right,那么效果1、2、3就会倒过来!如下所示:
1 <style type="text/css"> 2 *{ 3 margin:0px; 4 padding:0px; 5 } 6 .wrapper{ 7 width:300px; 8 height:300px; 9 border: 1px solid black; 10 } 11 .content{ 12 float:right; 13 color:#fff; 14 width:100px; 15 height:100px; 16 background-color:black; 17 } 18 </style> 19 </head> 20 <body> 21 <div class="wrapper"> 22 <div class="content">1</div> 23 <div class="content">2</div> 24 <div class="content">3</div> 25 </div> 26 </body>
如果我们多加点div,那么效果还是从右往左写,如下所示:
1 <style type="text/css"> 2 *{ 3 margin:0px; 4 padding:0px; 5 } 6 .wrapper{ 7 width:300px; 8 height:300px; 9 border: 1px solid black; 10 } 11 .content{ 12 float:right; 13 color:#fff; 14 width:100px; 15 height:100px; 16 background-color:black; 17 } 18 </style> 19 </head> 20 <body> 21 <div class="wrapper"> 22 <div class="content">1</div> 23 <div class="content">2</div> 24 <div class="content">3</div> 25 <div class="content">4</div> 26 <div class="content">5</div> 27 <div class="content">6</div> 28 <div class="content">7</div> 29 <div class="content">8</div> 30 <div class="content">9</div> 31 </div> 32 </body>
所以float可以让标签进行战队!从左到右或者从右到左!而且各个元素在战队的时候我们还可以为这些元素设置margin-top,margin-bottom等值,如下所示:
1 <style type="text/css"> 2 *{ 3 margin:0px; 4 padding:0px; 5 } 6 .wrapper{ 7 8 width:350px; 9 height:300px; 10 border: 1px solid black; 11 } 12 .content{ 13 float:left; 14 color:#fff; 15 width:100px; 16 height:100px; 17 background-color:black; 18 margin-left: 10px; 19 margin-bottom: 10px; 20 } 21 </style> 22 </head> 23 <body> 24 <div class="wrapper"> 25 <div class="content">1</div> 26 <div class="content">2</div> 27 <div class="content">3</div> 28 <div class="content">4</div> 29 <div class="content">5</div> 30 <div class="content">6</div> 31 <div class="content">7</div> 32 <div class="content">8</div> 33 <div class="content">9</div> 34 </div> 35 </body>
当父级可以容纳多少个div,一行就占几个,如果我们将外层调成400,不为子div设置margin-left宽度,那么显然一行就可以包含四个div子元素了!
再来看一段代码和效果:
1 <style type="text/css"> 2 *{ 3 margin:0px; 4 padding:0px; 5 } 6 .demo1{ 7 float:left; 8 width:100px; 9 height:100px; 10 background-color: black; 11 opacity:0.5; 12 } 13 .demo2{ 14 width:150px; 15 height:150px; 16 background-color: green; 17 } 18 </style> 19 </head> 20 <body> 21 22 <div class="demo1">1</div> 23 <div class="demo2">2</div> 24 </body>
你会发现当第一个div浮动之后,第二个div跑到上面去了,这和position的效果差不多,但是不能这么理解!当然你也可以这样理解,但是专业说法是:
1.浮动元素产生了浮动流
2.所有产生了浮动流的元素,块级元素看不到他们【浮动元素】,但是产生了BFC的元素和文本类属性的元素及文本都能看到浮动元素,那什么是文本类元素呢?就是凡是带来inline属性的元素都叫文本类元素!
例如:我将上面那段HTML代码中的第二个div去掉,然后换成一个文本,然后我们再看效果,结果如下:
1 <style type="text/css"> 2 *{ 3 margin:0px; 4 padding:0px; 5 } 6 .demo1{ 7 float:left; 8 width:100px; 9 height:100px; 10 background-color: black; 11 opacity:0.5; 12 } 13 14 </style> 15 </head> 16 <body> 17 18 <div class="demo1">1</div> 19 123 20 </body>
你会看到此时,文本123并没有跑到div下面!说明文本可以看到浮动元素!所以浮动元素可不能认为成产生了分层,它只能理解成产生了浮动流!浮动流对后面的元素影响不一而同!
再举个例子:
1 <style type="text/css"> 2 *{ 3 margin:0px; 4 padding:0px; 5 } 6 .demo1{ 7 float:left; 8 width:100px; 9 height:100px; 10 background-color: black; 11 opacity:0.5; 12 } 13 14 </style> 15 </head> 16 <body> 17 18 <div class="demo1">1</div> 19 <img src="1.png"> 20 </body>
效果如下:
这再次证明了只有块级元素看不到浮动元素!最后再举出一个BFC也是看得到浮动元素的例子:
1 <style type="text/css"> 2 *{ 3 margin:0px; 4 padding:0px; 5 } 6 .demo1{ 7 float:left; 8 width:100px; 9 height:100px; 10 background-color: black; 11 opacity:0.5; 12 } 13 .demo2{ 14 display:inline-block; 15 width:100px; 16 height:100px; 17 background-color: green; 18 } 19 20 </style> 21 </head> 22 <body> 23 24 <div class="demo1">1</div> 25 <div class="demo2">2</div> 26 </body>
我们再来探究另一个问题,我们在外层div中嵌套了三个内层子div元素,当我们给内层子div元素设置了浮动之后,会发现父div包不住子div了,这是因为当子div浮动之后,父div是块级元素,块级元素是看不到浮动元素的,所以包不住了!如下代码和效果所示:
1 <style type="text/css"> 2 *{ 3 margin:0px; 4 padding:0px; 5 } 6 .wrapper{ 7 border:1px solid black; 8 } 9 .content{ 10 float:left; 11 width: 100px; 12 height: 100px; 13 background-color: black; 14 color: #fff; 15 } 16 </style> 17 </head> 18 <body> 19 <div class="wrapper"> 20 <div class="content">1</div> 21 <div class="content">2</div> 22 <div class="content">3</div> 23 </div> 24 </body>
那现在我们怎么能让一个父级块元素包住浮动子元素呢?
我们知道浮动元素产生了浮动流,而浮动流干扰了块级元素,让块级元素看不到浮动元素,所以罪魁祸首是浮动流,我们可以试图找找有没有什么办法干掉浮动流,我们可以借助于clear属性,该属性有三个可选值:left、right、both,但是开发的时候我们基本上都是使用both;
我们先来看看正常效果:
1 <style type="text/css"> 2 *{ 3 margin:0px; 4 padding:0px; 5 } 6 .wrapper{ 7 border:1px solid black; 8 } 9 .content{ 10 float:left; 11 width: 100px; 12 height: 100px; 13 background-color: black; 14 color: #fff; 15 } 16 p{ 17 border:10px solid green; 18 } 19 </style> 20 </head> 21 <body> 22 <div class="wrapper"> 23 <div class="content">1</div> 24 <div class="content">2</div> 25 <div class="content">3</div> 26 <p></p> 27 </div> 28 </body>
当我们加了给p标签加了clear属性之后,p标签就能回到他正常该在的位置了,clear属性唯一的功能就是清除浮动流!如下所示:
1 <style type="text/css"> 2 *{ 3 margin:0px; 4 padding:0px; 5 } 6 .wrapper{ 7 border:1px solid black; 8 } 9 .content{ 10 float:left; 11 width: 100px; 12 height: 100px; 13 background-color: black; 14 color: #fff; 15 } 16 p{ 17 border:10px solid green; 18 clear:both; 19 } 20 </style> 21 </head> 22 <body> 23 <div class="wrapper"> 24 <div class="content">1</div> 25 <div class="content">2</div> 26 <div class="content">3</div> 27 <p></p> 28 </div> 29 </body>
当然此时p标签是有宽度,那p标签的border能不能设置为0px呢,设置了0px还好使不好使呢?答案是好使,只要p标签逻辑上在这个位置,那么它就可以将父元素给磴开!如下所示:
1 <style type="text/css"> 2 *{ 3 margin:0px; 4 padding:0px; 5 } 6 .wrapper{ 7 border:1px solid black; 8 } 9 .content{ 10 float:left; 11 width: 100px; 12 height: 100px; 13 background-color: black; 14 color: #fff; 15 } 16 p{ 17 border:0px solid green; 18 clear:both; 19 } 20 </style> 21 </head> 22 <body> 23 <div class="wrapper"> 24 <div class="content">1</div> 25 <div class="content">2</div> 26 <div class="content">3</div> 27 <p></p> 28 </div> 29 </body>
你会看到此时外层div就能包裹住内层div了,而且这种方式也是一劳永逸的,无论你的外层div中有多少个内层div,外层div都可以将内层div给包裹住!
这就是解决包住浮动元素的一个办法!
当然我们还有进一步的解决方案,这种方案倒是可行的,但是我们说HTML是页面的结构,而我们在解决一个bug,一个问题的时候我们不能在结构上乱修改,而像上面我们加了一个p标签,就相当于加了一个结构,而我们使用这个p标签的目的是希望它充当一个功能,解决一个问题,并不是为了结构,所以在正常编程的时候这个p标签结构是不能写在那里的,那咋办呢?
这里我们先来看伪元素的问题,什么是伪元素呢?
伪元素存在于任何一个元素里面,任意一个伪元素里面有两个特殊的伪元素,一个叫after,一个是before,伪元素和元素差不多一起来使用,但是它没有正常元素的结构,伪元素天生就存在,存在于每个标签里面,然后我们可以通过css将这个伪元素选择出来,例如:
<span>真帅</span>
虽然上面我们仅仅看到了span标签,并没有看到伪元素,但是伪元素实际上已经伴随着span标签出生了,我们可以通过css样式:
<style type="text/css"> span::before{ } span::after{ } </style>
通过上边的span::before/after我们就可以将span标签内部的【第一个/最后一个】逻辑元素选择出来,注意我们也可以通过如下:
<style type="text/css"> span::before{ content: "案例"; } span::after{ } </style> </head> <body> <span>真帅</span> </body>
给span标签内部添加内容,注意:伪元素也是属于标签的,before是属于标签的最前面一个元素,而after是属于标签的最后面一个元素,伪元素是天然的存在于元素里面,对于伪元素我们可以拿CSS去选中它,而且可以修改它的样式结构,什么都可以!只不过为啥叫伪元素?是因为它的元素结构是存在的,但是它又没写在HTML里面,所以叫伪元素!就是它可以被CSS操作,但是它没有HTML结构,所以叫伪元素【可以当元素来操作,但是没有元素结构】!当然也可以使用after,如下所示:
<style type="text/css"> span::before{ content: "案例"; } span::after{ content: ",的确,确实是这样"; } </style> </head> <body> <span>真帅</span> </body>
这段代码的效果图如下所示:
不过这里需要明确一点,伪元素天生存在,只不过我们通过CSS将它选中并进行修改!因为伪元素没有确定的结构,所以你很难通过HTML往里面添加内容,所以我们只能通过CSS选择器的content属性往里面添加内容,当然我这个content属性的值也可以啥也不写,当然啥也不写我们也必须加上【content:""】,还要注意伪元素天生是行级元素【inline】,我们可以通过inline-block将其改为块级元素,如下所示:
<style type="text/css"> span::before{ content: ""; width: 100px; height: 100px; background-color: red; display: inline-block; } span::after{ content: ",的确,确实是这样"; } </style> </head> <body> <span>真帅</span> </body>
得到的效果图:
当然对这个伪元素我们也可以定位,如下所示:
<style type="text/css"> span::before{ position:absolute; left:0px; top:100px; content: ""; width: 100px; height: 100px; background-color: red; display: inline-block; } span::after{ content: ",的确,确实是这样"; } </style> </head> <body> <span>真帅</span> </body>
由于使用了绝对定位,所以就浮动到第二层了,将原来的位置空出来了,然后下面的元素就上来了!注意:伪元素天生是行级元素,如果想要给它设置长、高啥的,那么必须给它改为块级元素!那么讲这个伪元素和我们要讲的知识有啥联系呢,为啥要先讲这个伪元素讲了呢?回到刚才那个问题,我们要在元素的最底部加入一个元素来清除浮动,但是如果真加上一个p元素就破坏了页面的结构了,所以在元素最后加一个元素我们这里用伪元素最合适,我不改变页面的结构,但是又在后面加一个元素,不要忘了清除元素的浮动【clear属性,但是clear属性必须要求当前元素为块级元素】,所以这里使用了伪元素代替原来的p元素,如下所示:
<style type="text/css"> .wrapper::after{ content:""; clear:both; display:block; } .wrapper{ border:1px solid black; } .content{ float:left; width: 100px; height: 100px; background-color: black; color: #fff; } </style> </head> <body> <div class="wrapper"> <div class="content">1</div> <div class="content">2</div> <div class="content">3</div> </div> </body>
效果图如下:
如上就是利用伪元素清除浮动的一个例子!而且以后我们写父级元素包住子级元素,子级元素是浮动元素,我们只能这么来写【利用伪元素清除浮动】!
当然除了这种方式之外,我们还可以父级元素变为BFC元素,这样父级元素就可以看到浮动子元素了!如下代码所示:
<style type="text/css"> *{ margin:0px; padding:0px; } .wrapper{ position:absolute; border:2px solid red; } .content{ float:left; width: 100px; height: 100px; background-color: black; color: #fff; } </style> </head> <body> <div class="wrapper"> <div class="content">1</div> <div class="content">2</div> <div class="content">3</div> </div> </body>
效果图如下所示:
虽然现在也可以包住子级浮动元素,但是说实话凡是使用了position:absolute或者float:left/right属性的元素,系统都会将其转换为inline-block元素【高级知识】,如果变成了行级块元素,那么长和高由内容来决定!
举例说明1:
<style type="text/css"> *{ margin:0px; padding:0px; } span{ height:100px; width: 100px; background-color: red; } </style> </head> <body> <span>123</span> </body>
效果图如下所示:
如果是加入了position:absolute,那么span就会变成行内块元素,如下代码及效果图所示:
<style type="text/css"> *{ margin:0px; padding:0px; } span{ position:absolute; height:100px; width: 100px; background-color: red; } </style> </head> <body> <span>123</span> </body>