css - float 【4000+字总结】

1,575 阅读13分钟

浮动的原始意义是什么?

www.zhangxinxu.com/wordpress/2… 目前流行采用浮动方法实现的无论是分栏布局,还是列表排列我们都可以用其他一些CSS属性(不考虑table)代替实现,唯一一个实现不了的就是“文字环绕图片”,我是想不出来能有什么方法可以让文字环绕图片显示。好,这个替代不了的作用才是float真正的意义所在。

浮动出现的意义其实只是用来让文字环绕图片而已,仅此而已

www.w3.org/TR/CSS22/vi… The most interesting characteristic of a float (or "floated" or "floating" box) is that content may flow along its side (or be prohibited from doing so by the 'clear' property). Content flows down the right side of a left-floated box and down the left side of a right-floated box.


英语不太好,意译翻译一下:
float最有趣的特征是内容会沿着浮动侧流动【展现】(或者通过clear属性禁止浮动效果)。内容跟随左浮动元素的右侧布局。跟随右浮动元素的左侧布局。

这里阐述的观点和张鑫旭的观点有一定关联性。核心还是浮动元素之后,内容会有一种包裹的效果。

float用法

CSS允许浮动任何元素,从图像到段落再到列表,所有的元素都可以浮动。在css中,这种行为使用属性float实现。
float 属性定义元素在哪个方向浮动。以往这个属性总应用于图像,使文本围绕在图像周围,不过在 CSS 中,任何元都可以浮动。浮动元素会生成一个块级框,而不论它本身是何种元素。如果浮动非替换元素,则要指定一个明确的宽度;否则,它们会尽可能地窄。

注释:假如在一行之上只有极少的空间可供浮动元素,那么这个元素会跳至下一行,这个过程会持续到某一行拥有足够的空间为止。

描述
left元素向左浮动。
right元素向右浮动。
none默认值。元素不浮动,并会显示在其在文本中出现的位置。
inherit规定应该从父元素继承 float 属性的值。



浮动的本质

浮动的包裹性

举例:宽度自适应的按钮

<!DOCTYPE html>  
<html lang="en-US">  
    <head>  
        <meta charset="UTF-8">  
        <title>Document</title>  
        <style type="text/css">
        .btn1 {
          display:inline-block; 
          background: green; 
          padding-left:3px; 
          color:#000; 
          font-size:12px; 
          text-decoration:none;
        }

        .btn1 cite, .btn2 cite {
          display:block; 
          line-height:26px; 
          padding:0 13px 0 10px; 
          background: yellow; 
        }

        .btn2 {
          float: left; 
          background: green; 
          padding-left:3px; 
          color:#000; 
          font-size:12px; 
          text-decoration:none;
        }
        </style>
    </head>  
    <body>
        <a href="javascript:" class="btn1"><cite>测试float & inline-block</cite></a>
        <br /><br />
        <a href="javascript:" class="btn2"><cite>测试float & inline-block</cite></a>
    </body>  
</html> 

image.png

www.zhangxinxu.com/wordpress/2… 上面这个例子旨在说明浮动属性(无论是左浮动还是右浮动)某种意义上而言与display:inline-block属性的作用是一模一样的,所以类似于display:block; float:left;的CSS代码超过95%的情况是没有道理的(display:block是多余的)。float无法等同于display:inline-block,其中原因之一就是浮动的方向性,display:inline-block仅仅一个水平排列方向,就是从左往右,而float可以从右往左排列,这就是两者的差异。


实际上,display:block; float:left; 基本上是没有道理的。


inline-block 有什么特性?

inline,block,inline-block特征区别

  • inline:
    • 使元素变成行内元素,拥有行内元素的特性,即可以与其他行内元素共享一行,不会独占一行.
    • 不能更改元素的height,width的值,大小由内容撑开.
    • 可以使用padding,margin的left和right产生边距效果,但是top和bottom就不行.
  • block:
    • 使元素变成块级元素,独占一行,在不设置自己的宽度的情况下,块级元素会默认填满父级元素的宽度.
    • 能够改变元素的height,width的值.
    • 可以设置padding,margin的各个属性值,top,left,bottom,right都能够产生边距效果.
  • inline-block:
    • 结合了inline与block的一些特点,结合了上述inline的第1个特点和block的第2,3个特点.
    • 用通俗的话讲,就是不独占一行的块级元素。

