《架构师重学前端》CSS浮动布局

336 阅读11分钟

什么是浮动

元素脱离文档流,并向左或向右移动,直到它的外边缘碰到包含框或者另一个浮动元素的边缘

只需要记住在元素浮动时,会产生如下变化

  • 脱离文档流
  • 向左或向右移动,直到遇到父元素边缘或者另一个浮动元素的边缘

单个元素浮动

PixPin_2024-06-01_15-32-38

A元素已经浮动了,B元素再浮动

PixPin_2024-06-01_16-01-18

上面的动画简单描述了浮动的变化过程

但是需要注意,在CSS中元素浮动是没有过程的,元素的位置是一瞬间就计算好了的

如何使用浮动

float: [left|right|none];

none是默认值,也就代表了元素没有浮动

left|right代表元素浮动,并且定义元素的浮动方向

<style>
    main {
        border: 3px solid #34495e;
        padding: 3px;
        background-color: #ecf0f1;
    }

    main>div {
        width: 50px;
        height: 50px;
        background-color: #f1c40f;
        float: right;
    }
</style>
<main>
    <div></div>
</main>

image-20240601162013294

浮动的特点

浮动元素变为行内块元素

<style>
    main {
        border: 3px solid #34495e;
        padding: 3px;
        background-color: #ecf0f1;
        width: 300px;
        margin: 100px auto;
    }

    main div,
    main span {
        display: flex;
        text-align: center;
        align-items: center;
        margin-right: 5px;
    }

    div {
        background-color: #f39c12;
        float: left;

        height: 80px;
        width: 80px;
    }

    span {
        background-color: #d35400;
        float: left;
        height: 80px;
        width: 80px;
    }
</style>
<main>
    <div>块浮动元素</div>
    <span>内联浮动元素</span>
</main>

image-20240601170432789

块元素浮动之后不再直接占用一行,内联元素浮动之后可以使用widthheight定义元素大小

个人猜测:元素浮动之后会把元素变为行内快元素,并且会发现后续再为元素设置dispaly时,并不会改变浮动颜色的行内快特性

浮动元素区域包含外边距、边框、内边距、内容


<style>
 
    main {
        border: 10px solid #34495e;
        background-clip: content-box;
        width: 300px;
        height: 100px;
        margin: 100px auto;
    }
    
    div {
        background-color: #f39c12;
        background-clip: content-box;
        float: left;
        height: 80px;
        width: 80px;
        border: 10px solid #bdc3c7;
        margin: 10px;
    }
</style>
<main>
    <div>块浮动元素</div>
</main>

image-20240601171817692

浮动的元素不仅仅包含内容、边框、内边距区域,还包含外边距区域

浮动移动边缘

在定义中指出浮动元素在移动到父元素边缘和其他浮动元素边缘时会停止

那这里的边缘值的是那个区域喃?

<style>
    main {
        border: 20px solid #34495e;
        background-color: #e74c3c;
        background-clip: content-box;
        width: 100px;
        height: 100px;
        margin: 100px auto;
        padding: 20px;
    }

    div {
        background-color: #f39c12;
        background-clip: content-box;
        float: left;
        height: 80px;
        width: 80px;
    }
</style>

<main>
    <div>块浮动元素</div>
</main>

image-20240601172446734

浮动元素移动到父元素的边缘是指的父元素的内容区域

<style>
    main {
        border: 5px solid #34495e;
        background-color: #e74c3c;
        background-clip: content-box;
        width: 300px;
        height: 100px;
        margin: 100px auto;
    }

    div {
        background-color: #f39c12;
        background-clip: content-box;
        float: left;
        height: 80px;
        width: 80px;
        border: 2px solid #9b59b6;
        margin: 5px;
    }

    div {
        float: left;
    }
</style>

<main>
    <div>元素A</div>
    <div>元素B</div>
</main>

浮动元素之间不能层叠

<style>
    main {
        border: 5px solid #34495e;
        background-color: #ecf0f1;
        background-clip: content-box;
        width: 320px;
        padding: 10px;
        margin: 100px auto;
    }

    div {
        background-color: #f39c12;
        background-clip: content-box;
        float: left;
        height: 80px;
        width: 80px;
        border: 2px solid #9b59b6;
        margin: 10px;
    }

    div {
        float: left;
    }
</style>

<main>
    <div>元素A</div>
    <div>元素B</div>
    <div>元素C</div>
    <div>元素D</div>
</main>

image-20240601175454741

如果水平方向剩余的空间不够显示多个浮动元素,浮动元素将向下移动,直到有充足的空间为止。

需要注意的是,就算多个浮动元素来自于不同父级也并不会重叠,这里可以理解为,在文档中只存在一个浮动层

<style>
    main {
        border: 5px solid #34495e;
        background-color: #ecf0f1;
        background-clip: content-box;
        width: 350px;
        padding: 10px;
        margin: 100px auto;
    }

    nav {
        border: 5px solid #e67e22;
        background-color: #e74c3c;
        padding: 10px;
    }

    div {
        background-color: #f39c12;
        background-clip: content-box;
        float: left;
        height: 80px;
        width: 80px;
        border: 2px solid #9b59b6;
        margin: 10px;
    }

    div {
        float: left;
    }
