布局的常用解决方案

610 阅读6分钟

水平居中布局

  1. text-align + inline-block

text-align是为文本内容设置对齐方式,而子元素的display设置为inline-block后,就有文本元素的特性。

<style type="text/css">
	.parent{
		text-align: center;

		width: 100%;
		height: 200px;
		background: #ccc;
	}
	.child{
		display: inline-block;
		
		width: 200px;
		height: 200px;
		background: #c9394a;
	}
</style>
<div class="parent">
	<div class="child">我是一个小可爱</div>
</div>
  • 优点:浏览器兼容性好

  • 缺点:属性是有继承性的,会导致子元素中的文本也是居中显示

  1. table/block元素 + margin

display:table;的表现和<table>标签类似

	<div class="parent1">
		<style type="text/css">
			.parent1{
				width: 100%;
				height: 200px;
				background: #ccc;
			}
			.child1{
				display: table/block;
				margin: 0 auto;
				
				width: 200px;
				height: 200px;
				background: #c9394a;
			}
		</style>
		<div class="child1">table + margin</div>
	</div>	
  • 优点:只需要对子元素进行设置就可以实现水平方向的居中布局
  • 缺点:如果子元素脱离文档流(float,postion:absolute/fixed),会导致margin属性无效
  1. absolute + transform
	<div class="parent2">
		<style type="text/css">
			.parent2{
				width: 100%;
				height: 200px;
				background: #ccc;

				position: relative;
			}
			.child2{
				width: 200px;
				height: 200px;
				background: #c9394a;

				position: absolute;
				left: 50%;
				transform: translateX(-50%);
			}
		</style>
		<div class="child2">table + margin</div>
	</div>	
  • 优点:无论父元素是否脱离文档流,都不影响子元素水平居中的效果
  • 缺点:transform属性是CSS3中的特性,浏览器的支持程度不好

垂直居中布局

  1. table-cell + vertical-align
  • 缺点:父级必须得有宽高
  <div class="parent">
    <style type="text/css">
      .parent {
        width: 500px;
        height: 600px;
        background: #ccc;

        display: table-cell;
        vertical-align: middle;
        text-align: center;
      }

      .child {
        width: 200px;
        height: 200px;
        background: #c9394a;
        display: inline-block;
      }
    </style>
    <span class="child">
      实现垂直居中布局
    </span>
  </div>

  • 优点: 浏览器兼容性好
  • 缺点1: vertical-align属性具有继承性,导致父级元素的文本也是居中显示。如果父级元素中存在其他的文本元素就会出现不理想的效果。
  • 缺点2: 父级得有固定宽高
  1. position+transform
<div class="parent1">
	<style type="text/css">
		.parent1{
			width: 200px;
			height: 600px;
			background: #ccc;

			position: relative;
		}
		.child1{
			width: 200px;
			height: 200px;
			background: #c9394a;

			position: absolute;
			top: 50%;
			transform: translateY(-50%);
		}
	</style>
	<div class="child1"> 
		实现垂直居中布局
	</div>
</div>
  • 优点:即使父元素脱离文档流也不会影响子元素的居中效果
  • 缺点:transforom是CSS3属性,要注意浏览器的兼容性

水平居中 + 垂直居中

  1. table + margin实现水平居中,table-cell + vertical-align实现垂直居中布局
<div id='parent'>
	<style type="text/css">
		#parent{
			width: 1000px;
			height: 600px;
			background: #ccc;
			
			/*表示td*/
			display: table-cell;
			vertical-align: middle;
		}
		#child{
			width: 200px;
			height: 200px;
			background: #c9394a;

			/*如果是display:table;表示<tabel> td中包含table 不太符合语义化*/
			display: block;
			margin:0 auto;
		}
	</style>
	<div id='child'>
		我是水平垂直居中
	</div>
