专项:宽高自适应 / 伪元素
自适应:元素的大小根据窗口或母元素自动调整。
宽度自适应
<head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> *{ margin: 0px; padding: 0px; } div{ /* 块级元素,设置width为auto或不写,都是宽度自适应 */ /* 而100%相当于设置宽度,并不是宽度自适应, 再加一个padding属性就能看到区别: - 100%出现了x轴的滚动条, 而auto则是padding越大width越小,不会出现滚动条 */ width: 200px; height: 200px; background-color: aquamarine; /* 宽度自适应一般用于导航栏与通栏 */ } </style> </head> <body> <div></div> </body>
高度自适应:
<head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> *{ padding: 0px; margin: 0px; } .header, .footer{ width: 100%; height: 50px; background-color: cadetblue; } .body{ width: 100%; /* height: 500px; */ /* 设置min-height,当盒子内没内容时,也能有这个最小高度 但同时实现高度自适应,当盒子内容逐渐变多时,高度也逐渐变高 */ min-height: 500px; /* 同样的还有 max-height;min-width;max-width */ background-color: darkcyan; } li{ height: 100px; } </style> </head> <body> <div class="header"> </div> <div class="body"> <ul> <li>111111</li> <li>222222</li> <li>333333</li> <li>444444</li> <li>555555</li> <li>666666</li> <li>777777</li> <li>888888</li> </ul> </div> <div class="footer"> </div> </body>
浮动元素的高度自适应探索
在上面的例子中,可以发现,body类元素的高度随着li标签的内容进行变化。然而,如果我们对子元素添加浮动属性,那么母元素则会发生高度塌陷,即高度直接为0。那么这种情况下,如何使得浮动元素的母元素能够高度自适应呢?
首先,我们拿出之前写过的一个二级菜单的例子:
<head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> *{ margin: 0px; padding: 0px; } .box{ width: 300px; margin: 0 auto; } ul{ list-style: none; } .item{ width: 148px; line-height: 30px; float: left; text-align: center; border: 1px solid blue; background-color: blue; color: white; } .item ul{ display: none; } .item:hover{ background-color: skyblue; font-weight: bold; border: 1px solid skyblue; } .item:hover ul{ background-color: whitesmoke; border: 1px solid whitesmoke; color: grey; display: block; } .item ul li:hover{ color: skyblue; } .body{ height: 100px; background-color: aquamarine; } </style> </head> <body> <ul class="box"> <li class="item">大冰的小屋 <ul> <li>乖,摸摸头</li> <li>阿弥陀佛么么哒</li> <li>好吗好的</li> <li>我不</li> <li>你坏</li> <li>啊</li> </ul> </li> <li class="item">大冰;山东人 <ul> <li>作家</li> <li>主持人</li> <li>民谣歌手</li> <li>老背包客</li> <li>不敬业的酒吧掌柜</li> <li>科班油画画师</li> <li>手鼓艺人</li> <li>业余皮匠</li> <li>业余银匠</li> <li>业余诗人</li> <li>资深西藏拉漂</li> <li>资深丽江混混</li> <li>黄金左脸</li> <li>禅宗临济弟子</li> <li>法国骑士</li> </ul> </li> </ul> </body>
当鼠标移上去后,二级菜单会弹出来

这看起来很正常,但是如果在菜单后面再加一个div,就会出现问题 。例如,我们在box类元素下面再加一个div
<div class="body" style="height: 100px; background-color: aquamarine;"> 1111111 </div>
效果如下:

