两边固定大小,中间自适应的布局:流体布局、双飞翼与圣杯...

578 阅读2分钟

流体布局

左右模块各自向左右浮动,并设置中间模块的 margin 值使中间模块宽度自适应

  • margin-left: 左边div宽度+边距
  • margin-right: 右边div宽度+边距 缺点:主要内容无法最先加载,当页面内容较多时会影响用户体验
<!DOCTYPE html>
<html lang="en">
<head>
    <style>
	.left {
	    float: left;
	    height: 200px;
	    width: 100px;
	    background-color: red;
	}
	.right {
	    width: 200px;
	    height: 200px;
	    background-color: blue;
	    float: right;
	}
	.main {
	    margin-left: 120px;
	    margin-right: 220px;
	    height: 200px;
	    background-color: green;
	}
    </style>
</head>
<body>
    <div class="container">
        <div class="left"></div>
        <div class="right"></div>
        <div class="main"></div>
    </div>
</body>
</html>

BFC 三栏布局

BFC的表现原则,具有BFC特性的元素的子元素不会受到外部元素影响,也不会影响到外部元素。

对比上一个方法:可以把中间也变成 BFC,因为块级宽度默认是页面的100%,所以中间实现宽度自适应
例子中采用 overflow: hidden

缺点跟方法一类似,主要内容模块无法最先加载,当页面中内容较多时会影响用户体验。因此为了解决这个问题,有了后面要介绍的布局方案双飞翼布局。

<!DOCTYPE html>
<html lang="en">
<head>
    <style>
	.left {
	    float: left;
	    height: 200px;
	    width: 100px;
	    margin-right: 20px;
	    background-color: red;
	}
	.right {
	    width: 200px;
	    height: 200px;
	    float: right;
	    margin-left: 20px;
	    background-color: blue;
	}	
	.main {
	    height: 200px;
	    overflow: hidden;
	    background-color: green;
	}
    </style>
</head>
<body>
    <div class="container">
        <div class="left"></div>
        <div class="right"></div>
        <div class="main"></div>
    </div>
</body>
</html>

双飞翼布局和圣杯布局

主体内容可以优先加载

利用的是浮动元素 margin 负值的应用

  • 当static (非浮动、非定位)元素的margin-top/margin-left被赋予负值时,元素将被拉进指定的方向。
  • -100%是与float流中前一元素的宽度做比较

我们通过下列过程来理解:

  1. 先加载中间主体内容,让它向左浮动起来,宽度设置为100%
  2. 让left向左浮动,设置中间主体的margin-right或者左边内容的margin-left为-100%,让left出现在左侧
  3. 让right向左浮动,设置右边内容的margin-right:-right-width,让他以右线为基准向左移动
  4. 但是此时,left和right覆盖在main的上面,存在遮挡问题
  5. 圣杯和双飞翼分别采用不同方式解决这个问题
<!DOCTYPE html>
<html lang="en">
<head>
    <style>
    *{
      box-sizing: border-box;
    }
    .main {
      float: left;
      height: 500px;
      background: blue;
      width:100%;
    }
    .left {
      width: 400px;
      height: 500px;
      background: lightpink;
    }
    .right {
      width: 300px;
      height: 500px;
      background: lightgreen; 
    }
    .left {
      float: left;
      margin-left: -100%;
    }
    .right {
      float: left;
      margin-right: -300px;
    }
    </style>
</head>
<body>
    <div class="container">
      <div class="main">我这里有好多好多的文本,但是本质上我是占整个页面的,后面的float流通过margin负值放在我的两侧,实质上是放在我的上面了,遮住我的部分</div>
      <div class="left"></div>
      <div class="right"></div>
    </div>
</body>
</html>

圣杯布局

  1. 在main、left、right外面加一个包裹,设置外边距(预留给左右)
  2. 然后延续上面float得到一个类似上面的main被遮住的布局,但是布局外面有预留空白
  3. 对left、right进行相对定位,把他们移到预留的空白上