inline-block布局和float布局的区别

<!DOCTYPE html>  
<html lang="en-US">  
    <head>  
      <meta charset="UTF-8">  
      <title>Document</title>  
      <style type="text/css">
        .parent, .parent1 {
          width: 340px;
          border: 1px solid red;
          overflow: hidden;
        }

        .parent div {
          display: inline-block;
        }

        .parent1 div {
          float: left
        }

        .child1 {
          width: 100px;
          height: 100px;
          line-height: 40px;
          background: yellow;
        }

        .child2 {
          width: 100px;
          height: 200px;
          line-height: 100px;
          background: green;
        }
      </style>
  </head>  
  <body>
    <div class='parent'>
      <div class='child1'>
        child1
      </div><div class='child2'>
        child2
      </div>
      text
      <div class='child1'>
        child1
      </div><div class='child2'>
        child2
      </div><div class='child1'>
        child1
      </div>
    </div>
    <br />
    <div class='parent1'>
      <div class='child1'>
        child1
      </div>
      <div class='child2'>
        child2
      </div>
      text
      <div class='child1'>
        child1
      </div>
      <div class='child2'>
        child2
      </div>
      <div class='child1'>
        child1
      </div>
    </div>
  </body>  
</html> 

image.png

  • inline-block不会脱离文档流,float会脱离文档流,具体看下面。
  • float会脱离文档流,出现父元素高度塌陷,需要通过overflow处理
  • inline-block元素布局会形成匿名块盒,盒的范围如下图,并且当前行内元素排列按照baseline为基准排列,而且html标签书写存在换行的时候,会造成子元素中间存在空隙。 image.png
  • float元素不会生成匿名块盒,生成BFC【块容器盒】,彼此之间互不影响。
  • float布局单方向的排列,不会越过方向上的已经存在的浮动元素。例如上面最后的child1的元素。不会排列到倒数第二个child2元素的前面的空白区域。
  • inline-block布局和float布局在一些特定条件下可以达到相同的效果。子元素高度相同,baseline相同
  • 对于布局处理,尽可能使用inline-block布局或者flex布局。除非需要文字环绕的情况下在使用浮动布局。

前置回顾:说明display:block; float:left; 没道理的原因

juejin.cn/post/694508…

  1. 如果’display’值为’none’,同时不设置’position’和’float’,那么该元素不生成框。
  2. 否则,如果’positon’值为’absolute’或’fixed’,即框为绝对定位,’float’的计算值为’none’,并且’display’根据下表设置。那么该框的位置由’top’,’right’,’bottom’,’left’和框的包含块决定。
  3. 否则,如果’float’的值不为’none’,那么该框会浮动,’display’根据下表设置。
  4. 否则,如果该元素为根元素,’display’根据下表设置。
  5. 否则,剩余的’display’属性值与指定值相同。
Specified valueComputed value
inline-tabletable
inline, table-row-group, table-column, table-column-group, table-header-group, table-footer-group, table-row, table-cell, table-caption, inline-blockblock
otherssame as specified


规则如第三条:元素添加float属性,内部表现计算的时候基本是按照 block[这里指的是块级盒,块容器盒,块盒]


浮动的破坏性

浮动的破坏性说的是,破坏当前行的line boxes。

<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
      .block-level-box {
        /*float: left;*/
      }
    </style>

  </head>

  <body>
    <span>inline text</span>
    <img class="block-level-box" src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Ffile02.16sucai.com%2Fd%2Ffile%2F2015%2F0107%2F1daf01ab3e6dc38c15efa15c4a6f7a40.jpg&refer=http%3A%2F%2Ffile02.16sucai.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1619604060&t=58546a123e31a1c096d02cbc1ee72c4a" />
    <span>inline text</span>

  </body>
</html>

image.png

修改代码,给图片添加float属性
image.png假设浮动没有破坏inline boxes,那么虽然图片会靠左显示,但是其会与文字形成新的高度包络线(同类聚合),且只能与一行文字形成line box,无法实现文字环绕效果,所以浮动破坏inline boxes是必须的。

