聊一下浮动

我们在排版文字的时候,通常会把开头第一个文字/字母放大处理以达到美观的效果。为了实现这个效果,可能你第一时间想到的是使用 ::first-letter 伪元素:

        p::first-letter{
            font-size: 60px;
        }

这样做确实能实现效果,但是如下图所示,第一行的排版受到第一个字母的内容区影响会变得很奇怪,上下行间距都会变得很宽, 解决的办法可以是设置vertical-align: text-bottom 但是上半行距也会变得很奇怪。  

更好的解决办法是将::first-letter 伪元素设置为浮动元素,这样就可以让文字环绕在其周围,并且不影响行间距

        p::first-letter{
            font-size: 60px;
            float: left;
        }

大多数情况下,浮动被用来作为一种横向布局的方式使用,但是其诞生时被赋予的最初作用其实是"文字环绕"效果, 比如上面的文字环绕大号文字,文字环绕图片等等,只不过当今我们对于网页样式布局的需求从简单的文字图片排版,变成了更加美观,复杂的页面设计,浮动这个最原本的功能也就被忽略了。

由于其本身设计就不是被用来做横向布局的,所以就造成我们在使用浮动布局时需要处理如"塌陷"这样的问题。同时,浮动缺乏弹性,而且容错性很低,很容易在调整一个样式之后造成其他的盒子样式错乱!

如果你想规避浮动在横向布局上的一些天然"缺陷" 可以使用flex grid等更好的方案。

开启浮动&浮动特性

当我们需要一个元素开启浮动时,可以使用属性:

        float: left 左浮动 | right 右浮动 | none 不浮动 ( 默认 )

在浮动开启后,元素会脱离文档流,并且"漂浮"到所在父元素的左/右边缘, 但是不会超出父元素的范围

不论元素是块元素还是行内元素,其在开启浮动之后 display变成block,并且类似于行内块元素的特性,即元素的宽高自动包裹其内容的大小,但是可以通过设置width/height改变其大小

浮动元素特性

1. 脱离文档流, 但是不会超出其父容器的范围

2. 浮动元素会开启BFC,形成一块独立渲染的区域

3. 浮动元素之间不会相互重叠,浮动元素无法盖住其他的浮动元素

4. 浮动元素无法超过前面浮动元素的高度,最多只是高度相同

5. 浮动元素上方的块元素如果在文档流内,则浮动元素无法覆盖在其上面

6. 浮动元素下方文档流中的块元素,可以挤占浮动元素原本的位置,会跑到浮动元素下面

7. 浮动元素周围的文字,会形成环绕的效果,不会跑到浮动元素上面 (浮动的原本功能)

浮动元素的范围就是父元素的范围,在浮动的过程中不会超出这个范围

        .container{
            width: 300px;
            height: 350px;
            background-color: lightgray;
        }

        .box{
            box-sizing: border-box;
            width: 100px;
            height: 100px;
            border: 1px solid black;
            float: left;
        }

浮动元素无法超过其上方块元素的高度,无法覆盖其上方的块元素,如下图所示:

                     

但是我们只需要将浮动元素和块元素在html中的顺序调转,让浮动元素在块元素上方,则浮动元素会覆盖块元素,块元素钻到浮动元素下面了,如图:

                        

同时,由于文字会环绕浮动元素周围,所以div元素的文字会移动到右边,我们检查div元素,会发现其左边的下方其实是被盖住了

                  

其实原理也很好理解,浮动元素由于脱离文档流,在文档流中不占据位置,所以其下方的块元素由于在文档流中就一定会挤上来,而由于浮动元素的层叠水平是要更高的,所以会在上面覆盖住div元素。 

你可以简单的理解为,文档流就是水面,在文档流中的元素都在水中,而浮动是漂浮在水面上的原木,所以会盖住下面文档流中的元素

                   

当然,具体的覆盖顺序,你需要了解一下css中的层叠上下文,层叠水平和层叠顺序,这个后面我会写文章具体讲。

浮动作用机制     

如何实现文字环绕                       

说到浮动,父元素高度塌陷是一个绕不开的话题,那么为什么会出现父元素高度塌陷呢,简单来说就是浮动元素脱离了文档流,其在父元素中不占有位置,那么父元素在计算高度的时候,肯定不会将其计算在其中。