新加的元素移上去了,而不是待在二级菜单的下面。这就是前文提到的,子元素浮动导致母元素box的高度塌陷为0。在之前的实验中,我们提到过清除浮动的四种方法(https://www.cnblogs.com/liohaunt/articles/17842319.html)。我们尝试用这四种方法解决问题。
1. 为box增加固定高度height属性。

可以发现,body类元素移到二级菜单下方了,但是里面的内容却会跟着展开的菜单一起移动。这是因为我们之前提到过的,浮动并不会脱离文档流,因此会有文字环绕的效果。
2. 在box中再加一个元素设置clear属性为both / 为body设置clear属性为both / 为二级菜单的母元素box设置overflow属性hidden,他们的效果均为:

可以发现,下面的body位置会随着二级菜单的展开而移动,这是因为这三种方法都会导致子元素降到与父元素相同的水平高度,虽然父元素的高度还是为0,但是子元素的高度依然会把下面的元素撑开。
我们想要达到的功能,是body元素在一级菜单的下面,但是当二级菜单展开,body的位置以及内容不会变化。但是以上这四种方法,都无法达到这样的效果。我们刚好学习了元素的位置属性,能不能利用元素的位置属性,来实现这种功能?
我们的思路是:一级菜单与body类元素不脱离文档流,而展开的二级菜单脱离文档流。于是,我们为二级菜单的母元素box设置overflow属性hidden,并且为一级菜单item设置相对定位,为二级菜单设置绝对定位。
<head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> *{ margin: 0px; padding: 0px; } .box{ width: 300px; margin: 0 auto; /* height: 32px; */ overflow: hidden; } ul{ list-style: none; } .item{ width: 148px; line-height: 30px; float: left; text-align: center; border: 1px solid blue; background-color: blue; color: white; position: relative; } .item ul{ display: none; position: absolute; } .item:hover{ background-color: skyblue; font-weight: bold; border: 1px solid skyblue; } .item:hover ul{ background-color: whitesmoke; border: 1px solid whitesmoke; color: grey; display: block; } .item ul li:hover{ color: skyblue; } .body{ height: 100px; background-color: aquamarine; } </style> </head> <body> <ul class="box"> <li class="item">大冰的小屋 <ul> <li>乖,摸摸头</li> <li>阿弥陀佛么么哒</li> <li>好吗好的</li> <li>我不</li> <li>你坏</li> <li>啊</li> </ul> </li> <li class="item">大冰;山东人 <ul> <li>作家</li> <li>主持人</li> <li>民谣歌手</li> <li>老背包客</li> <li>不敬业的酒吧掌柜</li> <li>科班油画画师</li> <li>手鼓艺人</li> <li>业余皮匠</li> <li>业余银匠</li> <li>业余诗人</li> <li>资深西藏拉漂</li> <li>资深丽江混混</li> <li>黄金左脸</li> <li>禅宗临济弟子</li> <li>法国骑士</li> </ul> </li> <!-- <li style="clear: both;"></li> --> </ul> <div class="body" style="height: 100px; background-color: aquamarine;"> 1111111 </div> </body>
但是我们发现,本来应该展开的二级菜单被隐藏了。这是因为子元素设置了绝对定位,且box元素设置了溢出隐藏。因此子元素只能在母元素的范围内进行显示。

(并且子元素设置绝对定位后,它的宽度也跟从前不同了,我想我以后会专门开一个专题研究父子元素的属性继承问题)
难道浮动元素就无法实现这种效果了么?kerwin老师提到的伪元素概念或许能够提供一种解决方法。
伪元素
定义:寄托于某个元素才能存在。利用CSS创建新标签元素,这个新标签元素在HTML文档结构中不显示,但新标签元素又是一个行内元素,所以称为其伪元素。这一类元素选择器就称为伪元素选择器。
例如:
显示效果为:
<head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> div::first-letter { font-size: 50px; } div::first-line{ background-color:cadetblue; } div::before{ /* 伪元素content中的内容,无法在浏览器中选中 */ content: "Hello, Friend! "; } div::after{ content: "GoodBye, Friend!"; } </style> </head> <body> <div>Lorem ipsum dolor sit amet consectetur adipisicing elit. Praesentium hic quisquam necessitatibus harum minima architecto aut nostrum ex quos quis, explicabo incidunt vitae aspernatur pariatur reiciendis in molestias inventore eos.</div> </body>

伪元素content中的内容,无法在浏览器中选中。
回到刚刚的例子,如何利用伪元素实现理想的效果?母相子绝,然后为box设置伪元素after,完整代码如下:
<head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> *{ margin: 0px; padding: 0px; } .box{ width: 300px; margin: 0 auto; } .box::after{ content: ""; clear: both; display: block; } ul{ list-style: none; } .item{ width: 148px; line-height: 30px; float: left; text-align: center; border: 1px solid blue; background-color: blue; color: white; position: relative; } .item ul{ display: none; position: absolute; /* top: 20px; */ } .item:hover{ background-color: skyblue; font-weight: bold; border: 1px solid skyblue; } .item:hover ul{ width: 148px; background-color: whitesmoke; border: 1px solid whitesmoke; color: grey; display: block; } .item ul li:hover{ color: skyblue; } .body{ height: 100px; background-color: aquamarine; } </style> </head> <body> <ul class="box"> <li class="item">大冰的小屋 <ul> <li>乖,摸摸头</li> <li>阿弥陀佛么么哒</li> <li>好吗好的</li> <li>我不</li> <li>你坏</li> <li>啊</li> </ul> </li> <li class="item">大冰;山东人 <ul> <li>作家</li> <li>主持人</li> <li>民谣歌手</li> <li>老背包客</li> <li>不敬业的酒吧掌柜</li> <li>科班油画画师</li> <li>手鼓艺人</li> <li>业余皮匠</li> <li>业余银匠</li> <li>业余诗人</li> <li>资深西藏拉漂</li> <li>资深丽江混混</li> <li>黄金左脸</li> <li>禅宗临济弟子</li> <li>法国骑士</li> </ul> </li> <!-- <li style="clear: both;"></li> --> </ul> <div class="body" style="height: 100px; background-color: aquamarine;"> 1111111 </div> </body>


这样就达到了完美效果。
如果content中有值时,可以这样设置:
.box::after{ content: "aaaaaa"; clear: both; display: block; width: 0; height: 0; visibility: hidden; }
可以隐藏content中的值,并且显示效果与刚刚相同。
display:none; 与 visibility:hidden的区别:
前者是不占位的隐藏。后者是占位隐藏,相当于设置为透明,达到隐藏的效果。
浏览器窗口自适应:
由于设备不同:手机、电脑、平板……不同设备的浏览器窗口也不同,那么,使得元素大小根据浏览器窗口自适应就很有必要。首先我们来看这样一段代码, 它想实现的功能是使top这个类元素能够占满浏览器一半的窗口:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> .top{ width: 100%; height: 50%; background-color: aquamarine; } </style> </head> <body> <div class="top"></div> </body> </html>
即使我们设置了背景颜色,却发现然际显示效果一片空白。打开检查器,发现



显然,这是因为top的母元素body的高度为0,而body的母元素html的高度为0。因此,最终top的高度就为零。height的百分比是相对于父元素的,要实现理想的效果,需要加上这么一段样式,这段代码的含义是:为html与body的高度设置为第一屏高度的百分之百
html,body{ height: 100%; }

两栏布局

假如我们想实现上面的效果,左边宽度200px, 右边宽度将剩下的窗口部分占满。两边的高度占满整个窗口。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> *{ padding: 0; margin: 0; } html,body{ height: 100%; } .left{ float: left; width: 200px; height: 100%; background-color: rgb(44, 44, 77); } .right{ height: 100%; margin-left: 200px; background-color: rgb(160, 160, 160); } </style> </head> <body> <div class="left"></div> <div class="right">111222</div> </body> </html>
效果如下。上面的代码先是给left加了一个左浮动,使得right移了上去。然后为right添加margin-left,实现了两栏布局的效果。

然而再尝试这种效果时,可能会出现几个误区:
1. 为left和right都设置float:left
浮动元素的宽度自适应将根据子元素的宽度来进行调整,也就是说,如果没有子元素,那么此浮动元素的宽度将自适应为0。如果在此基础上为right设置width:100%, 那么效果也只会是right移到left下面去,并且占满窗口整个宽度。
2. 为right的宽度设置为width:100%-200px
这样的计算无法达到效果。right的宽度还是占满整个屏幕
但是,这种写法也是可以达到效果的:
.left{ float: left;; width: 200px; height: 100%; background-color: rgb(44, 44, 77); } .right{ float: left; width: calc(100% - 200px); height: 100%; background-color: rgb(160, 160, 160); }
在上面这个例子中,我们为left和right都设置了浮动属性,然而由于right的宽度使用了calc函数进行设置,因此可以将right看成一个设定了固定宽度的盒子,并且left和right这两个盒子可以严丝合缝地占满同一行。只是right的宽度会随着窗口的大小随之变化而已。
calc函数的使用:
作用:用于动态计算长度值。
需要注意的是,运算符前后都需要保留一个空格;例如width: calc(100% - 200px);
任何长度都可以使用calc函数进行计算
三栏布局
假如我们想实现一种三栏布局:左边宽度固定,右边宽度固定,中间自适应,要如何实现?
第一种方法:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> *{ padding: 0px; margin: 0px; } html,body{ height: 100%; } .left,.right{ float: left; width: 200px; height: 100%; } .left{ background-color: aqua; } .right{ background-color: aqua; } .center{ float: left; width: calc(100% - 400px); height: 100%; background-color: aquamarine; } </style> </head> <body> <div class="left"></div> <div class="center"></div> <div class="right"></div> </body> </html>
第二种方法:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> *{ padding: 0px; margin: 0px; } html,body{ height: 100%; } .left,.right{ width: 200px; height: 100%; } .left{ float: left; background-color: aqua; } .right{ float: right; background-color: aqua; } .center{ width: auto; margin: 0 200px; height: 100%; background-color: aquamarine; } </style> </head> <body> <div class="left"></div> <div class="right"></div> <div class="center"></div> </body> </html>

浙公网安备 33010602011771号