</div>
  • 优点:浏览器兼容性好
  • 缺点:如果子元素中设置的是display:tabel,父元素设置的是display:table-cell那么语义化不够友好。
  1. position+负margin
  • 必须知道居中的盒子的宽高
  <div id='parent1'>
    <style type="text/css">
      #parent1 {
        width: 1000px;
        height: 600px;
        background: #ccc;
        /*表示td*/
        position: relative;
      }

      #child1 {
        width: 200px;
        height: 200px;
        background: #c9394a;
        text-align: center;
      }

      #child1 {
        position: absolute;
        left: 50%;
        top: 50%;
        margin-left: -100px;
        margin-top: -100px;
      }
    </style>
    <div id='child1'>
      我是水平垂直居中
    </div>
  </div>
  1. position:absolute 结合 magin:auto实现
  • 居中的盒子必须有宽高,但是不用知道具体的值
<div id='parent1'>
    <style type="text/css">
      #parent1 {
        width: 1000px;
        height: 600px;
        background: #ccc;
        /*表示td*/
        position: relative;
      }

      #child1 {
        width: 200px;
        height: 200px;
        background: #c9394a;
        text-align: center;
      }
      #child1 {
        position: absolute;
        left: 0;
        right: 0;
        top: 0;
        bottom: 0;
        margin: auto;
      }
    </style>
    <div id='child1'>
      我是水平垂直居中
    </div>
  </div>
  1. position+transform:translate(-50%;-50%)实现
<div id='parent1'>
	<style type="text/css">
		#parent1{
			width: 1000px;
			height: 600px;
			background: #ccc;
			/*表示td*/
			position: relative;
		}
		#child1{
			width: 200px;
			height: 200px;
			background: #c9394a;

			/*如果是display:table;表示<tabel> td中包含table 不太符合语义化*/
			position: absolute;
			left: 50%;
			top:50%;
			transform: translate(-50%,-50%);
		}
	</style>
	<div id='child1'>
		我是水平垂直居中
	</div>
</div>
  1. flex
 <div id='parent2'>
    <style type="text/css">
      #parent2 {
        width: 1000px;
        height: 600px;
        background: #ccc;
        display: flex;
        justify-content: center;
        align-items: center;
      }

      #child2 {
        width: 200px;
        height: 200px;
        background: #c9394a;
        text-align: center;
      }
    </style>
    <div id='child2'>
      我是水平垂直居中
    </div>
  </div>