上面第一张图,可以发现。图片和两段文本是处于同一个line-box下,大家具有同一个内容高度。当文本放不下的时候,内容会到下一行。当时当我们将图片设置float属性的时候,此时图片已经破坏原有的line-boxes。文本自己形成自己的line-boxes。

这里可以参考:www.w3.org/TR/CSS22/vi… 这里的例子说明:

Text flows normally up to the inner box, which is pulled out of the flow and floated to the right margin (its 'width' has been assigned explicitly). Line boxes to the left of the float are shortened, and the document's remaining text flows into them.

这里的例子也是在说明,line-box会变短


浮动有没有脱离文档流

浮动元素是脱离文档流【normal flow】的,但是没有脱离文本流【text flow】。
关于文本流的概念,在css2.2中在举例说明float的时候提到了这个概念,但是没有深入说明。
google搜到了一篇文档 HTML document flow and text flow

  • 文档流: 相对于盒子模型
  • 文本流: 相对于文本

元素浮动之后,会让它跳出文档流,也就是说当它后面还有元素时,其他元素会无视它所占据了的区域,直接在它身下布局。但是文字却会认同浮动元素所占据的区域,围绕它布局,也就是没有跳出文本流。但是绝对定位后,不仅元素盒子会跳出文档流,文字也会出文本流。那么后面元素的文本就不会在认同它的区域位置,会直接在它后面布局,不会在环绕。

浮动元素和绝对定位对比

www.programmersought.com/article/332…

(1) Floating will make the element separate from the document flow, but will not separate from the text flow, because the text content of other boxes still occupy the position when calculating the layout.

(2) Absolute positioning will make the element out of the document flow, but also from the text flow,

翻译一下:

  • 元素设置float属性之后,将会跳出文档流,但是不会跳出文本流。因为其他框在计算布局的时候仍然会计算float元素的内容部分
  • 绝对定位会跳出文档流,也会跳出文本流。



浮动详细内幕

www.w3.org/TR/CSS22/vi…

  1. The left outer edge of a left-floating box may not be to the left of the left edge of its containing block. An analogous rule holds for right-floating elements.
  2. If the current box is left-floating, and there are any left-floating boxes generated by elements earlier in the source document, then for each such earlier box, either the left outer edge of the current box must be to the right of the right outer edge of the earlier box, or its top must be lower than the bottom of the earlier box. Analogous rules hold for right-floating boxes.
  3. The right outer edge of a left-floating box may not be to the right of the left outer edge of any right-floating box that is next to it. Analogous rules hold for right-floating elements.
  4. A floating box's outer top may not be higher than the top of its containing block. When the float occurs between two collapsing margins, the float is positioned as if it had an otherwise empty anonymous block parent taking part in the flow. The position of such a parent is defined by the rules in the section on margin collapsing.
  5. The outer top of a floating box may not be higher than the outer top of any block or floated box generated by an element earlier in the source document.
  6. The outer top of an element's floating box may not be higher than the top of any line-box containing a box generated by an element earlier in the source document.
  7. A left-floating box that has another left-floating box to its left may not have its right outer edge to the right of its containing block's right edge. (Loosely: a left float may not stick out at the right edge, unless it is already as far to the left as possible.) An analogous rule holds for right-floating elements.
  8. A floating box must be placed as high as possible.
  9. A left-floating box must be put as far to the left as possible, a right-floating box as far to the right as possible. A higher position is preferred over one that is further to the left/right.

  1. 浮动元素的左(或右)外边界不能超出其包含块的左(或右)内边界
  2. 如果源文档中一个浮动元素之前出现另一个元素,浮动元素的顶端不能比包含该元素所生成框的顶端要高。
  3. 左浮动元素的右外边界不会在其右边右浮动元素的左外边界的右边。右浮动元素的左外边界也不会在其左边任何左浮动元素的右外边界的左边
  4. 浮动框的外部顶部不得高于其包含的块的顶部。
  5. 浮动元素的顶端不能比之前所有浮动元素或块级元素的顶端更高
  6. 元素的浮动框的外部顶部不得高于包含由源文档中前面的元素生成的框的任何行框的顶部。
  7. 浮动元素的左(或右)外边界必须是源文档中之前出现的左浮动(或右浮动)元素的右(左)外边界。除非后出现浮动元素的顶端在先出现浮动元素的底端下面
  8. 浮动元素必须尽可能高地放置
  9. 左浮动元素必须向左尽可能远,右浮动元素则必须向右尽可能远。位置越高,就会向右或向左浮动得越远

