关于浮动和定位你想知道的都在这里了

1、何为脱离标准流

首先,我们必须明确html元素可以分为三种:行内元素(inline)、行内块元素(inline-block)和块元素(block)。

所谓标准文档流,指的是行内元素正常情况会在同一行显示(超出容器宽度自然换行),而每一个块元素独占一行,会自上而下排列。

而浮动和定位的共同表现是脱标(脱离标准文档流),接下来我们可以先看一个例子,稍稍感受下脱标的具体表现:

先看一个标准流的正常表现:

<div style="height: 300px;width: 300px;background: gold;;">
    <div style="background: red;width: 100px;height: 100px;"></div>
    <div style="background: darkcyan;width: 100px;height: 100px;"></div>
</div>

接下来,我们给红色的小方块,添加样式{float: left},结果如下:

看出来了吗,绿色方块在红色方块的下面,所谓脱标,可以想象成脱标的元素(红色方块)与其他元素不在同一个平面,而是在标准流的上面一层,既然不在同一层,红色方块原来所在的位置将不再保留,而绿色方块自然会往上走。

2、初识浮动

在上面那段代码的基础上,稍作改动,给绿色方块也加上{float: left},结果如下:

从这张图中,至少可以得出如下两点结论:

a、浮动元素(向左或向右)一直遇到父元素(左上角或右上角)或另一个浮动元素时停止浮动,需要注意的是,如果父元素有padding值,浮动元素无法跨越padding。

b、我们知道div是块元素,块元素独占一行,但图中两个div在同一行显示,所以相当于浮动元素默认会将元素转为行内块元素,注意:我们给<a>这样的行内元素设置float属性,默认也会转为行内块元素。

如上图所示(截图来自京东),浮动最大的用处就是让几个div在同一行显示,由于浮动是以父元素为参考的,所以使用浮动时,记得加上父元素。

接下来,我们将上面的代码稍作改动,去掉父元素的高,再加一个父元素的兄弟元素:

<div style="width: 300px;background: gold;;">
    <div style="background: red;width: 100px;height: 100px;float: left;"></div>
    <div style="background: darkcyan;width: 100px;height: 100px;float: left;"></div>
</div>

<div style="width: 300px;height: 300px;background: pink;"></div>

我们想要的效果是下图这样的(黄色是父元素的背景,粉色贴着父元素的下边缘显示):

而上述代码的实际效果是这样的(父元素不见了,粉色跑到了两个小方块下面,而不是从下边缘显示):

原因是什么呢?我们知道一个div,如果不给它指定高度,则它的高度由它包含的内容撑开,我们上文中说过,浮动元素会脱离标准文档流,相当于这里的父元素不包含内容,所以高度是0,则下面的粉色方块自然会上来。

再强调一次,浮动元素和标准流不在同一个平面!

为了解决此类问题,我们需要清除浮动,所谓清除浮动,就是为了解决由于浮动元素引起的父元素(不设置高度)高度为0从而影响页面布局的问题

这里需要明确的一点是,清除浮动不是必须的,例如,如果我们不需要粉色方块,那这个布局并没有任何问题,清不清除浮动并没有什么影响,所以我们清除浮动,是由于影响了布局。接下来,我们看下常见的清除浮动的几种方法:

a、在最后一个浮动元素后面设置一个空元素,给这个空元素设置属性{clear:both}

clear:both——在元素左右两侧均不允许浮动元素

<div style="width: 300px;background: gold;">
    <div style="background: red;width: 100px;height: 100px;float: left;"></div>
    <div style="background: darkcyan;width: 100px;height: 100px;float: left;"></div>
    <br style="clear: both;" />
</div>

<div style="width: 300px;height: 300px;background: pink;"></div>

这种方法虽然解决了浮动引起的布局问题,但是会引入很多无意义的空标签,现在一般不用这种方式了。

b、伪元素方法清除浮动

