搞定一个CSS知识点——浮动

351 阅读11分钟

CSS的学习之路如此漫长,需要掌握的无非就是五种布局方式:浮动布局、定位布局、弹性布局、网格布局、表格布局。日常我们见到的文字环绕效果、三栏式布局等页面都是怎么实现的呢?别担心,今天我们就从浮动布局开始get我们的知识点。

css的元素分类

在css的html标签中,元素一般分为三类:

1.块级元素 : 在html标签中<div>、 <p>、<h1>、<form>、<ul> 、 <li>就是块级元素,在css中设置display:block的标签也显示为块级元素。块级元素的特点是默认占据一整行,可以设置宽高。

2.行内元素:在html标签中常见的<span>、<a>、<label>、 <strong> 、<em>就是典型的行内元素,在css中设置了display: inline也在页面中显示成行内元素。行内元素的特点是可以同行显示,不可以设置宽高

3.行内块级元素:在html标签中常见的<input>就是行内块级元素,在css中设置display:inline-block的标签在页面中显示为行内块级元素。行内块级元素的特点是可以同行显示,可以设置宽高。

浮动特点

1. 文字环绕效果

首先,我们写一个页面,页面中我们使用<img>标签放一张图片并且设置了宽高分别为100px,使用<p>标签放一段文字。

image.png 如图所示,因为我们的<p>标签是块级元素,所以文字会在图片的下方显示,这就导致了页面的不美观。那如何让文字和图片在一行显示呢?你会第一时间想到使用display设置<img><p>为行内块级元素或者行内元素,但是行吗?当然不行。我们会发现不论设置成哪一个,文字都没有办法去到图片的同一行。

但是,如果我们把<img>设置样式为float: left,文字却能实现环绕效果。

image.png

如上图所示,就是浮动的作用,实现了文字环绕效果。

2. 脱离正常文档流

随着互联网的发展,浮动布局就被运用的越来越广泛,不止有文字环绕效果会使用它,其他地方也会有。例如:我们在页面中放置3个宽高一致的div容器,分别设置不同的背景色代码如下:

<style>
        div{
            width: 100px;
            height: 100px;
       }
        .item1{
            background-color: rgb(106, 235, 235);
        }
        .item2{
            background-color:blueviolet;
        }
        .item3{
            background-color: rgb(43, 208, 139);
        }
    </style>
</head>
<body>
    <!-- 不换行盒子就黏在一起了 -->
    <div class="item1"></div>
    <div class="item2"></div>
    <div class="item3"></div>
</body>

首先,我们想让是三个div全部去到同一行,我们可以都设置div为行内块元素,就可以去到同一行。

image.png