左右固定宽度,中间自适应的三列布局

  1. 圣杯布局
  <style>
    html,
    body {
      height: 100%;
      overflow: hidden;
    }

    .container {
      height: 100%;
      padding: 0 200px;
    }

    .left,
    .right {
      width: 200px;
      min-height: 200px;
      background: blue;
    }

    .center {
      width: 100%;
      min-height: 400px;
      background: orange;
    }

    .left,
    .right,
    .center {
      float: left;
    }

    .left {
      margin-left: -100%;
      position: relative;
      left: -200px;
    }

    .right {
      margin-right: -200px;
    }
  </style>
  <div class="container clearfix">
    <div class="center">中间</div>
    <div class="left">左边</div>
    <div class="right">右边</div>
  </div>
  1. 双飞翼布局
  <style>
    .container {
      width: 100%;

    }

    .container .center {
      margin: 0 200px;
      min-height: 400px;
      background: red;
    }

    .container,
    .left,
    .right {
      float: left;
    }

    .left {
      background: yellow;
      width: 200px;
      min-height: 200px;
      margin-left: -100%;
    }

    .right {
      background: yellow;
      width: 200px;
      min-height: 200px;
      margin-left: -200px;
    }
  </style>
  <div class="container clearfix">
    <div class="center">中间</div>
  </div>
  <div class="left">左边</div>
  <div class="right">右边</div>
  1. 单纯的float实现
  <section class="layout float">
    <style>
      .layout.float .left {
        float: left;
        width: 300px;
        background: red;
      }

      .layout.float .right {
        float: right;
        width: 300px;
        background: blue;
      }

      .layout.float .center {
        background: yellow
      }
    </style>
    <article class="left-right-center">
      <div class="left"></div>
      <div class="right"></div>
      <div class="center">
        <h1>浮动解决方案</h1>
        <p> 1.这是三列布局的中间部分</p>
        <p> 2.这是三列布局的中间部分</p>
        <p> 3.缺点:清楚浮动,兼容性好</p>
        <p> 4. 创建BFC</p>
      </div>
    </article>
  </section>
  1. 定位实现
 <section class="layout absolute">
    <style>
      .layout.absolute .left-right-center>div {
        position: absolute;
      }

      .layout.absolute .left {
        left: 0;
        width: 300px;
        background: red;
      }

      .layout.absolute .center {
        left: 300px;
        right: 300px;
        background: yellow;
      }

      .layout.absolute .right {
        right: 0;
        width: 300px;
        background: blue;
      }
    </style>
    <article class="left-right-center">
      <div class="left"></div>
      <div class="center">
        <h1>绝对定位解决方案</h1>
        <p>1.这是三列布局的中间部分</p>
        <p>2.这是三列布局的中间部分</p>
        <p>3.布局脱离文档流</p>
      </div>
      <div class="right"></div>
    </article>
  </section>
  1. flex布局
  <section class="layout flexbox">
    <style>
      .layout.flexbox {
        margin-top: 300px;
      }

      .layout.flexbox .left-right-center {
        display: flex;
      }

      .layout.flexbox .left {
        width: 300px;
        background: red;
      }

      .layout.flexbox .center {
        flex: 1;
        background: yellow;
      }

      .layout.flexbox .right {
        width: 300px;
        background: blue;
      }
    </style>
    <article class="left-right-center">
      <div class="left"></div>
      <div class="center">
        <h1>flex解决方案</h1>
        <p>1.这是三列布局的中间部分</p>
        <p>2.这是三列布局的中间部分</p>
        <p>3.比较完美的解决方案</p>
      </div>
      <div class="right"></div>
    </article>
  </section>

表格布局

实现方式一:用table形式实现table布局

	<style type="text/css">
		table{
			width: 800px;
			height: 200px;
			border-collapse: collapse;/*合并表格边框*/
		}
		.red{
			background: red;
		}
		.blue{
			background: blue;
		}
	</style>
	
    <h1>我是用table标签形式实现的table布局</h1>
	<table>
		<tr>
			<td class="red"><div>我是table的第一列</div></td>
			<td class="blue">我是table的第二列</td>
			<td class="red">我是table的第三列</td>
		</tr>
	</table>
优点:
  • 默认情况下会平均分配列宽。
  • 设置其中一列的宽度,其他列宽度会自动平均分配。可以方便的实现一侧固定,一侧自适应布局。
  • 每个表格中的内容会自动垂直居中。

实现方式二:用css实现table布局

    <style type="text/css">
   		.table{
			display: table;
			width: 800px;
			height: 200px;
			margin-top: 10px;
		}
		.table-row{
			display: table-row;
		}
		.table-cell{
			display: table-cell;
		} 
	</style>
	
    <h1>我是css式实现的table布局</h1>
	<div class="table">
		<div class="table-row">
			<div class="red table-cell">我是table的第一列</div>
			<div class="blue table-cell">我是table的第二列</div>
		</div>
	</div>
优点:
  • 默认情况下会平均分配列宽。
  • 设置其中一列的宽度,其他列宽度会自动平均分配。可以方便的实现一侧固定,一侧自适应布局。
缺点:
  • 每个表格中的内容不会自动垂直居中了。

点我查看效果

浮动

优点
  • 可以解决内联元素的间隙问题
  • 没有margin合并问题

flex布局

flex container

display:flex;

flex-direction 主轴的方向

  1. row; // 默认值 表示主轴方向 左——>右
  2. column; // 表示主轴方向 上——>下
  3. row-reverse; // 表示主轴方向 右——>左
  4. column-reverse; // 表示主轴方向 下——>上