<head>
    <meta charset="utf-8">
    <title></title>
    <style>
      .clearfix:after {
        content: ".";
        display: block;
        height: 0;
        clear: both;
        visibility: hidden
      }

      .clearfix {
         *zoom: 1 /*兼容IE6 */
      }
    </style>
  </head>

  <body>
    <div class="clearfix" style="width: 300px;background: gold;">
      <div style="background: red;width: 100px;height: 100px;float: left;"></div>
      <div style="background: darkcyan;width: 100px;height: 100px;float: left;"></div>
    </div>

    <div style="width: 300px;height: 300px;background: pink;"></div>
  </body>

添加clearfix类的本质,其实和第一种方法一样,但是优点是避免了无意义的空标签,这种方法目前最常用。

c、通过overflow清除浮动

<div style="width: 300px;background: gold;overflow: hidden;">
      <div style="background: red;width: 100px;height: 100px;float: left;"></div>
      <div style="background: darkcyan;width: 100px;height: 100px;float: left;"></div>
</div>

<div style="width: 300px;height: 300px;background: pink;"></div>

overflow清除浮动的原理,可以参考这篇文章https://www.jianshu.com/p/7e04ed3f4bea

常用的清除浮动方法就是这三种了,关于浮动还有一个点需要知道下,我们先看下面这个例子:

<div style="width: 300px;background: gold;overflow: hidden;">
      <img src="./timg.jpg" alt="" style="float: left;">
      <img src="./timg (1).jpg" alt="">
</div>

如果你还记得我们第一小节说的关于脱离标准流的现象(不记得的偷偷回去看一眼),那么理论上这个例子,我们应该只能看见第一张图片,因为第一张图片脱标以后不占位置,所以第二张图片会跑上去,但是事实是:

如图,两张图片都显示出来了,原因我们看完另一个例子再说

ps:这里有个与浮动无关的知识点,我们发现父元素底边有一条黄色的缝隙,这是因为文字基线对齐,即使旁边没有文字也是这样对齐,解决这个问题,可以给图片设置属性{vertical-align: middle}

我们把第一小节的例子做一点改动,给绿色小方块加上文字:

<div style="width: 300px;height: 300px;background: gold;">
      <div style="background: red;width: 100px;height: 100px;float: left;">我有浮动</div>
      <div style="background: darkcyan;width: 100px;height: 100px;">我没有浮动</div>
</div>

结果如下:

发现了吗,绿色方块不出所料跑到了红色方块下面,但是文字并没有被挡住,因为文字和图片是不会被浮动元素挡住的,要知道浮动设计的初衷就是为了实现文字环绕图片显示的效果,word里应该都见过这种效果。

3、初识定位

定位是通过position属性实现的,position有四个值:static、relative、absolute和fixed。

position默认的值是static,就是我们正常的文档流。

relative是相对定位,先看一个例子:

<div style="width: 300px;height: 300px;background: gold;">
      <div style="background: red;width: 100px;height: 100px;margin-left: 100px;">我没有相对定位</div>
      <div style="background: darkcyan;width: 100px;height: 100px;margin-left: 100px;">我没有相对定位</div>
</div>

这是一个正常的文档流,结果也是一个正常的结果:

然后,我们给红色方块加上相对定位:

<div style="width: 300px;height: 300px;background: gold;">
      <div style="background: red;width: 100px;height: 100px;margin-left: 100px;position: relative;left: 100px;">我有相对定位</div>
      <div style="background: darkcyan;width: 100px;height: 100px;margin-left: 100px;">我没有相对定位</div>
</div>

注意一下,top、right、bottom和left属性只有定位元素才有(即position非static)

回到这个例子,结果如下:

得出如下两点结论:

a、相对定位是以自己为参照物移动的,和父元素无关

b、绿色方块并没有移上去,所以相对定位是保留原来位置的,并没有脱离文档流,重要的事情默念三遍

相对定位单独使用情况较少,现在只需要记住relative是保留原有位置的。这么短的时间这么近的距离又写了一遍,再记不住的同学过分了啊,自行面壁思过。

接下来,我们看absolute,只需要将上面的例子position的值改为absolute:

<div style="width: 300px;height: 300px;background: gold;">
      <div style="background: red;width: 100px;height: 100px;margin-left: 100px;position: absolute;left: 100px;">我有绝对定位</div>
      <div style="background: darkcyan;width: 100px;height: 100px;margin-left: 100px;">我没有定位</div>
