CSS包含3种基本的布局模型,用英文概括为:Flow、Layer 和 Float。在网页中,元素有三种布局模型:
1、 流动模型(Flow) 2、 浮动模型 (Float) 3、 层模型(Layer)。

1、流动模型

流动模型也就是标准文档流。从上到下、从左到右,输出文档内容,由块级元素和行级元素组成。流动(Flow)是默认的网页布局模式。也就是说网页在默认状态下的 HTML 网页元素都是根据流动模型来分布网页内容的。

流动布局模型具有2个比较典型的特征:

第一点,块状元素都会在所处的包含元素内自上而下按顺序垂直延伸分布,因为在默认状态下,块状元素的宽度都为100%。实际上,块状元素都会以行的形式占据位置。

第二点,在流动模型下,内联元素都会在所处的包含元素内从左到右水平分布显示。(内联元素可不像块状元素这么霸道独占一行)。

注:

块状元素包含<div>、<p>、<h1>...<h6>、<ol>、<ul>、<dl>、<table>、<address>、<blockquote> 、<form>等

内联元素包含<a>、<span>、<br>、<i>、<em>、<strong>、<label>、<q>、<var>、<cite>、<code>等

内联块状元素包含<img>、<input>等

块级元素特点:
1、每个块级元素都从新的一行开始,并且其后的元素也另起一行。(真霸道,一个块级元素独占一行)

2、元素的高度、宽度、行高以及顶和底边距都可设置。

3、元素宽度在不设置的情况下,是它本身父容器的100%(和父元素的宽度一致),除非设定一个宽度。

内联元素特点:

1、和其他元素都在一行上;

2、元素的高度、宽度及顶部和底部边距不可设置;

3、元素的宽度就是它包含的文字或图片的宽度,不可改变。

内联块状元素(inline-block)

内联块状元素是可调宽高但是又不会独占一行,代码display:inline-block就是将元素设置为内联块状元素。<img>、<input>标签就是这种内联块状标签。

1、和其他元素都在一行上;

2、元素的高度、宽度、行高以及顶和底边距都可设置。

标准文档流的模型如下例子:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>标准文档流</title>
</head>
<style type="text/css" media="screen">
    #div1{
        height: 200px;
        width: 100%;
        background-color: red;
    }
    #a1{
        background-color: green;
        width: 100px;  /*注意这里虽然设置了宽高,但是实际上并没有生效*/
        height:  100px;
    }
    #a2{
        background-color: yellow;
    }
    #div2{
        height: 200px;
        width:100%;
        background-color: black;
    }
    #img1{
        width: 100px; /*注意这里设置了宽高,实际效果宽高也出来了,说明是块状内联元素*/
        height:  100px;
        background-color: pink;
    }
    #img2{
        width: 100px;
        height:  100px;
        background-color: purple;
    }
</style>
<body>
    <div id="div1">

    </div>
    <a id = "a1" href="#" title="">###############</a>
    <a id = "a2" href="#" title="">==============</a>
    <div id="div2">

    </div>
    <img id = "img1" src="#" alt="">
    <img id = "img2" src="#" alt="">
</body>
</html>

2、浮动模型

块状元素这么霸道都是独占一行,如果现在我们想让两个块状元素并排显示,怎么办呢?不用担心,接下去提到的浮动模型便可以解决这个问题。

在W3C的中文官方网站是这样定义:

浮动的框可以向左或向右移动,直到它的外边缘碰到包含框或另一个浮动框的边框为止。 由于浮动框不在文档的普通流中,所以==文档的普通流中的块框==表现得就像浮动框不存在一样。

那么从这个定义来说浮动我们至少可以获取如下信息:

  1. 浮动框的停止位置
  2. 浮动框所处文档的立体位置
  3. 浮动框周边的元素表现形式

那么我们一一说明上面三点影响布局的实际效果。

正常的标准文档流在第一小节的例子中已经举例了,那么现在我们将上面的例子稍微改一下:

#a1{
        background-color: green;
        width: 100px;
        height:  100px;
        float: left;
    }