如图,三个div去到了同一行。但是有个问题:在浏览器中,会把我们的代码换行当成一个空字符处理,在设置div为行内块级元素后会导致容器之间有一个字符间隙。所以为了避免这个间隙,我们可以在html/body/*{ }上设置font-size:0,再在子容器上设置font-size的值。(这儿我就不展示效果了,你们可以自己试试喔~)

第二种方法,就是浮动。

我们试了:发现如果设置了item1容器向左浮动,item2好像不见了,被item1盖在下面了?

image.png

如果设置了item2容器向左浮动,item3好像不见了,被item2盖在下面了?

image.png

如果设置了item3容器向左浮动,好像没变化,

image.png

为什么浮动会让一些元素重叠?其实是因为:元素会遵从正常的文档流——从上往下、从左往右的顺序渲染在页面中,而浮动会让元素脱离正常的文档流。

如果让原来item1向左脱离文档流,会在最左边;但是item2和item3依然在正常的文档流中从上往下排列,item2取代item1的位置,所以在item1的下面重叠了;同理,item2向左脱离文档流,但是item1和item3依然在正常的文档流中从上往下排列,所以是item3取代原来item2的位置,但是在item2的下面重叠了;而item3向左脱离文档流,但是item1和item2依然在正常的文档流中从上往下排列,所以和不设置的效果没有区别。

所以也可以这么理解,浮动的元素会从自己开始的正常文档流脱离,块级元素可以去到同一行,对自己之前的文档流不受影响。要想三个去到同一行,就得三个都脱离文档流,否则就会有元素的重叠或者换行,如图为均向左浮动的结果。

image.png

3. 浮动中的margin

在父容器中,子容器如果想要水平居中,如果子容器为块级元素,我们可以设置其样式为margin:0 auto,即子容器上下外边距为0,左右自适应就可以居中了。如图是item1设置的结果。

image.png

如果子容器为非块级元素,margin:0 auto已经失效我们可以设置父容器的样式为text-align: center,也会在父容器中水平居中。如图为三个非块级元素的居中效果。

image.png

那在块级元素均浮动的情况下,我想要水平居中margin:0 auto能生效吗?

image.png

看上图是均浮动情况下,item1使用了margin:0 auto,但是并没有失效。所以在元素在浮动后,可以使用margin 但是不能使用margin:0 auto

4. 设置行内元素的宽高

我们在一开始聊到行内元素的特点就是不可以设置宽高,但是浮动的行内元素不一样。我们设置三个item容器都是行内元素后,宽高定义了100px,但是容器的大小不受设置影响,均由内部文字的大小决定容器的宽高,如图。

image.png

但是我们给行内元素均浮动后,行内的高度显示成100px了,如图。

image.png

由此,我们可以得出,浮动后的行内元素可以设置宽高

清除浮动

我们先给个代码,在页面显示。

<style>
    .left{
        width: 400px;
        height: 100px;
        background: #c21919;
        /* float: left; */
    }
    .right{
        width: 300px;
        height: 100px;
        background: #2e3ed0;
        /* float: right; */
    }
    img{
        display: block;
        margin: 0 auto;
    }
    .search{
        text-align: center;
    }
</style>
<body>
    <div class="page">
        <div class="head">
            <div class="left"></div>
            <div class="right"></div>
        </div>
        <div class="search">
            <img src="https://logo800.cn/uploads/logoxinshang/58/logo800_16491626185785714.png" alt="" width="200" height="200">
            <input type="text">
        </div>
    </div>
</body>

image.png

在正常文档流时,left和right容器不在同一行,并且百度图片和搜索框都水平居中了;现在我们想要left和right容器在同一行,一个在左,一个在右。我们首先想到给两个容器添加float:left。

image.png

我们知道父元素head容器的高度不会被浮动的元素所影响,所以head是没有高度的,如图在浏览器的检查中可以看到,head的高度是0。如果设计师给到我们的设计稿是head和search容器之间有间距的,这时候就出现问题了。其实我们对search容器加margin-top可以解决,但是当页面出现多个元素浮动的话,我们是不方便处理它带来的影响的。这个时候我们就会用到清除浮动的方法来消除影响。

  • 清除浮动的办法
    1. 直接设置父容器的高度
    2. 在浮动元素最末尾增加一个子容器,在子容器上做清除浮动。
    3. 伪元素 XXX::after{ content: "hello"; clear: both; display: block; }。
    4. 为后面被影响的元素添加清除浮动

OK,为了能更好的理解这些办法,让我们举个例子:

<style>
    *{
        margin: 0;
        padding: 0;
    }
    li{
       /* display: inline-block;  */
       float: left;
    }
    ul li{
        list-style: none;
        width: 200px;
        height: 100px;
    }
    li:nth-child(1){
        background: rgba(22, 105, 187, 0.467);
    }
    li:nth-child(2){
        background: rgba(41, 146, 27, 0.467);
    }
    li:nth-child(3){
        background: rgba(202, 202, 47, 0.467);
    }
    .text{
        width: 50px;
        height: 200px;
        background: #b6131388;
    }
</style>
<body>
    <div class="container">
        <ul class='ul_clear'>
            <li>1</li>
            <li>2</li>
            <li>3</li>
        </ul>
        <div class="text">Hello World</div>
    </div>

image.png

如图,我们的代码得到的页面效果中,子容器li上添加了float属性,使得父容器ul没有高度,所以与text容器重叠在一起了。

所以清除这种重叠效果的第一种方法,写死父容器ul的高度。我们让父容器与的内外边距是0,所以可以设置父容器ul高度等于子容器li高度100px,这样与text容器不会重叠,如图所示。

image.png