</div>

结果如下:

从这个图可以肯定的一点是,absolute是脱标的,否则绿色方块是不会上去的,那absolute的参照物是谁?我们可以注意到绿色小方块被挡住了一点,那就不是以自己为参照,也不是以父元素为参照,否则应该不会挡住绿色方块,应该正好在绿色方块右边。

接下来我们让父元素居中显示:

<div style="width: 300px;height: 300px;background: gold;margin: auto;">
      <div style="background: red;width: 100px;height: 100px;margin-left: 100px;position: absolute;left: 100px;">我有绝对定位</div>
      <div style="background: darkcyan;width: 100px;height: 100px;margin-left: 100px;">我没有没有定位</div>
</div>

结果是这样的(截图是从浏览器左边缘开始截得):

如果还是看不出来,我们把红色方块的margin-left去掉,left值设为0:

<div style="width: 300px;height: 300px;background: gold;margin: auto;">
      <div style="background: red;width: 100px;height: 100px;position: absolute;left: 0;">我有绝对定位</div>
      <div style="background: darkcyan;width: 100px;height: 100px;margin-left: 100px;">我没有没有定位</div>
</div>

截图依旧是浏览器左边缘截得图:

看出来了吗,这几种情况的absolute是以浏览器窗口为参照的,计算是从浏览器可视窗口左上角计算的,第一张图覆盖绿色的一小部分,是因为body有默认的padding值,覆盖的正好是这个padding的长度。

接下来,我们给父元素设置定位属性:

<div style="width: 300px;height: 300px;margin: auto;background: gold;position: relative;" >
        <div style="width: 100px;height: 100px;background: red;position:absolute;left: 0">我有绝对定位</div>
        <div style="width: 100px;height: 100px;background: darkcyan;">我没有定位</div>
</div>

结果如下:

再次强调,绿色方块上移了,证明绝对定位是脱标的,原来的位置不再保留。

这个看上去貌似是以父元素为参考的,接下来我们给父元素再加一个父元素,原来的父元素的定位属性去掉:

<div style="position: relative;width: 500px;height: 500px;padding: 20px;background: pink;margin: auto;">
        <div style="width: 300px;height: 300px;margin: auto;background: gold;" >
            <div style="width: 100px;height: 100px;background: red;position:absolute;left: 0;top: 0;">我有绝对定位</div>
            <div style="width: 100px;height: 100px;background: darkcyan;">我没有定位           </div>
        </div>
</div>

结果如下:

由图中可以看出,这里的红色方块是以爷爷元素为参考的(提示:设置绝对定位后,最好同时设置left和top值,方便之后调试,默认的位置可能并不是你想象中的)。而且粉色方块设置了padding值,但是红色定位方块是可以跨越padding的,而我们上文中说过float是不能跨越padding的。

如上几个例子,总结一下,定位元素是以离它最近的设置了定位属性(position值只要不是static就行,并非一定是relative)的父级元素为参考的,如果它的父级元素全都没有设置定位属性,则以浏览器可视窗口为参照

接下来我们给父元素也加一个兄弟元素:

<div style="width: 300px;height: 300px;margin: auto;background: gold;position: relative;" >
            <div style="width: 100px;height: 100px;background: red;position:absolute;left: 0;top: 0;">我有绝对定位</div>
            <div style="width: 100px;height: 100px;background: darkcyan;position: absolute;right: 0;bottom: 0;">我也有定位</div>
</div>
<div style="width: 300px;height: 300px;margin: auto;background: pink;"></div>

结果如图:

可以看出如图所示效果正是我们想要的,为什么粉色方块没有上移呢?我们上文中默念三遍的relative是保留位置的,所以90%的情况我们用到绝对定位的时候,给它的父元素设置relative属性。(此处应该默念三遍)

因为如果不给父级元素设置定位属性的话,则绝对定位元素是以浏览器为参考的,若是定位属性设置的不是relative,则不会保留位置,粉色方块会上移,那不是我们想要的效果,当然,还是需要说明的是,如果没有粉色方块,那么你给position值设置为非static值都可以。