将id为a1的标签设置左浮动,那么根据上面浮动的定义这个a1的浮动框应该会是啥样的?其周边的元素又会出现什么变化呢?

我们对比一下浮动前和浮动后的变化:

标准文档流.png

浮动之后:

浮动1.png

找茬的时间到了,你们找到几处不同的地方?

  1. a1这个框变大了;
  2. a2这个框和a1靠得更近了;

目前只有这两处变化,那么这两处变化的原因是啥呢?

  1. 问题1的原因其实很简单,这个原因在刚才的浮动定义中并没有提及,不过在别的资料中会讲到的:那就是设置浮动的标签如果之前是内联元素或者是块状内联元素,那么设置之后就通通成为块状元素。因此a1这个框变为块状元素后大小便是可以调节的了。
  2. 在不浮动的时候a1框和a2框有一个小小的间隙,但是浮动之后该间隙就消失了。那么我们首先想知道为什么不浮动的时候什么都没设置为什么会有一个间隙呢?这个问题的原因是因为内联元素默认会有水平空隙,造成水平空隙的原因可以是:
    • 行内元素之间的“换行符”产生间距
    • 行内元素之间使用“tab(制表符)”产生间距
    • 行内元素之间使用“空格”产生间距 解决办法可以参考://toutiao.com/i6199751211212554754/。 那么为什么设置浮动之后间隙就消失了呢?

答案当然是因为浮动。那么根据浮动的概念我们知道浮动框也就是a1会脱离文档流,这样从文档结构上来说a1的就不再是与a2在同一层次上,所以此时在标准文档流中的内联元素就只有a2了,所以内联元素之间的间距就不成立了,所以二者之间的距离就会消失掉。

这时大家肯定会很奇怪:为什么a1不在标准文档流中,那么a2不是应该靠到最左边的边缘上吗?而且概念也定义了相邻元素会将浮动框当做没有一样的呀?

是的,这个问题其实不仅涉及到浮动框,而且还牵扯到行内框等概念。但是有一点需要记住的是概念中强调能够将浮动框当做不存在的情况只能是块框(记住只是一个框,也就是轮廓,不包含里面的内容),也就是块状元素。那么内联元素或者块框里面的文本等又是如何处理的呢?

解释这个问题之前我们需要掌握CSS中行框和行内框的概念。也就是说如果块框中包含了文本,那么文本自己本身会出现一个所谓的行框。

参考这篇文章//www.cnblogs.com/rainman/archive/2011/08/05/2128068.html。

那么我们就可以这样理解为什么a2框并不会左移到边缘处:

  • 首先a2这个框本身是内联元素,也就不是块框,因此不会将a1框当做不存在
  • 其次a2框内部包含的是行内框,也就是文本内容,它的本身也不可能将a1框当做不存在。

如果a2框是个块框,那么效果又会是怎么样呢?修改上面的代码一下:

...
    #a1{
        background-color: green;
        width: 100px;
        height:  100px;
        /*float: left;*/
    }
    #a2{
        background-color: yellow;
        width: 200px;
        height: 200px;
    }
...

    <a id = "a1" href="#" title="">###############</a>
    <div id = "a2">===============</div>
...

此时a1框不浮动:

修改代码demo1.png

接下去让a1框浮动起来

修改代码浮动起来.png

好的,效果如我们所预见的一样:

  • a2这个块框将a1浮动框当做不存在的一样,往上移动顶住div1框
  • a2这个块框内部的行内框无法将a1浮动框当做不存在一样,继续保持在原有位置上不动。

总之掌握浮动无非就记住三个要点:

  • 浮动框脱离文档流
  • 只有块框(不包含里面的内容)才会表现得浮动框不存在一样
  • 内联元素至始至终都是认为浮动框就在自己的旁边,并且占用自己原有的位置

如果你往文档排版的方向想象也就知道为什么浮动要这样设计:就是为了实现文本环绕;

注意

在W3C中文官网中没有提到的还有一个很重要的知识点:

浮动框定位的宗旨是,在其左、上、右外边界不溢出包含块边界的情况下,尽量的靠上、靠左("float:left")或靠右("float:right")放置,但是不能高于它前面生成的块框、浮动框和行框的顶边,并且不能与其他浮动元素重叠。

--引用自www.w3help.org/zh-cn/kb/011/

所以有这种效果:

浮动2.png

2.1、清除浮动

在非IE浏览器(如Firefox)下,当容器的高度为auto,且容器的内容中有浮动(float为left或right)的元素,在这种情况下,容器的高度不能自动伸长以适应内容的高度,使得内容溢出到容器外面而影响(甚至破坏)布局的现象。这个现象叫浮动溢出或者高度塌陷,为了防止这个现象的出现而进行的CSS处理,就叫CSS清除浮动。

例子程序:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>标准文档流</title>
</head>
<style type="text/css" media="screen">
    *{margin:0;padding:0}
    #wrapper{
        background-color: red;
        border:  1px solid yellow;
    }
    #div1{
        height: 200px;
        width:200px;
        background-color: green;
        float: left;
    }
    #div2{
        height: 200px;
        width:500px;
        background-color: black;
        float: right;
    }
    #div3{
        height: 500px;
        width:100%;
        background-color: purple;
        clear: both;
    }

</style>
<body>
    <div id="wrapper">
        <div id="div1">

        </div>
        <div id="div2">

        </div>
        <div id="div3">

        </div>
    </div>
</body>
</html>

在div3没有设置清除浮动之前,父元素wrapper的高度只有div3的高度。但是设置div3清除浮动的时候,div3的位置就不会再受到div2浮动框的影响了。

除了此种方法可以清除浮动之外,还有好多种方法的,这里只推荐使用伪元素清除浮动,也是使用clear:both的方法,但是并没有多添加标签:

#wrapper:after{
        content: "";
        clear: both;
        visibility: hidden;
        display: block;
        height:0;
    }

3、层模型

什么是层布局模型?层布局模型就像是图像软件PhotoShop中非常流行的图层编辑功能一样,每个图层能够精确定位操作,但在网页设计领域,由于网页大小的活动性,层布局没能受到热捧。但是在网页上局部使用层布局还是有其方便之处的。 CSS定义了一组定位(positioning)属性来支持层布局模型。

层模型有三种形式:

  1. 绝对定位
  2. 相对定位
  3. 固定定位

3.1、绝对定位

如果想为元素设置层模型中的绝对定位,需要设置position:absolute(表示绝对定位),这条语句的作用将元素从文档流中拖出来(也就是脱离标准文档流),然后使用left、right、top、bottom属性相对于其最接近的一个具有==定位属性==的父包含块进行绝对定位。如果不存在这样的包含块,则相对于body元素,即相对于浏览器窗口

但是如果不设置偏移量的时候又是不一样的,它会始终位于父元素的左上角,而不以某些已经具有定位属性的父包含块来定位!

根据上面所说的我们可以有下面的一个demo来说明:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>absolutely position</title>
  <style type="text/css" media="screen">
    #div1{
        width: 200px;
        height: 100px;
        background-color: gray;
    }
    #wrapper1{
      position: relative;
      width: 400px;
      height:  400px;
      background-color: green;
    }
    #wrapper2{
      width: 200px;
      height:  200px;
      padding:50px;
      background-color: red;
    }
    #div2{
      width:100px;
      height: 100px;
      background-color: blue;
      position: absolute;
    }
  </style>
</head>
<body>
  <div id = "div1">This is first container</div>
  <div id = "wrapper1">
    <div id = "wrapper2">
      <div id = "div2">This is second container</div>
    </div>
  </div>
</body>
</html>

该demo的效果如下:

绝对定位demo1.png 效果中的解释看上去应该是很清楚了,主要是区分父元素和父包含块的含义。如果一旦设置了偏移属性,效果应该是这样的:

#div2{
      width:100px;
      height: 100px;
      background-color: blue;
      position: absolute;
      left: 100px;
      top: 100px;
    }

绝对定位demo2.png