</style>

<main>
    <div>元素A</div>
    <div>元素B</div>
    <nav>
        <div>元素C</div>
        <div>元素D</div>
    </nav>
</main>

image-20240601175317021

元素A元素B的父容器是main元素C元素D的父容器是nav

不难发现就算mainnav重叠,但是内部的浮动元素并不会重叠

父元素高度塌陷

<style>
    main {
        border: 3px solid #34495e;
        padding: 3px;
        background-color: #ecf0f1;
    }

    main>div {
        width: 50px;
        height: 50px;
        background-color: #f1c40f;
        float: right;
    }
</style>
<main>
    <div></div>
</main>

image-20240601180235217

认真观察一开始的动画和例子,会发现:子元素产生浮动时,父元素的高度变为了0,这是元素浮动产生的副作用父元素高度塌陷

其实原理很简单,父元素的高度是由子元素撑开的,但是这里元素产生浮动脱离了文档流,也就无法再撑开父元素,父元素因为感知不到高度,高度便塌陷了

后置的块元素会填补前置浮动元素的文档流位置

<style>
    * {
        padding: 0px;
        margin: 0px;
    }	
    
    main {
        border: 3px solid #34495e;
        padding: 3px;
        background-color: #ecf0f1;
        width: 300px;
        margin: 100px auto;
    }

    main>div {
        width: 80px;
        height: 80px;
        text-align: center;
        line-height: 80px;
        margin-bottom: 5px;
    }

    main>div:nth-child(1) {
        background-color: #f39c12;
    }

    main>div:nth-child(2) {
        background-color: #d35400;
        float: right;
    }

    main>div:nth-child(3) {
        background-color: #c0392b;
    }
</style>
<main>
    <div>前置元素</div>
    <div>浮动元素</div>
    <div>后置元素</div>
</main>

image-20240601164832392

不难发现,浮动元素的前置前置元素并不会收到影响,但是后置元素会填充浮动元素的一开始的位置

浮动元素脱离的文档流,自然也就不占用位置了

就像排队拿药,一个人如果离开了,只会影响他后面的的人位置,并不影响他前面的人位置

但是这里需要注意,这里只是说明了是块级元素

内联元素、行内元素、文本会环绕在浮动元素周围

<style>
    main {
        border: 3px solid #34495e;
        padding: 3px;
        background-color: #ecf0f1;
    }

    main>img {
        float: left;
    }
</style>
<main>
    这是一行测试文本这是一行测试文本这是一行测试文本这
    <img src="https://picsum.photos/id/237/100/100"></img>
    这是一行测试文本这是一行测试文本这是一行测试文本这是一行测试文本这是一行测试文本这是是一行测试文本这是一行测试文本这是一行测试文本
</main>

image-20240601181608817

这里其实也应该分为前置情况与后置情况,前置文本会出现在图片上面和右侧,后置文本会出现在底部和右侧

清除浮动影响

为什么清除浮动影响

根据上面浮动的特点发现,在使用浮动时:

  • 浮动元素会造成父元素高度塌陷浮
  • 浮动元素的后续块元素会填补前置区域

尤其时高度塌陷,这并是我们想要的,所以要清除浮动带来影响

如何清除

末尾添加块元素

<style>
    main {
        border: 6px solid #34495e;
        padding: 6px;
        background-color: #ecf0f1;
    }

    main>div:nth-child(1) {
        width: 80px;
        height: 80px;
        background-color: #f1c40f;
        float: right;
    }

    main>div:nth-child(2) {
        height: 5px;
        background-color: #27ae60;
        clear: both;
    }
</style>
<main>
    <div>浮动元素</div>
    <div></div>
</main>

image-20240601182851769

这里需要一定要给末尾的块元素添加*clear: both;*样式,如果不添加就是这样

image-20240601183729158

可以看到末尾块元素往前填补浮动造成的空缺,父元素也并没有解决高度塌陷问题

先来看一下clear到底是何方神圣:clear: [both|left|right|none];

添加clear能够清除浮动元素对于该元素的影响,但是这里一定要是块元素,行内元素、文本、内敛元素设置该属性无效

left代表清除left浮动元素对于该元素影响,right同理,both则是指的是清除全部浮动元素所带来的影响

好了上面的内容看完了,是不是还是很迷糊,为什么在末尾添加块元素,加上clear就能解决高度塌陷问题?

这里回忆一下,为什么会高度塌陷喃?是因为浮动元素脱离文档流,无法撑开父元素。

首先我们在末尾添加一个块元素,块元素替补浮动元素位置,父元素的高度就是这个块元素的高度,并没有把浮动元素高度算进去,在这个块元素加上clear: both;,就会清除浮动元素所带来的影响,块元素也就不会往前替补浮动元素位置,

如图所示,块元素回到原来自己的位置上,父元素高度也就被撑开了

image-20240601184516351

虽然解决了高度塌陷的问题,但是添加一个元素显示并不好,我们还可以通过伪元素实现这个方案