浮动元素的包含块

根据上面前置回顾可以看到,float元素表现为block,个人认为是一个块容器盒。那该元素的包含块根据规则

juejin.cn/post/694508… 规则2: 如果元素的position属性值为releative或者static。包含块则是最近的块级盒子或者建立格式上下文祖先元素

浮动元素的包含块是其最近的块级祖先元素。这里的意思是什么呢?(我的理解)浮动元素是不利于页面布局的,所以我们需要建立一个浮动的范围去规范其作用边界。找到块级祖先元素,我们可以利用块级祖先元素进行布局处理,然后在当前块级元素中在进行浮动的相关操作。

规则1: 浮动元素的左(或右)外边界不能超出其包含块的左(或右)内边界

<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
      .block-level-box {
        float: left;
      }

      div {
        height: 600px;
        background: green;
        margin-top: 40px;
        padding-top: 40px;
        padding-left: 30px;
      }
    </style>

  </head>

  <body>
    <div>
      <img class="block-level-box" src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Ffile02.16sucai.com%2Fd%2Ffile%2F2015%2F0107%2F1daf01ab3e6dc38c15efa15c4a6f7a40.jpg&refer=http%3A%2F%2Ffile02.16sucai.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1619604060&t=58546a123e31a1c096d02cbc1ee72c4a" />
    </div>

  </body>
</html>

image.png
浮动元素的包含块区域为content区域

规则2:如果源文档中一个浮动元素之前出现另一个元素,浮动元素的顶端不能比包含该元素所生成框的顶端要高。

<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
      .block-level-box {
        float: left;
        margin-top: 20px;
      }

      .block-level-box-1 {
        float: left;
      }

      img {
        max-width: 200px;
      }

      div {
        height: 600px;
        background: green;
        margin-top: 40px;
        padding-top: 40px;
        padding-left: 30px;
      }
    </style>

  </head>

  <body>
    <div>
      <span class="block-level-box">
        float span
      </span>
      <img class="block-level-box" src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Ffile02.16sucai.com%2Fd%2Ffile%2F2015%2F0107%2F1daf01ab3e6dc38c15efa15c4a6f7a40.jpg&refer=http%3A%2F%2Ffile02.16sucai.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1619604060&t=58546a123e31a1c096d02cbc1ee72c4a" />
      <img class="block-level-box-1" src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Ffile02.16sucai.com%2Fd%2Ffile%2F2015%2F0107%2F1daf01ab3e6dc38c15efa15c4a6f7a40.jpg&refer=http%3A%2F%2Ffile02.16sucai.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1619604060&t=58546a123e31a1c096d02cbc1ee72c4a" />
    </div>
  </body>
</html>

image.png
这里因为前两个浮动元素添加了margin-top,因为margin-top也是属于块级盒子的范畴,所以第三个盒子的上边缘会高出20px。

规则3: 左浮动元素的右外边界不会在其右边右浮动元素的左外边界的右边。右浮动元素的左外边界也不会在其左边任何左浮动元素的右外边界的左边

<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
      .block-level-box {
        float: left;
        margin-top: 20px;
      }

      .block-level-box-1 {
        float: right;
      }

      img {
        max-width: 200px;
      }

      div {
        height: 600px;
        background: green;
        margin-top: 40px;
        padding-top: 40px;
        padding-left: 30px;
      }
    </style>
  </head>

  <body>
    <div>
      <img class="block-level-box" src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Ffile02.16sucai.com%2Fd%2Ffile%2F2015%2F0107%2F1daf01ab3e6dc38c15efa15c4a6f7a40.jpg&refer=http%3A%2F%2Ffile02.16sucai.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1619604060&t=58546a123e31a1c096d02cbc1ee72c4a" />
      <img class="block-level-box-1" src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Ffile02.16sucai.com%2Fd%2Ffile%2F2015%2F0107%2F1daf01ab3e6dc38c15efa15c4a6f7a40.jpg&refer=http%3A%2F%2Ffile02.16sucai.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1619604060&t=58546a123e31a1c096d02cbc1ee72c4a" />
    </div>

  </body>