position: relative;
left: -120px;
<!DOCTYPE html>
<html lang="en">
<head>
    <style>
	.container {
	    margin-left: 120px;
	    margin-right: 220px;
	}
	.main {
	    float: left;
	    width: 100%;
	    height: 300px;
	    background-color: red;
	}
	.left {
	    float: left;
	    width: 100px;
	    height: 300px;
	    margin-left: -100%;
	    position: relative;
	    left: -120px;
	    background-color: blue;
	}
	.right {
	    float: left;
	    width: 200px;
	    height: 300px;
	    margin-left: -200px;
	    position: relative;
	    right: -220px;
	    background-color: green;
	}
    </style>
</head>
<body>
    <div class="container">
	<div class="main"></div>
	<div class="left"></div>
	<div class="right"></div>
    </div>
</body>
</html>

双飞翼

相比圣杯的思路就是,缩小main的内容范围

  1. 给 中间的main 加一个父元素main_f,main加上左右宽度的margin
  2. main_f与左右一起float
<!DOCTYPE html>
<html lang="en">
<head>
    <style>
      .main_f {
  	    float: left;
  	    width: 100%;
        }
        .main {
  	    height: 200px;
  	    margin-left: 110px;
  	    margin-right: 210px;
  	    background-color: green;
        }
	.left {
	    float: left;
	    height: 200px;
	    width: 100px;
	    margin-left: -100%;
	    background-color: red;
	}
	.right {
      float: left;
	    width: 200px;
	    height: 200px;
	    margin-left: -200px;
	    background-color: blue;
	}	
    </style>
</head>
<body>
    <div class="main_f">
        <div class="main"></div>
    </div>
    <div class="left"></div>
    <div class="right"></div>
</body>
</html>

Flex 布局

简单实用,未来的趋势,需要考虑浏览器的兼容性。

<!DOCTYPE html>
<html lang="en">
<head>
    <style>
	.container {
            display: flex;
	}
	.main {
            flex-grow: 1;
		    height: 300px;
		    background-color: red;
	}
	.left {
		    order: -1;
		    flex: 0 1 200px;
		    margin-right: 20px;
		    height: 300px;
		    background-color: blue;
	}
	.right {
	    	flex: 0 1 100px;
            margin-left: 20px;
		    height: 300px;
		    background-color: green;
	}
    </style>
</head>
<body>
    <div class="container">
	<div class="main"></div>
	<div class="left"></div>
	<div class="right"></div>
    </div>
</body>
</html>

Table 布局

缺点:无法设置栏间距

<!DOCTYPE html>
<html lang="en">
<head>
    <style>
        .container {
	    display: table;
	    width: 100%;
        }
        .left, .main, .right {
	    display: table-cell;
        }
        .left {
	    width: 200px;
	    height: 300px;
	    background-color: red;
        }
        .main {
	    background-color: blue;
        }
        .right {
	    width: 100px;
	    height: 300px;
	    background-color: green;
        }
    </style>
</head>
<body>
    <div class="container">
	<div class="left"></div>
	<div class="main"></div>
	<div class="right"></div>
    </div>
</body>
</html>

绝对定位布局

简单实用,并且主要内容可以优先加载。

<!DOCTYPE html>
<html lang="en">
<head>
    <style>
	.container {
	    position: relative;
	}
	.main {
	    height: 400px;
	    margin: 0 120px;
	    background-color: green;
	}
	.left {
	    position: absolute;
	    width: 100px;
	    height: 300px;
	    left: 0;
	    top: 0;
	    background-color: red;
	}
	.right {
	    position: absolute;
	    width: 100px;
	    height: 300px;
	    background-color: blue;
            right: 0;
	    top: 0;
	}
    </style>
</head>
<body>
    <div class="container">
        <div class="main"></div>
	<div class="left"></div>
	<div class="right"></div>
    </div>
</body>
</html>