我们在使用浮动横向布局的时候,经常需要使用clear或者bfc开解决这个 “bug” 但是这真的是一个 "bug"么?

我们之所以认为塌陷是个bug 是因为我们背离了浮动设计者设计浮动的本质 - 文字环绕

如果做到文字环绕? 如果你是标准制定者,你会如何实现呢?

如图,一张图片,和一片文字,如果想让文字环绕图片,首先需要让文字和图片相邻,而在文档流中的图片占据高度,无法让下方的文字上来。

所以标准的制定者第一步先 简单粗暴的"破坏文档流" 也就是让图片脱离文档流“飘起来” 这样地下的文字就有可以和图片相邻了

   

脱离文档流之后,文字挤上来,文字和图片就可以相邻了,这也是为什么浮动元素会造成父元素塌陷,因为其为了达到文字环绕的效果,必须先让浮动元素脱离文档流。

所以父元素塌陷这个现象并不是一个 “bug” 而是有意而为之的

如果仅仅让浮动元素脱离文档流,也无法达到文字环绕的效果,如果要达到该效果,更重要的第二部就是,让行框盒子 line-boxes 和 浮动元素 互相不重叠 ,也就是 - 行框盒子和浮动元素的不可重叠性: 行框盒子如果和浮动元素的垂直高度有重叠,则行框盒子在正常定位状态下只会跟随浮动元素,而不会发生重叠!

                                                  红框代表右移的行框盒子 

用上面例子来看,我们使用:first-line 伪元素标记文字的第一行行框盒子,会发现,行框盒子如果和图片重叠,则行框盒子(红色部分) 会跟随在图片的后面,这样就达到了文字环绕的效果!

需要注意,行框盒子,并不是整段文字所在的盒子,而是每一行文字所在的行框盒子,如图,文字所在的盒子是覆盖了图片元素的 是有重叠的!

如果你对行框盒子 行内盒子 这些概念不是很了解,可以去看看讲vertical-align和line-height的文章!

如果你理解了上面的原理,请思考一个问题: 

我们通常使用 clear 或者 BFC来解决父元素高度塌陷的问题,那么如果我干脆给父元素一个高度,这样不就可以直接规避塌陷的问题了吗?

这样确实可行,但是给父元素多少高度呢,如果我让父元素的高度和图片元素高度相等 可以吗?

看下面的例子:

    <style>
        * {
            padding: 0px;
            margin: 0px
        }

        img {
            height: 100px;
            float: left;
        }

        .float {
            float: left;
        }

        .container {
            background-color: lightblue;
            height: 100px;
        }
    </style>
   
    <div class="container">
        <div class="float">
            <img src="../assets/avaters/avater2.webp" />
        </div>
    </div>

设置图片的高度为 100px 父元素的高为100px 这样看上去确实可以,如下图,父元素由于设置了高度也不会出现塌陷的问题 

但是这样做可能会对容器外的元素造成影响, 比如,我在container元素后价一行文字

 <div class="container">
        <div class="float">
            <img src="../assets/avaters/avater2.webp" />
        </div>
    </div>
    <span>我在容器外,但是我也环绕图片了!</span>

其效果如下:

                         

为什么在容器外的span元素,也受影响了呢? 其实看懂了上面环绕原理之后,你大概能猜出来,因为span的行框盒子,和图片发生重叠了! 

但是为什么会重叠,图片被高为100px的容器包裹着啊! 但是其实不是,我们检查元素就可以发现,img外层的float元素高度并不是100px 而是105px

                                         

如果你看过我写的vertical-align和line-height 你就会立刻明白,因为img元素为替换元素,默认是baseline对其,而替换元素的baseline为其底边,所以导致其下方还有部分的空间,我们加一个小些字母xxjjgg就更清晰了!

        

所以,float的高度并不是内部img的高度100px 而是考虑到了极限对齐后的105px,需要解决也很简单,可以给float设置一个高度 100px 或者让图片底部对齐 即可!

                   

浮动锚点和浮动参考 

浮动,是以谁为基准浮动呢,我们看一个例子:

    <style>
        .container {
            background-color: lightgray;
            width: 400px;
        }

        a {
            float: right;
        }
    </style>

    <p class="container">
        "He has been able to put Ghana on the map when it comes to art," she said.
        <a href="xxx">更多..</a>
    </p>