<style>
    main {
        border: 6px solid #34495e;
        padding: 6px;
        background-color: #ecf0f1;
    }

    main>div {
        width: 80px;
        height: 80px;
        background-color: #f1c40f;
        float: right;

    }
    main::after {
        content: "";
        clear: both;
        display: block;
    }
</style>
<main>
    <div>浮动元素</div>
</main>

image-20240601184914938

效果是一样的,但是这里需要注意

  • 一定使用 display: block;变为块元素
  • 一定使用::after后置伪元素,::before前置并不能清除浮动,这是因为浮动只会对后缀元素造成影响

BFC清除浮动

<style>
    main {
        border: 6px solid #34495e;
        padding: 6px;
        background-color: #ecf0f1;
    }

    main>div {
        width: 80px;
        height: 80px;
        background-color: #f1c40f;
        float: right;

    }

    main {
        overflow: hidden;
    }
</style>
<main>
    <div>浮动元素</div>
</main>

image-20240601194034423

这里就不细讲BFC,这需要知道开启BFC可以防止高度塌陷

shape-outside

shape-outside可以设置浮动元素周边的文字按照什么方式环绕

区域

shape-outside: [content-box|padding-box|border-box|margin-box];

<style>
    * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
    }

    main {
        border: 3px solid #34495e;
        padding: 3px;
        background-color: #ecf0f1;
    }

    div {
        width: 70px;
        height: 70px;
        background-color: #27ae60;
        border: 5px solid #f1c40f;
        margin: 5px;
        padding: 5px;
        float: left;
        shape-outside: content-box;
    }
</style>
<main>
    <div></div>
    这是一行测试文本这是一行测试文本这是一行测试文本这是一行测试文本这是一行测试文本这是是一行测试文本这是一行测试文本这是一行测试文本
</main>

image-20240601215040955

路径

<style>
    * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
    }

    main {
        border: 3px solid #34495e;
        padding: 3px;
        background-color: #ecf0f1;
    }

    div {
        width: 70px;
        height: 70px;
        background-color: #27ae60;
        float: left;
        shape-outside: circle(50% at 50% 50%);
        clip-path: circle(50% at 50% 50%);
    }
</style>
<main>
    <div></div>
    这是一行测试文本这是一行测试文本这是一行测试文本这是一行测试文本这是一行测试文本这是是一行测试文本这是一行测试文本这是一行测试文本
</main>

image-20240601215536942

图片轮廓

<style>
    * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
    }

    main {
        border: 3px solid #34495e;
        padding: 3px;
        background-color: #ecf0f1;
    }

    img {
        width: 100px;
        height: 100px;
        float: left;
        shape-outside: url(favicon.png);
    }
</style>
<main>
    这是一行测试文本这是一行测试文本这是
    <img src="favicon.png" />
    这是一行测试文本这是一行测试文本这是一行测试文本这是一行测试文本这是一行测试文本这是是一行测试文本这是一行测试文本这是一行测试文本
</main>

image-20240601220504613

注意:图片一定是png图片

浮动使用场景

多栏布局

两栏布局

<style>
     * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
    }
    
    main {
        background-color: #ecf0f1;
        box-sizing: border-box;
        font-size: 30px;
    }


    section {
        height: 100vh;
        border: 8px solid #2ecc71;
        margin-left: 200px;
    }

    nav {
        height: 100vh;
        width: 200px;
        border: 8px solid #f1c40f;
        float: left;
    }
</style>
<main>
    <nav>固定区域</nav>
    <section>自适应区域</section>
</main>

image-20240601194143193

三栏布局

<style>
    * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
    }

    main {
        background-color: #ecf0f1;
        box-sizing: border-box;
        font-size: 30px;
    }


    section {
        height: 100vh;
        border: 8px solid #2ecc71;
        margin-left: 200px;
        margin-right: 200px;
    }

    nav {
        height: 100vh;
        width: 200px;
        border: 8px solid #f1c40f;
    }

    nav:nth-of-type(1) {
        float: left;
    }

    nav:nth-of-type(2) {
        float: right;
    }
</style>
<main>
    <nav>固定区域</nav>
    <nav>固定区域</nav>
    <section>自适应区域</section>
</main>

image-20240601194435848

注意点:

  • 需要使用margin-left空出固定区域的位置,要不自适应区域会占用全部区域

image-20240601194827094

  • 固定区域元素标签一定要放在自适应区域区域标签前面,这是因为浮动元素只会影响后置元素

image-20240601195018064

菜单布局

<style>
    * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
    }


    ul {
        overflow: hidden;
    }

    li {
        list-style: none;
        width: 200px;
        float: left;
        border: 8px solid #f1c40f;
        margin: 10px;
    }
</style>
<main>
    <ul>
        <li>元素1</li>
        <li>元素2</li>
        <li>元素3</li>
        <li>元素4</li>
        <li>元素5</li>
    </ul>
</main>

image-20240601195330070

图文混排

image-20240601181608817

前面浮动特点中有介绍

后言

当前CSS布局中,更多是使用flexgrid布局,浮动的唯一作用也就只剩图文混排了