两列布局

891 阅读3分钟

写在前面

除了看图文之外, 也要注意代码中的注释

概念

将界面分成左右两列, 左列定宽, 右列自适应

如下面的图所示:

image.png

实现方式

版本一

基本原理: 一个块级元素浮动,另一个块级元素保持默认,这样第二个块级元素就会当第一个块元素不存在,而使得他们显示在同一行

实现效果和代码

实现代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>两列布局</title>
    <style>
        .root{
            height:300px;
            width: 600px;
        }
        .left{
            float:left;
            background-color: pink;
            width:200px;
            height: 100%;
        }
        .right{
            height: 100%;
            background-color: gray;
            margin-left:200px;
        }
    </style>
</head>
<body>
    <!-- 大盒子设置宽高 -->
    <div class="root">
        <!-- 左侧的盒子定宽,并设置左浮动(因为设置了浮动因此该元素已脱离文档流) -->
        <div class="left"></div>
        <!-- 
            因为left盒子设置了浮动的原因,所以右盒子会浮动到和左盒子同一行,
            因为div默认为块级元素,所以宽度默认为100%,此时需要再设置margin-left,
            将被右盒子挡住的部分,再显示出来
        -->
        <div class="right"></div>
    </div>
</body>
</html>

实现效果如下:

image.png

优点和缺陷

优点: 实现简单

缺陷: 右盒子的内容,如果设置清除浮动,那么改元素可能塌出盒子之外.

详细缺点如下:

  • 左盒子width和右盒子margin-width耦合
  • 左右盒子, 一个脱离了文档流, 一个还在文档流中
  • 右盒子的内容如果清除浮动, 会导致该内容塌出盒子之外
缺陷演示代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>两列布局</title>
    <style>
        .root{
            height:300px;
            width: 600px;
        }
        .left{
            float:left;
            background-color: pink;
            width:200px;
            height: 100%;
        }
        .right{
            height: 100%;
            background-color: gray;
            margin-left:200px;
        }
        .content{
            clear: both;
            height: 200px;
            background-color: green;
        }
    </style>
</head>
<body>
    <!-- 大盒子设置宽高 -->
    <div class="root">
        <!-- 左侧的盒子定宽,并设置左浮动(因为设置了浮动因此该元素不会再在文档流中) -->
        <div class="left"></div>
        <!-- 
            因为left盒子设置了浮动的原因,所以右盒子会浮动到和左盒子同一行,
            因为div默认为块级元素,所以宽度默认为100%,此时需要再设置margin-left,
            将被左盒子挡住的部分,再显示出来
        -->
        <div class="right">
            <div class="content"></div>
        </div>
    </div>
</body>
</html>
缺陷效果演示

image.png

版本二

基本原理:两个框都浮动,使得框内的子孙元素在使用clear属性时,不会影响框外的元素。再利用宽度100% - 负值margin-left或margin-right,留出足够容纳其他元素空间的特性,实现两列布局。

实现效果和代码

实现代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>两列布局</title>
    <style>
        .root{
            height:300px;
            width: 600px;
        }
        .left{
            float:left;
            background-color: pink;
            width:200px;
            height: 100%;
            /* 由于.right-fix让其所在盒子浮了上来,且将.left所在元素覆盖住了,
            所以这里必须设置position: relative,让其显示优先级在.right-fix之上 */
            position: relative;
        }
        .right-fix{
            height: 100%;
            background-color: orange;
            /* 这里产生了浮动,使得该元素也脱离了文档流 */
            float:right;
            width: 100%;
            /* 注意: 宽度为100%,且设置了右浮动,那么这个margin-left效果实际为,
            在保持位置不变的情况下将左侧空出200px */
            margin-left:-200px;
        }
        .right{
            height: 100%;
            background-color: lightgray;
            /* 注意: 这里也必须设置margin-left, 否则内容会在父盒子的最左侧 */
            margin-left: 200px;
        }
        .content{
            /* 此时这里清除浮动,不会再导致这个节点被漏出去 */
            clear: both;
            height: 200px;
            background-color: green;
        }
    </style>
</head>
<body>
    <!-- 大盒子设置宽高 -->
    <div class="root">
        <!-- 左侧的盒子定宽,并设置左浮动(因为设置了浮动因此该元素不会再在文档流中) -->
        <div class="left"></div>
        <div class="right-fix">
            <div class="right">
                <div class="content">fff</div>
            </div>
        </div>
    </div>
</body>
</html>

实现效果

image.png

优点和缺陷

优点: 解决了版本一中右盒子内部元素清除浮动会造成元素漏出盒子的问题

缺点: css和html结构都变得复杂了

详细缺点如下:

  • 左盒子width和右盒子margin-width耦合

版本三

原理:通过display: table方式实现table效果的布局

实现效果和代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>两列布局</title>
    <style>
        .root{
            display: table;
            table-layout: fixed;
            height:300px;
            width: 900px;
        }
        .left, .right{
            display: table-cell;
        }
        .left{
            width:300px;
            background-color: lightblue;
        }
        .right{
            background-color: lightcoral;
        }
        .content{
            background-color: lightgreen;
            width: 100px;
            height: 100px;
            clear: both;
        }
    </style>
</head>
<body>
    <!-- 大盒子设置宽高 -->
    <div class="root">
        <div class="left"></div>
        <div class="right">
            <div class="content">fff</div>
        </div>
    </div>
</body>
</html>

image.png

优点和缺陷

优点: 实现简单,兼容性好,版本一和版本二中有的问题,版本三都解决了

缺陷: table布局模拟的是table特性,直接使用table布局的问题,display=table也一样有

扩展

  1. 页面的每个元素都被看做一个矩形框,这个框由元素的内容, 内边距, 边框和边距组成.
  2. css的3种定位机制: 普通流(就是常说的文档流), 浮动定位, 绝对定位. 除非专门指定, 否则所有框都在普通流中定位.
  3. 相对定位普通流定位的一种,因为元素的位置是相对于它在普通流中的位置的。
  4. 绝对定位使元素的位置与文档流无关,不占据空间,普通文档流中其他元素的布局也会当这个绝对定位元素不存在。绝对定位的元素位置是相对于距离它最近的那个已定位的祖先元素确定的。如果绝对定位元素,没有已定位的祖先元素,那么他的位置就是相对于根元素而言的。
  5. 固定定位是绝对定位的一种,差异在于固定元素的包含块是视口,所以固定定位的元素的位置在页面上的表现总是不动的。
  6. 浮动定位的元素可以左右移动,直到他的外边缘碰到包含框或另一个浮动框的边缘。这里的包含框的边缘是指当前元素的父元素的边缘。
  7. 给框设置浮动,会使框脱离普通流(文档流),不影响周围的元素,普通流中的块框表现的就像浮动框不存在一样。
  8. clear属性表示框的哪些边不应该挨着浮动框, 浮动框(这里用框1表示)内部的子孙框,如果进行clear属性设置,是不会对框1的子孙框之外的框产生影响的。

最后的小记

  • 宽度为100%且右浮动的块元素中设置margin-left为负值,实际效果是保持位置不变,并在左边的位置留出一片位置