专栏首页前端之旅CSS 基础系列:常见布局方式

CSS 基础系列:常见布局方式

1.单列布局

常见的单列布局有两种:

  • header、content、footer等宽
  • header、footer 等宽,content 略窄

对于第一种:

给 header、content、footer 设置相同的 width 或者 max-width(显示的宽度都一样,但是前者内容过长会溢出,后者会换行),再设置 margin 达到水平居中。

代码示例:

<div class="header"></div>
<div class="content"></div>
<div class="footer"></div>
.header{
    margin:0 auto; 
    max-width: 960px;
    height:100px;
    background-color: blue;
}
.content{
    margin: 0 auto;
    max-width: 960px;
    height: 400px;
    background-color: aquamarine;
}
.footer{
    margin: 0 auto;
    max-width: 960px;
    height: 100px;
    background-color: aqua;
}

对于第二种:

首先给 header 和 footer 共同的宽度(不设置宽度时默认撑满整个屏幕),之后给 content 和 header 子元素(比如头部的导航条)、footer 子元素一个共同的宽度。最后通过 margin 设置水平居中。

代码示例:

<div class="header">
    <div class="nav"></div>
</div>
<div class="content"></div>
<div class="footer"></div>
.header{
    margin:0 auto;
    max-width: 960px;
    height:100px;
    background-color: blue;
}
.nav{
    margin: 0 auto;
    max-width: 800px;
    background-color: darkgray;
    height: 50px;
}
.content{
    margin: 0 auto;
    max-width: 800px;
    height: 400px;
    background-color: aquamarine;
}
.footer{
    margin: 0 auto;
    max-width: 960px;
    height: 100px;
    background-color: aqua;
}

2.两列自适应布局

两列自适应布局是指一列由内容撑开,另一列撑满剩余宽度的布局方式。有三种常用方式可以达到两列自适应布局

float + BFC:

左元素在没有固定宽度的情况下设置浮动,因此宽度由内容撑开;右元素激活 BFC(这里采用 overflow:hidden)后,可以防止被浮动元素盖住,且正是为了防止被盖住,右元素宽度才会由默认的撑满屏幕变为撑满剩余部分。这里还要注意一个点是:浮动元素的 margin 是相对于与自己同级的浮动兄弟元素来说的。

代码示例:

<div class="parent" style="background-color: lightgrey;">
    <div class="left" style="background-color: lightblue;">
        <p>left</p>
    </div>
    <div class="right"  style="background-color: lightgreen;">
        <p>right</p>
        <p>right</p>
    </div>        
</div>
.left {
  float: left;
  margin-right: 20px;
}
.right {
  overflow: hidden;
  zoom: 1; /* 兼容 IE */
}

flex 布局:

设置父盒子为弹性盒后,子元素默认成一行显示,之后设置右元素 flex:1。该属性默认为 0,表示即使该行有额外空间也不会占满,设置为 1 表示右元素占满额外空间。

代码示例:

/* html部分同上 */
.parent {
  display:flex;
}  
.right {
  margin-left:20px; 
  flex:1;   
}

grid 布局:

代码示例:

/* html部分同上 */
.parent {
  display:grid;
  grid-template-columns:auto 1fr;
  grid-gap:20px
} 

3.三栏布局

即中间列自适应宽度,旁边两侧固定宽度的布局方式,最典型的是圣杯布局和双飞翼布局。

3.1 圣杯布局:

3.1.1 代码示例:

<article class="container">
    <div class="center"></div>
    <div class="left"></div>
    <div class="right"></div>
</article>
.body{
    min-width: 600px;
}
.container {
    padding-left: 220px;
    padding-right: 220px;
}
.left {
    float: left;
    width: 200px;
    height: 400px;
    background: red;
    margin-left: -100%;
    position: relative;
    left: -220px;
}
.center {
    float: left;
    width: 100%;
    height: 500px;
    background: yellow;
}
.right {
    float: left;
    width: 200px;
    height: 400px;
    background: blue;
    margin-left: -200px;
    position: relative;
    right: -220px;
}