但是,在这种办法是不适合大多数的页面布局的。所以我们的css为清除浮动做了量身定制的一个方法clear: left/right/both,在左侧不允许浮动元素/在右侧不允许浮动元素/在左右侧不允许浮动元素。于是我们就有了第二种办法,在浮动元素li最末尾增加一个子容器div,在该容器上做清除浮动。代码和效果如下图所示。

image.png

对于程序员说,肯定是代码越少越好啊哈哈哈~所以第三种方法,写一个伪元素,::before是在元素之前,::after是在元素之后。但是伪元素我们不定位它不显示,我们需要强行声明为块级元素,再在它上面添加清除浮动效果,代码如下:

<style>
 .ul_clear::after{
        content: '';
        clear: both;
        display: block;
    } 
 </style>

最后一种方法,为后面被影响的元素直接添加清除浮动,这是最简单的方法,我猜你也懂了。

BFC容器

其实,清除浮动的负面影响还有一个方式,这里我们作为一个大点单独讲解:什么是BFC?哪些属性可以创建BFC?BFC有什么特点?

1. BFC的意义

BFC容器,是Block Formatting Context的英文缩写,也叫块级格式化上下文。Formatting context 是 W3C CSS2.1 规范中的一个概念。它是页面中的一块渲染区域,并且有一套渲染规则,它决定了其子元素将如何定位,以及和其他元素的关系和相互作用。BFC是一个独立的布局环境,其中的元素布局是不受外界的影响

我们来看一个bug,给到我们一串代码,分析一下。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<style>
    *{
        margin: 0;
        padding: 0;
    }
    .parent{
        width: 100vw;
        height: 400px;
        background-color: blueviolet;
        /* margin把body带下来了 */
        margin-top: 100px;
    }
    .child{
        width: 100vw;
        height: 200px;
        background-color: antiquewhite;
        /* 父子容器margin重叠了 */
        margin-top:50px ; 
    }
</style>
<body>
    <div class="parent">
        <div class="child"></div>
    </div>
</body>
</html>

image.png

我们在浏览器找到父容器和子容器的的margin-top,分别如下两图:

image.png

image.png

父子容器的margin-top竟然重叠了?本来我们认为的结果应该是这样的。

image.png

这就让我们需要解决的父子容器的margin重叠问题,这是创建BFC容器的意义

2. 创建BFC

那哪些属性可以创建BFC呢?我们还是使用第三个大点所用的示例的代码,我们设置父容器ul和子容器li均左浮动,会发生什么?

image.png

从图中我们会发现,ul竟然有高度了,按道理ul有高度了text应该被挤下去,但是ul整体tuoli了文档流,就导致了与text的重叠。我们能够发现,其实有浮动的元素,创建了一个独立空间,按照着float后的规则布局,并且不受外界元素的影响。所以我们可以知道,其实浮动可以创建BFC容器。

我们再试试定位,定位也是脱离文档流的一种方式。我们设置了子容器li均左浮动,父容器ul设置position:absolute,看看效果。

image.png

耶~一样的,定位也可以让父容器ul有高度了,也是与text容器重叠了。其实和float类似的道理,所以定位也可以创建一个BFC容器

还有吗?当我们把块级元素变成行内块级时,会使得块级元素去到同一行,

image.png

一样的道理,为什么块级会去到一行,因为行内块级形成了自己的一套规则,但是它不会让元素脱离文档流,所以display也可以生成一个BFC容器;除设置行内块外,里面特别的一种是display:table-cell——表格布局,它里面以table开头的属性,大多数都可以;还有弹性布局flex

最后一种,overflow:hidden/auto/overly/scroll也可以。

总结创建BFC的方法:

  1. float:right || left;
  2. position:absplute || fixed;
  3. display:inline-XXX || flex || grid || table || table-XXX;
  4. overflow:hidden || auto || overlay || scroll;

3. BFC的特征

  • BFC容器是让处于BFC内部的元素与外部的元素相互隔离,使外部的元素的定位不会相互影响。
  • 解决外边距重叠问题。
  • BFC容器在计算高度时,会把浮动元素的高度也计算在内。

今天的知识点就聊到这儿啦~内容有点多,期待下次与你分享!喜欢就点个赞喔! 爱你们

期待.jpg