</html>

屏幕录制2021-05-12 上午12.28.17.2021-05-12 00_29_27.gif


负外边距

负外边距会导致浮动元素移动到包含块的外面。

<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
      .block-level-box {
        float: left;
        margin-top: -50px;
      }

      img {
        max-width: 200px;
      }

      div {
        height: 600px;
        background: green;
        margin-top: 40px;
        padding-top: 40px;
        padding-left: 30px;
        clear: both;
      }
    </style>
  </head>

  <body>
    <div>
      <img class="block-level-box" src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Ffile02.16sucai.com%2Fd%2Ffile%2F2015%2F0107%2F1daf01ab3e6dc38c15efa15c4a6f7a40.jpg&refer=http%3A%2F%2Ffile02.16sucai.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1619604060&t=58546a123e31a1c096d02cbc1ee72c4a" />
    </div>
  </body>
</html>

image.png



浮动重叠规则

如果一个浮动元素和正常留中的内容发生重叠会发生什么呢?规则如下

  • 行内框与一个浮动元素重叠时,其边框背景和内容都在浮动元素之上显示。
  • 块框与一个浮动元素重叠时,其边框和背景在该浮动元素之下显示,而内容在浮动元素之上显示。
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
      .main {
          width: 800px;
          height: 300px;
          border: 5px solid red;
          margin: 20px;
          background-color: green;
      }
       
      img {
          width: 200px;
          height: 100px;
      }
       
      .left {
          margin: 10px -15px 10px 10px;
          float: left;
      }
       
      strong {
          background-color: yellow;
          border: 1px gray solid;
          padding: 5px;
      }
       
      .footer {
          width: 300px;
          height: 200px;
          background: gray;
      }
    </style>
  </head>

  <body>
    <div class="main"> 
      <img class="left" src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Ffile02.16sucai.com%2Fd%2Ffile%2F2015%2F0107%2F1daf01ab3e6dc38c15efa15c4a6f7a40.jpg&refer=http%3A%2F%2Ffile02.16sucai.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1619604060&t=58546a123e31a1c096d02cbc1ee72c4a" />         
      <strong>向内元素</strong>
    </div>
  </body>
</html>

image.png

  • 第一个规则,可能这个不太好测试,但是借助负外边距还是可以测试出来的。我们可以看到文本内容相关的内容,边框和内边距都已经是在浮动元素的上面。
  • 第二个规则图中可以看到背景灰色的div是在图片的下面。


清浮动

父元素加上 overflow: hidden

​因为overflow.hidden会触发BFC。

BFC的意思是,我这个元素里面的子孙元素,不会影响外部元素的布局。但浮动本身会造成行内宽度的压缩,出现文字环绕效果。如此一来,浮动元素越宽,当然行内的可容纳的文字数就越少,文字的行数就会增加,文档流高度也就增加。这样,就影响了其外部元素的布局。

所以从BFC的本意来说,必须给浮动元素撑出高度,使得后续的元素无法跟浮动元素共享同一水平位置,这也是BFC的特性,大家有兴趣的看一下html的高度会涵盖float属性(PS: html是BFC元素)。

浮动元素后面加上block元素并且带有clear属性

both属性之后的元素会忽略上一个元素的浮动声明而不去补之前的空缺

clear

  • 适用于:块级元素继承性:无
  • none:允许两边都可以有浮动对象
  • both:不允许有浮动对象
  • left:不允许左边有浮动对象
  • right:不允许右边有浮动对象

:after 清除

.parent {
  zoom: 1;
}
.parent:after {
  display: block;
  content: '';
  clear: both;
  visibility: hidden;
}



汇总

猜测(PS: 基准可能是block box层)是添加出一个匿名块级元素包含float元素,但是第一个原因的是将这个匿名块级元素包含于BFC元素,第二个原因的是将匿名块级元素包含于当前的父级元素。

参照:

www.zhangxinxu.com/wordpress/2…
www.w3.org/TR/CSS22/vi…
www.programmersought.com/article/332…