3.1.2 实现步骤:

  • 首先我们想要优先加载 center 部分的内容,所以 dom 结构上先写 center
  • 为了让三者共在一行,给它们设置浮动;为了让 center 自适应,给它设置宽度 100%。此时布局是这样的:

这里要注意的点:块级元素在不显式设置宽度的情况下确实撑满整个屏幕,从这个角度来看,width 设置为 100% 似乎没有必要。但不要忘记了我们给它设置了浮动 —— 浮动元素具有包裹性,在不显式设置宽度的情况下由内容撑开。这里如果不设置 100% 宽度,且里面没有足够的内容,那么会导致布局崩坏。

  • 设置 left 和 right 的 margin-left 为负值,让它们回到与 center 同一行。此时布局是这样的:

这里要注意的点:所有浮动元素可以看作位于同一个浮动流,利用负边距可以让某个元素在这个流中移动,并且会叠加到相应元素的上面。对于 left 来说,它需要左移父元素的总宽度,对于 right 来说,它需要左移自身宽度。

  • 设置父容器的左右 padding,使内部内容向中间挤压,从而使左右留白。此时布局是这样的:
  • 给 left 和 right 设置绝对定位,让它们占据父元素的留白空间。最终得到的布局是这样的:
  • 给页面设置 min-width: 600px

这里要注意的点:由于左右两列宽度固定,因此我们至少要给页面一个最小宽度,但这个最小宽度并不是简单的左右两列宽度之和 —— 别忘了,之前的 left 位于 center,left 是 relative 定位,所以在 center 上占据过的空间不会消失。所以页面最小宽度是 left-width * 2 + right-width

3.1.3 缺点;

如果其中一列内容高度拉长,其他两列的背景并不会自动填充(后面介绍的等高布局可以解决这个问题)

3.2 双飞翼布局:

双飞翼布局在圣杯布局基础上进一步优化,解决了圣杯布局错乱问题,实现了内容与布局的分离。而且任何一栏都可以是最高栏,不会出问题。

3.2.1 代码示例

<div class="center">
    <div class="inner">双飞翼布局</div>
</div>
<div class="left"></div>
<div class="right"></div>
.body {
    min-width: 600px;
}
.left {
    float: left;
    width: 200px;
    height: 400px;
    background: red;
    margin-left: -100%;
}
.center {
    float: left;
    width: 100%;
    height: 500px;
    background: yellow;
}
.center .inner {
    margin: 0 200px; /* 主要区别 */
}
.right {
    float: left;
    width: 200px;
    height: 400px;
    background: blue;
    margin-left: -200px;
}

3.2.2 实现步骤

前两步与圣杯布局一样:

  • 三个部分都设定为左浮动,然后设置 center 的宽度为 100%,此时,left 和 right 部分会跳到下一行;
  • 通过设置负 margin 让 left 和 right 部分回到与 center 部分同一行;

这里开始有所不同:

  • center 部分增加一个内层div,并设margin: 0 200px;
  • 同样要给页面设置最小宽度,这里没有用定位,所以最小宽度可以直接等于左右两列宽度之和

3.2.3 缺点:

多加一层 dom 树节点,增加渲染树生成的计算量。

两种布局的对比:

  • 优先加载主列。
  • 三列浮动,配合负外边距形成三列布局
  • 两种布局方式的主要区别在于如何处理主列,从而让其内容不被覆盖。对于圣杯布局,它是利用父盒子的左右 padding 确保将主列内容挤到中间,在效果上表现为三个独立列;对于双飞翼布局,它是在主列里放置一个子盒子,利用子盒子的左右 margin 确保内容位于中间,在效果上表现为左右两列在主列上面。

3.3 flex 布局:

flex 布局是最简便的,而且在移动端应用广泛。

3.3.1 代码示例:

<div class="container">
    <div class="center"></div>
    <div class="left"></div>
    <div class="right"></div>
</div>
.container{
    display: flex;
}
.center{
    height:500px;
    background-color: blue;
    flex: 1;
}
.left{
    height: 200px;     
    background-color:gray; 
    order: -1;
    flex:0 1 100px;
}
.right{
    height: 200px;
    background-color: red;
    flex: 0 1 100px;
}