flex-wrap 换行机制

如果总元素的宽度和高度大于设置的总宽度和总高度,又没有设置换行的方式,flex会让每个元素平均分配总宽度和总高度。

  1. no-wrap //默认值 不换行
  2. wrap //换行

flex-group:flex-direction+flex-wrap

justify-content 主轴的对齐方式

  1. flex-start // 起点对齐
  2. flex-end // 终点对齐
  3. center // 居中对齐
  4. space-betten // 平均分布
  5. space-around // 左右两边等距分布

align-items 交叉轴的对齐方式

  1. flex-start // 起点对齐
  2. flex-end // 终点对齐
  3. center // 居中对齐
  4. stretch // 在没有给flex item设置高度的时候,flex imte会在交叉轴上占满,如果给flex item设置的高度,那么这个属性不生效。
  5. baceline // 按照flex item中的文字基线对齐。

align-content :把多行当做整体

  • 换行的元素会在交叉轴上居中,所以就可能出现:和换行之前的行之间出现间距的问题:
  • 解决方案:通过设置宽或者高解决。

row-reverse会靠右对齐,而column-reverse不会靠下对齐的原因

因为整个容器的高度和包含内容块的高度一致,而横向上总宽度是大于包含块的宽度的。

flex item

flex-basis:设置弹性盒子的基准值,也就是宽度

flex-grow: 扩展比例,去分割剩余空间

flex-shrink:缩小的比例 0表示不缩小,

flex:flex-group|flex-shrink|flex-basis

  • flex:1 表示 flex-group:1;flex-shrink:1;flex-basis:0%;

  • flex:auto 表示 flex-group:1;flex-shrink:1;flex-basis:auto;

  • flex:none 表示 flex-group:0;flex-shrink:0;flex-basis:auto;

  • 优点

现代的浮动解决方案,实现起来比较容易简单

  • 缺点

兼容不好

点我查看flex布局实例

inline-block布局

	<style type="text/css">
   	.container{
   		width: 800px;
   		height: 200px;
   		background: yellow;
   		font-size: 0;
   	}
   	.left{
   		width: 200px;
   		height: 200px;
   		background: red;
   		display: inline-block;
   		font-size: 20px;
   	}
   	.right{
   		width: 600px;
   		height: 200px;
   		background: blue;
   		display: inline-block;
   		font-size: 20px;
   	}
   </style>
   <div class="container">
   	<div class="left">
   		我是左边
   	</div>
   	<div class="right">
   		我是右边
   	</div>
   </div>
缺点
  1. 块与块之间会出现间隙
  • 原因: 因为文字和文字之间会有间隙
  • 解决方案: 将父元素的font-size设置为0
  1. 不适合宽度自适应的布局
优点

响应式布局

主要方法:

自适应空间[rem/viewport]、隐藏[media query]、折行[media query]。

  • viewport解决方案
<!--不会等比缩放-->
<meta name="viewport" content="width=device-width" initial-sacle=1.0>
<!--等比缩放:为width设定固定的值-->
<meta name="viewport" content="width=320" initial-sacle=1.0>

  • media query解决方案
  1. 用media query实现隐藏
@media (max-width:640px){
	.left{
		display: none
	}
}
  1. 用media query实现折行
@media (max-width:640px){
    .intro{
		display: block;
		margin: 7px auto;
	}
}
  • rem解决方案

以html的font-size为基准的像素。html的font-size默认是16px,为了好计算可以设置为10px。


@media(max-width: 375px){
	html{
		font-size: 24px;
	}
}
@media (max-width: 320px){
	html{
		font-size: 20px;
	}
}
.intro1{
	display: inline-block;
	width: 18rem;
	height: 18rem;
	line-height: 18rem;
	text-align: center;
	border-radius: 9rem;
	border: .1rem solid red;
	margin: .7rem;
}

rem的缺点:rem的单位不一定会非常精确。

点我查看代码演示