当元素设置了绝对定位,但是没有设置宽度,那么该元素的大小也会随着里面的内容变化而变化,这个类似于浮动。

3.2、相对定位

如果想为元素设置层模型中的相对定位,需要设置position:relative, 它通过left、right、top、bottom属性确定元素在正常文档流中的偏移位置。相对定位完成的过程是首先按static(float)方式生成一个元素(并且元素像层一样浮动了起来),然后相对于以前的位置移动,移动的方向和幅度由left、right、top、bottom属性确定,偏移前的位置保留不动。也就是说元素随即拥有偏移属性和z-index属性。

OK! 概念讲到这里我们需要注意相对定位的几个要点:

  1. 相对定位的完成过程:生成一个元素
  2. 偏移的参照物是以前的位置;
  3. 偏移前的位置保留不动

如何解释上面三点呢?我用一句更加通俗的话来解释:元素设置相对定位的时候会复制出一个一模一样的元素然后相对于之前的位置进行偏移,然后将之前的位置“隐藏”,这样相邻的元素就不会发生任何改变。

效果看下面的代码就可以知道了:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>absolutely position</title>
  <style type="text/css" media="screen">
    #div1{
        width: 200px;
        height: 100px;
        background-color: gray;
        position: relative;
        top: 200px;
        left: 20px;
    }
    #div2{
      width:100px;
      height: 100px;
      background-color: blue;
    }
  </style>
</head>
<body>
  <div id = "div1">This is first container</div>
  <div id = "div2">This is second container</div>
</body>
</html>

效果:

相对定位.png

Relative与Absolute组合使用

  1. 参照定位的元素必须是相对定位元素的前辈元素;
  2. 参照定位的元素必须加入position:relative;
  3. 定位元素加入position:absolute,便可以使用top、bottom、left、right来进行偏移定位了。

3.3、固定定位

固定定位与absolute定位类型类似,但它的相对移动的坐标是视图(屏幕内的网页窗口)本身。由于视图本身是固定的,它不会随浏览器窗口的滚动条滚动而变化,除非你在屏幕中移动浏览器窗口的屏幕位置,或改变浏览器窗口的显示大小,因此固定定位的元素会始终位于浏览器窗口内视图的某个位置,不会受文档流动影响,这与background-attachment:fixed;属性功能相同。

3.3.1、与absolute定位的关系:

3.3.1.1、相同点

第一,完全脱离标准文档流 第二,未设置偏移量时,都定位在父元素的左上角

3.3.1.2、不同点

absolute

  1. 无已定位祖先元素,以为 偏移参照基准
  2. 有已定位祖先元素,以距其最近的已定位祖先元素为偏移参照基准
  3. 位置随滚动条变化而变化

fixed

  1. 无论有、无已定位祖先元素,均以浏览器可视窗口为偏移参照基准
  2. 不会随滚动条的位置变化而变化,被它遮盖的元素会从其下面穿过

固定定位最喜欢用在导航栏中,比如//5udou.cn/togetherAlways中的最右边的导航栏使用的就是固定定位。

4、常见的布局设计

目前的布局都是一列、两列、三列和混合布局四种方式。

4.1、单列布局

单列布局水平居中定宽:margin: 0px auto,此时不可以再设置浮动或者绝对定位属性,否则失效。

一般我们都不会主动去设置高度,这边为了展示效果设置了height: 900px;。下同。

demo很简单:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>absolutely position</title>
  <style type="text/css" media="screen">
    #div1{
        width: 900px;
        height:  900px;
        background-color: gray;
        margin: 0 auto;
    }
  </style>
</head>
<body>
  <div id = "div1">This is first container</div>
</body>
</html>

4.2、两列布局

两列布局可以使用浮动的方法,也可以使用绝对定位。

使用浮动的自适应demo:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>absolutely position</title>
  <style type="text/css" media="screen">
    #wrapper{
      width: 800px;
      margin: 0 auto;
    }
    #div1{
        width: 50%;
        height: 800px;
        background-color: gray;
        float: left;
    }
    #div2{
      width:50%;
      height: 800px;
      background-color: blue;
      float:left;
    }
  </style>