3.3.2 实现步骤:

只说几个注意的点

  • 在不优先加载主列的情况下,dom 结构可以按照左中右顺序书写,这样不需要额外设置 order;因为我们这里要优先加载主列,所以 dom 结构还是先写主列,之后通过降低左列的 order 恢复顺序。
  • flex 只有一个值时,设置的是 flex-grow,代表弹性子元素对父元素剩余空间的分配,因为不设置的时候默认是 0,所以这里只有设置了 1 的主列参与分配剩余空间,从而实现宽度自适应。
  • flex 有三个值时,设置的是 flex-growflex-shrinkflex-basis。这里左右两列的 flex-basis 都是 100px,实际上为它们设置了固定宽度。

4.等高布局

等高布局是指多个子元素在父元素中高度相等的布局方式。

4.1 正 padding + 负 margin:

该方法可以解决圣杯布局各子元素高度不等的缺点。给各个子元素设置一个大数值的 padding-bottom,再设置相同数值的负的 margin-bottom,并给总的父盒子设置 overflow:hidden,把溢出背景切掉。假设某一列高度最大,则父盒子的高度会等于这一列高度,而其他列本来的留白部分由带背景色的 padding 补偿。 基本代码与圣杯布局一样,新增代码如下:

/* 注意是三个都设置 */
.center,
.left,
.right {
    padding-bottom: 10000px;
    margin-bottom: -10000px;
}
.container {
    padding-left: 220px;
    padding-right: 220px;
    overflow: hidden;
}

关于原理,我暂时是这么理解的,不一定正确:可以看作 margin 负值是向内收缩至与 padding 高度相等处,虽然 padding 还在(所以有背景颜色),但是丧失了在空间上撑开父盒子的能力(因为此时被 margin 取代,margin 撑不开高度),即父盒子由最高列撑开,其他两列不足高度的部分由 padding 填充。

4.2 利用背景图片:

这种方法是我们实现等高列最早使用的一种方法,就是使用背景图片,在列的父元素上使用这个背景图进行Y轴的铺放,从而实现一种等高列的假象。实现方法简单,兼容性强,不需要太多的css样式就可以轻松实现,但此方法不适合流体布局等高列的布局。

在制作样式之前需要一张类似下面的背景图:

代码示例:

<div class=”container clearfix”>
    <div class=”left”></div>
    <div  class=”content”></div>
    <div class=”right”></div>
</div>
.container {
  background: url("column.png") repeat-y;
  width: 960px;
  margin: 0 auto;
}
.left {
  float: left;
  width: 220px;
}
.content {
  float: left;
  width: 480px;
}
.right {
  float: left;
  width: 220px;
}

4.3 利用表格布局:

这是一种非常简单,易于实现的方法。不过兼容性不好,低版本 IE 无法正常运行。

<div class="container table">
    <div class="containerInner tableRow">
    /* 左列 */
    <div class="column tableCell cell1">
        <div class="left aside">
        ....
        </div>
    </div>
    /* 主列 */
    <div class="column tableCell cell2">
        <div class="content section">
        ...
        </div>
    </div>
    /* 右列 */
    <div class="column tableCell cell3">
        <div class="right aside">
        ...
        </div>
    </div>
    </div>
</div>
.table {
  width: auto;
  min-width: 1000px;
  margin: 0 auto;
  padding: 0;
  display: table;
}
.tableRow {
  display: table-row;
}
.tableCell {
  display: table-cell;
  width: 33%;
}
.cell1 {
  background: #f00;
  height: 800px;
}
.cell2 {
  background: #0f0;
}
.cell3 {
  background: #00f;
}

4.4 使用边框和定位:

这种方法是使用边框和绝对定位来实现一个假的高度相等列的效果。结构简单,兼容各浏览器,容易掌握。假设你需要实现一个两列等高布局,侧栏高度要和主内容高度相等。

代码示例:

<div id="wrapper">
    <div id="mainContent">...</div>
    <div id="sidebar">...</div>
</div>
#wrapper {
  width: 960px;
  margin: 0 auto;
}
#mainContent {
  border-right: 220px solid #dfdfdf;
  position: absolute;
  width: 740px;
  height: 800px;  
  background: green;
}
#sidebar {
  background: #dfdfdf;
  margin-left: 740px;
  position: absolute;
  height: 800px;
  width: 220px;
}

4.5 利用 flex 布局:

最简单的方法就是直接设置父盒子为弹性盒。此时弹性子元素的 align-items 属性默认值是 stretch,也就是在 y 轴上将所有子元素拉伸为同一高度,从而达到等高布局。

5.粘连布局

  • 内容区 main 高度足够长的时候,footer 紧跟在 main后面;
  • 内容区 main 高度不够长的时候,footer 粘连在屏幕的底部

5.1 代码示例:

<div id="wrap">
    <div class="main">
    main <br />
    main <br />
    main <br />
    </div>
</div>
<div id="footer">footer</div>
* {
    margin: 0;
    padding: 0;
}
html,
body {
height: 100%;/* 高度一层层继承下来 */
}
#wrap {
    min-height: 100%;
    background: pink;
    text-align: center;
    overflow: hidden;
}
#wrap .main {
    padding-bottom: 50px;
}
#footer {
    height: 50px;
    line-height: 50px;
    background: deeppink;
    text-align: center;
    margin-top: -50px;
}

5.2 实现步骤

  • footer 必须是一个独立的结构,与 wrap 没有任何嵌套关系
  • wrap 区域的高度通过设置 min-height,变为视口高度
  • footer 要使用 margin 为负来确定自己的位置
  • main 区域需要设置 padding-bottom。这也是为了防止负 margin 导致 footer 覆盖任何实际内容。

参考: https://juejin.im/post/5bbcd7ff5188255c80668028#heading-19

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 在项目中使用 vue-awesome-swiper 遇到的问题

    最近做的商城项目需要在首页展示一个轮播图,秉承着“有现成轮子就绝不自己写”(其实是懒和菜)的想法,在网上搜索了一下,最后选择使用 vue-awesome-swi...

    Chor
  • 关于dom对象和jq对象的疑问

    提示allp[i].attr()不是一个方法,而attr()是jq对象的方法,这个报错等于说allp[i]不是一个jq对象。 参考stackoverflow ,...

    Chor
  • 「译」ES6:参数默认值的实现细节

    在这篇文章中我们会介绍另一个 ES6 的特性,带默认值的函数参数。正如我们将看到的,有一些微妙的案例。

    Chor
  • 前端-CSS-更改标签样式-长宽字体-背景-边框-显示方式-定位-透明度-扩展点-02

    suwanbin
  • Vue 2.x折腾记 - (20) JSX在业务中的具体实践以及跟React书写的差异化

    Vue的jsx,能够支持部分vue独有的特性,比如拿到computed, 指令及自定义事件;

    CRPER
  • 翻译:如何使用CSS实现多行文本的省略号显示

    本文翻译自CSS Ellipsis: How to Manage Multi-Line Ellipsis in Pure CSS,文中某些部分有些许改动,并添...

    欲休
  • javascript当中div在单行(float:left)用法

    div在单行(float:left) 例 1.2.1 divInOneLineIEFF.html <div style="width:100px"> ...

    马克java社区
  • CSS布局解决方案(全屏布局)

    原文连接:https://segmentfault.com/a/1190000013565024#articleHeader1

    用户1093975
  • CSS3圆角、opacity 透明度、rgba 背景色设置

    设置某一个角的圆角,比如设置左上角的圆角: border-top-left-radius:30px 60px;

    Devops海洋的渔夫
  • Html和CSS布局技巧(转)

    水平居中的页面布局中最为常见的一种布局形式,多出现于标题,以及内容区域的组织形式,下面介绍四种实现水平居中的方法(注:下面各个实例中实现的是child元素的对齐...

    山河木马

扫码关注云+社区

领取腾讯云代金券