我们在文字中加上一个右侧浮动的a标签,那么这个标签应该在第一行,还是第二行呢?

其效果如图所示,为什么会在第二行呢,这就需要介绍浮动的两个概念 浮动锚点和浮动参考

先说浮动参考,浮动参考指的是浮动元素对齐参考的实体,而这个实体,就是当前浮动元素所在的行框盒子,上述例子,由于换行导致a标签在第二行的行框盒子所在位置,所以其将第二层的行款盒子作为浮动参考,并且向右浮动。

浮动锚点是什么? 当浮动元素夹在块元素之间,这时候不存在行框盒子,此时浮动锚点就发挥作用,浮动锚点在文档流中,可以看成是一个没有margin border padding的空inline元素,其作用就是创建一个浮动参考,这样依旧可以浮动。

为什么浮动无法超过上面的块元素,因为其浮动锚点在块元素下面,浮动参考也就是块元素下面的行框盒子!

消除浮动造成的影响 

 浮动在创造之初就不是拿来做定位的,我们在试用其定位的同时,需要消除掉一些影响

其主要影响就是脱离文档流,导致

  1. 浮动元素的父元素会发生塌陷
  2. 浮动元素下面的块元素会被覆盖

解决办法一般有两种 clear 清除浮动 和 BFC

clear

clear的本意不是清除浮动,浮动并没有被清除,其作用是:

不让设置clear的元素和上方浮动元素相邻

clear可以设置 

  1. left: 不让设置clear的元素和上方左浮动的元素相邻
  2. right: 不让设置clear的元素和上方右浮动的元素相邻
  3. both: 不让设置clear的元素和上方左右浮动元素相邻

需要注意,clear属性只在块元素才生效!

我们通常结合 ::after伪元素在父元素最后,增加一个元素并且设置clear

    <style>
        .float{
            width: 200px;
            height: 200px;
            background-color: lightcoral;
            float: left;
        }

        .container{
            background-color: lightgray;
        }

        .container::after{
            content: '';
            /* clear必须在块元素才生效 */
            display: block;
            clear: both;
        }
    </style>
    <div class="container">
        <div class="float"></div>
    </div>

 使用:after 在container的最后,增加一个子元素,并且设置浮动,需要注意,::after伪元素默认为行内元素,需要设置为块元素!

设置之后,由于最后的元素不能和浮动元素相邻,所以只能在浮动元素后面,自然也就把父元素高度撑起来了,如下图:

一般情况下,both很常用,right left的使用场景不多,我比较愿意将其来理解为 抗左浮动和抗右浮动,其一大作用是可以实现左边多块 宽度固定 右侧自适应的布局

将 头像部分设置成左浮动,绿色部分设置为左抗浮动且左浮动,这样绿色部分不能和头像部分相邻,就只能在下面了,右边元素在文档流中,会挤上去。

 设置父元素为BFC

BFC 可以当成是一块独立的渲染区域,标准规定,在这个独立的渲染区域内的浮动元素的高度,会被计算进BFC元素的高度,同时BFC元素不会和浮动元素重叠。

所以我们可以将外层容器设置 overflow: hidden , display: flow-root 等 将外层容器设置为BFC 从而将内部的浮动元素计算到其高度中,解决塌陷的问题

 

    <style>
        .float{
            height: 200px;
            width: 200px;
            border: 1px solid black;
            background-color: lightgreen;
            float: left;
        }

        .container{
            background-color: lightcoral;
            display: flow-root;
        }
    </style>

    <div class="container">
        <div class="float"></div>
    </div>
    
    <span>HELLOW</span>

 由于container是BFC,所以内部的float元素的高度会被计算在container的高度内,解决了塌陷问题,如下:

BFC 同样可以解决float重叠的问题,看下面例子

    <style>
        .float {
            height: 200px;
            width: 200px;
            border: 1px solid black;
            background-color: lightgreen;
            float: left;
        }

        .hellow {
            background-color: lightcoral;
            display: flow-root;
        }
    </style>
    <div class="float"></div>
    <div class="hellow">HELLOW</div>

给浮动元素下方的HELLO元素设置display: flow-root开启 BFC

此时可以看到 HELLO所在的div元素 并没有被浮动元素覆盖,我们只需要设置其宽度 100% 即可让其在浮动元素下面

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值