专项:宽高自适应 / 伪元素

自适应:元素的大小根据窗口或母元素自动调整。

宽度自适应

<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>
View Code

当鼠标移上去后,二级菜单会弹出来

这看起来很正常,但是如果在菜单后面再加一个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>
View Code

但是我们发现,本来应该展开的二级菜单被隐藏了。这是因为子元素设置了绝对定位,且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>
View Code

第二种方法:

<!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>
View Code
posted @ 2023-11-30 11:09  孤兒教母  阅读(98)  评论(0)    收藏  举报