</head>
<body>
  <div id = "wrapper">
    <div id = "div1">This is first container</div>
    <div id = "div2">This is second container</div>
  </div>
</body>
</html>

使用这种方法记得清除浮动,这里就不再细讲了。

使用绝对定位的话其中的一列的宽度最好是固定,这样另外一列的定位偏移位置可以计算出来,否则会出现两列重叠的现象。并且因为绝对定位的元素会脱离标准文档流,所以固定宽度的列的高度一定要大于自适应宽度列的高度,否则会出现下面的这种效果:

两列布局.png

正确的自适应demo代码应该是:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>absolutely position</title>
  <style type="text/css" media="screen">
    #wrapper{
      width: 800px;
      margin: 0 auto;
      position: relative;
    }
    #div1{
        width: 200px;
        height: 500px;
        background-color: gray;
    }
    #div2{
      width:50%;
      height: 500px;
      background-color: blue;
      position: absolute;
      left: 210px;
      top: 0px;
    }
    #div3{
      width: 100%;
      height: 100px;
      background-color: yellow;
    }
  </style>
</head>
<body>
  <div id = "wrapper">
    <div id = "div1">This is first container</div>
    <div id = "div2">This is second container</div>
    <div id = "div3">This is third container</div>
  </div>
</body>
</html>

4.3、三列布局

三列布局中如果三列的宽度都是百分比的话采用浮动自然会平整地分布在同一水平上,但是如果左右都是固定宽度的话使用浮动就无法让它们都停留在同一水平上了,原因是因为如果水平方向没有足够的空间放置浮动元素,它将向下移动,直到有足够的空间或没有更多的浮动元素为止。

代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>test</title>
  <style type="text/css">
      *{
          margin:0px;
          padding: 0px;
      }
      .left{
          width:200px;
          height:200px;
          background-color: #9955ff;
          border: 1px solid;
          float: left;
      }
      .middle{
          height:200px;
          background-color: #DDAAF1;
          float: left;
      }
      .right{
          width: 300px;
          height:200px;
          background-color: #DFFA1A;
          float: right;
      }

</style>
</head>
<body>
  <div class="left">200PX</div>
  <div class="middle">随着互联网的发展速度迅猛,前端工程师职业越来越火热,想学习Web前端技能吗 ? 该路径从基础知识到实战案例演练,一步步带您快速掌握如何搭建网站静态页面、开发网站交互特效,为您打开WEB前端工程师大门。还在等什么?快来学习吧!</div>
  <div class="right">300px</div>
</body>
</html>

效果如下:

三列布局demo1.png

所以此时需要修改代码使用绝对定位来实现自适应:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>test</title>
  <style type="text/css">
      *{
          margin:0px;
          padding: 0px;
      }
      .left{
          width:200px;
          height:200px;
          background-color: #9955ff;
          border: 1px solid;
          position: absolute;
          left: 0;
          top: 0;
      }
      .middle{
          height:200px;
          background-color: #DDAAF1;
          margin: 0 300px 0 200px;
      }
      .right{
          width: 300px;
          height:200px;
          background-color: #DFFA1A;
          position: absolute;
          right: 0;
          top: 0;
      }

</style>
</head>
<body>
<div class="left">200PX</div>
<div class="middle">随着互联网的发展速度迅猛,前端工程师职业越来越火热,想学习Web前端技能吗 ? 该路径从基础知识到实战案例演练,一步步带您快速掌握如何搭建网站静态页面、开发网站交互特效,为您打开WEB前端工程师大门。还在等什么?快来学习吧!</div>
<div class="right">300px</div>
</body>
</html>

三列布局的方法还有别的实现,具体布局具体实现吧,不能一概而论。大家主要掌握基本概念,那样的话自然是布局信手拈来,不在话下。

CSS的布局基础终于写完了,断断续续地写了好几天,思路也是不断地调整,如果各位童鞋读着有些许间断请见谅了哈!