但是我还是建议,用到绝对定位的时候,就给父元素设置position: relative(再次默念三遍)。因为实际应用中,很少会出现没有粉色方块的时候,即使真的没有,按照习惯设为relative也没有什么问题。

接下来我们再将这个例子稍作改动:

<div style="width: 300px;height: 300px;margin: auto;background: gold;position: relative;" >
            <div style="width: 100px;height: 100px;background: red;position:absolute;left: 0;top: 0;">我有绝对定位</div>
            <div style="width: 100px;height: 100px;background: darkcyan;position: absolute;left: 50px;top: 50px;">我也有定位</div>
</div>

结果如图:

红色方块被绿色方块盖住了,如果我们想让红色方块在绿色方块上方,只需要给红色方块设置{z-index: 1},z-index属性只有定位元素(position值不为static)才有,默认是0,后面元素会覆盖前面的。

<div style="width: 300px;height: 300px;margin: auto;background: gold;position: relative;" >
            <div style="width: 100px;height: 100px;background: red;position:absolute;left: 0;top: 0;z-index: 1;">我有绝对定位</div>
            <div style="width: 100px;height: 100px;background: darkcyan;position: absolute;left: 50px;top: 50px;">我也有定位</div>
</div>

结果如图:

上面截图来自京东,注意一下左右两边的翻页箭头,右下角的广告以及左下角的翻页小圆点,像这样覆盖到元素(图片)上方的就是典型的用定位做的。

我们上文说过浮动也是脱标的,也会覆盖元素,那我们为什么不用浮动呢?

首先,我们看下左右两侧的小箭头怎么做的,我们假设这俩个箭头透明矩形框的高度是50px,以右侧为例(别忘了给父元素设置relative):

<div style="position: absolute;right: 0;top: 50%;margin-top: -25px;"></div>

注意一下:让一个定位元素垂直居中,只要设置top50%,再将margin-top设为负的自身高度的一半,水平居中只要设置left 50%,再将margin-left设为负的自身宽度的一半,(50%指的是箭头框的边框离顶部50%,所以需要再让他上移高度的一半)

回到正题,假设我们用浮动实现,如果不用css3的calc函数(calc(50% - 25px)),是没有办法垂直居中的,退一步即使箭头勉强用css3完成了,那小圆点呢,float:left之后,你需要计算margin-left和margin-top的值,要知道浮动元素碰到另一个浮动元素会停止浮动,并且不能跨越padding,所以这个值是很难计算的,好不容易计算好了,ui改了设计,那简直是个灾难。定位你则只需要考虑小圆点距离父元素的left和bottom值就可以了。

还有一点,讲浮动的时候,我们说过图片和文字是不会被浮动元素覆盖的,所以图中的例子没法用浮动,如果不是图片,那就如上述所说,是个根本没办法计算的值。

所谓定位定位,就是可以让你使用left、top、right和bottom自由的将一个元素精确的放在任何你想的地方。

上文我们说过,浮动最大的用处是让几个div在同一行显示。同理,你如果用定位实现这个效果,你需要给每个div设置left和top值,如果div大小更改,那你需要重新计算,很困难,用浮动则只需要给每个div设置float:left就搞定了。

我们再看几个使用定位的例子:

购物车上的小数字0

鼠标移上去显示底部的那块黄色的区域

总而言之,像这样覆盖某个元素,或者位置在一个正常div很难实现的地方,或者一块区域,你看过去无法左中右或者上下布局的,那就用定位,定位最大的好处就是它不影响其他元素,你可以很自由的控制它的位置。

absolute到此为止,剩下最后一个fixed属性,fixed和absolute的区别就是fixed始终以浏览器窗口为参照。

如图中所示这些侧边的小标签,无论你缩小窗口或是滚动页面,这些小标签始终在窗口的某个位置,像这样就是fixed实现的了。

浮动和定位是css中无法跳过的两个概念,希望这篇文对这俩个概念还不是很熟悉的小伙伴能有一些帮助。

猜你喜欢

转载自blog.csdn.net/m0_37897013/article/details/81455385