CSS布局,大方向是从上到下,每一块从内到外,注意细节。无难点,多动手。其实写布局就是在写UI(User Interface,用户界面)。市场上那么多的UI框架,也就是为更快地实现布局,节约写CSS的时间。

CSS布局套路

是否兼容IE8?

如果需要兼容IE8那就用 float布局,定宽 或百分比实现弹性布局。

不需要兼容IE8 就用 flex布局,弹性宽度,例如 移动端就用flex布局,width: auto;

布局原则

  • 不到万不得已,不要写死 width 和 height
  • PC端最外面div设置mix-height,里面再设置一层写width=mix-height。移动端宽度一定不要写死,设置width: auto。PC端要兼容IE的话可以写死高度宽度,然后就一直float float,不要用高级语法了。左浮左浮,均匀布局。
  • 尽量用高级语法,如 calc、flex
  • 如果是 IE,IE能把页面写出来就不错了,就宽度高度全部写死
  • 用 div 做布局,外面的 div 就用来做布局,用来做布局的div 就不要乱加东西,要写东西就在里面加div再写内容。其实外面的div 就是我们写好的UI框架。

float布局

float布局是目前应用最广的,兼容IE5。口诀:

0 把宽度算好

1 儿子全加 float: left (right)

2 父亲 加添加类 clearfix

3 如果宽度不够,可以用 负margin 来凑 。margin: 0 -4px;

  1. .clearfix::after{
  2. content:'';
  3. display:block;
  4. clear:both;
  5. }
  6. .clearfix{
  7. zoom: 1;
  8. }

两栏布局(百分比布局,弹性布局)

  • 原理:div.parent 不定宽,内部两个 div.child 固定形成弹性布局。
  1. 基本两栏布局

    code

  2. 两栏布局中间有间隔 gap

    code

注意上面都是不定宽的版本,定宽版本在

两栏布局(定宽)

效果:

CSS布局 - 图1

  1. 写了宽高的版本 code
  2. 不写高度,用 padding 对齐。code
.clearfix::after {    /* IE9以下不支持 */
      content: '';
      display: block;
      clear: both;
    }
.clearfix {
      zoom: 1; /* 兼容IE6 */
 }
.header {
      background: #ddd;
      margin: 0 auto;  
      min-width:  500px; 
    }
.logo {
      width: 80px;      
      background: black;
      height: 40px;   
      line-height: 40px; /* 行高=高度,实现单行文本垂直居中 */
      text-align: center;  /* 单行文本水平居中 */
      color: white;
    }
.nav { /* 大宽度就不写死,根据内容自适应 */ 
      line-height: 24px; /* line-height可以控制字体的高度,24+8+8=40 左边logo和右边导航栏高度相等,就自动对齐了*/
      padding: 8px 0;
    }

.navItem {
      float: right;
      margin-left: 30px;
      background: #bbb;
    }
<div class="header clearfix">
    <div class="logo" style="float: left">
      logo
    </div>
    <div class="nav clearfix" style="float: right">
      <div class="navItem">导航1</div>
      <div class="navItem">导航2</div>
      <div class="navItem">导航3</div>
      <div class="navItem">导航4</div>
    </div>
</div>

用float实现均匀布局

  • 效果

CSS布局 - 图2

  • 方法1:原理是 float + 伪类 + 计算宽度 缺点: 使用了伪类,语法太高级,IE9以下的浏览器不支持code
    改进:float + 负 margin + 计算宽度 使用 -margin 法 来去除首尾子元素的 左、右margin。本质上是使用负margin 给元素增加宽度来容纳所有子元素,一种障眼法。改进后的优点: 兼容IE5的,兼容所有浏览器。不满8个卡片也是ok的。完整 code 。核心CSS代码如下css .pictures { width: 600px; margin: 0 auto; } .pictures-inner { margin: 0 -10px; } .picture { float: left; width: 135px; /* 宽度根据总宽度计算出来的 */ height: 135px; margin: 10px; background: #777; }

为什么设置负margin 可以给未显示设置 width 属性的元素(子元素宽度继承父元素,父元素显示设置 width 属性)增加宽度呢?复现一下 code

/* <div class="p"><div class="c"></div></div> */

.p {
  height: 100px;
  width: 210px;
  background: pink;
}
.c {
  height: 80px;
  margin: 0 -10px;
  background: red;
}

注意是父元素写 width ,子元素不写 width ,然后 子元素 使用 负margin 可以为子元素本身增加宽度,上述代码中 div.c最终渲染出的width是 230px

CSS布局 - 图3

flex 布局

父元素加 display: flex;justify-content: center;align-items: center;,那么子元素就水平垂直居中。

justify-content: space-between;两端对齐,多余的空间放到中间。

justify-content: space-around;多余的空间放到子元素的两边。

  • flex布局简单: code
    核心css代码:```css .pictures { width: 600px; margin: 0 auto; display: flex; flex-flow: row wrap; justify-content: space-between;

}

.picture { width: calc(25% - 10px); height: 135px; margin: 10px 0 0 0; background: #777; }

<br />效果如下:

![](https://i.loli.net/2019/05/03/5ccbfcbf0e3dc.png#alt=2HWADO8.png)

- 但是有个 bug,不满8个卡片,样式会有改变,跟卡片的个数和宽度有关系。

![](https://i.loli.net/2019/05/03/5ccc1b7dd8b83.png#alt=%28%29VR.png)

为了改进这个缺点,不使用 `justify-content: space-between;`属性,使用`display: flex; margin: 0 -10px;` **flex + 负margin 增加宽度** ,不用浮动。

<a name="b9c22ff3"></a>
### flex 最优版: flex + 负 margin

[flex 最优版 code](http://js.jirengu.com/kitiw/1/edit?html,output)

改进部分css核心代码:

```css
.pictures {
    width: 600px;
    margin: 0 auto;   
}
.pictures-inner {
    display: flex;
    flex-flow: row wrap;
    margin: 0 -10px;  /* 负 margin 增加宽度*/
}
.picture {
    width: calc(25% - 20px);
    height: 135px;
    margin: 10px 10px 0; 
    background: #777;
}

效果如图:

CSS布局 - 图4

优点:因为使用了 flex 布局,当卡片(.pictures)的总宽度未知时,也就是width: 600px;未知,使用width: calc(25% - 20px);能始终保持一行占4个卡片,此时卡片总宽度始终等于视口宽度,缩放浏览器时卡片宽度也自动缩放。

.pictures { 
  width: 600px; /* 跟banner等宽 */
  margin: 0 auto;
}

上面代码是我们在 最优 写的。

当卡片总宽度未知时,即:

.pictures { 
  margin: 0 auto;   // 没有设置width,这句也没用了
}

div.pictures宽度此时就是浏览器视口的宽度。效果如下图:
CSS布局 - 图5

CSS布局 - 图6

可以看到当卡片的总宽度未知时缩放浏览器时每张卡片宽度也自动缩放。

广告图:1:3布局,而且中间留有间隙空白

效果如下:

CSS布局 - 图7

  • 方法1:利用 div.inner留空白 。

完整code

展示核心 HTML + CSS

<div class="art">
    <div class="aside"><div class="aside-child">广告1</div></div>
    <div class="main"><div class="main-child">广告2</div></div>
</div>

注意上面代码中所有的 div 都是用来布局的。

.art {
    display: flex;
    width: 600px;    /* 用于布局宽度 */
    margin: 20px auto;
    text-align: center;  /* 水平居中,会被子继承 */
}
.aside {
    width: 25%;  /* 用于1:3的布局div */

}
.main {
    width: 75%;  /* 用于1:3的布局div */
}
.aside-child {
    margin-right: 20px;  /* 关键*/
    background: red;
    padding: 100px 0;  /* 垂直居中 */
}
.main-child {
    padding: 100px 0;
    background: green;
}
  • 法2: 完整 code
    展示核心 HTML + CSS```php
    <div class="art-1"><div class="content">广告图1</div></div>
    <div class="art-2"><div class="content">广告图1</div></div>
    
    <br />注意 `div.art` `div.art-1` `div.art-2`都是用来做布局的,除了布局的样式不要乱加东西。 `div.content`是用来添加内容的。也就是外面是 UI框架,里面是内容。```css
    .art {
    display: flex;
    width: 600px;
    margin: 20px auto;
    text-align: center;
    }
    .art-1 {
    width: calc(25% - 20px);
    margin-right: 20px;
    background: red;
    padding: 100px 0;
    }
    .art-2 {
    width: 75%;
    background: green;
    padding: 100px 0;
    }
    

目前页面效果

CSS布局 - 图8

现在将上面的布局做成手机布局

效果

CSS布局 - 图9

CSS布局 - 图10

核心步骤及代码

完整 code

1 加 meta:vp 不让页面缩放

<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">

2 使用媒体查询(@media)实现手机布局,把所有的width都设置为 width: auto;,手机端不要写死 width

flex 配合 media 就可以实现任何页面布局。一定记住 做响应式不要写死 width

给出核心 CSS:

/* 在之前的样式表后面加,注意样式优先级*/
/* 手机 */
@media (max-width: 426px){
  .nav {
    display: none;
  }
  .menu {
    display: block;
    line-height: 24px;
    padding: 8px 0;
  }
  .banner {
    width: auto;
  }
  .pictures {
    width: 320px;
    overflow: hidden;  /*关键*/
  }
  .picture {
    width: calc(50% - 20px);
  }
  .art {
    width: auto;
    flex-direction: column;
  }
  .aside {
    width: auto;

  }
  .main {
    width: auto;
  }
  .aside-child {
    margin-right: 0;
  }
}

上面代码的原理是,通过查看谷歌开发者工具-手机模式-Responsive,发现最小手机屏幕宽度是 320px,最大手机屏幕宽度是 425px 。这个代码主要是区别电脑(包括手提、平板)和 手机,默认样式是电脑的,(desktop first),同时使用媒体查询检测设备,若检测到当前屏幕的宽度小于 426px ,则说明当前展示网页的设备是手机,则应用手机网页样式,手机网页元素的width一律为 auto,除非不得不写宽度,比如上面:

.pictures {
    width: 320px;
    overflow: hidden;
}

以上就是做手机端响应式的步骤和原理。也没啥,响应式就是比PC端多了媒体查询

应该指出,移动端页面不要使用 百分比,在开发时直接使用设计稿 (640px 或者 750px )上标记的物理像素,写在 css 文件里 要记得转换成 css像素(一般都是标记100px, CSS 写 100px/2),然后再做 移动端适配(动态REM)。

因此,假设要做一个公司的官网,要求兼容手机和电脑,方案一是 写两套 HTML + CSS,手机一套,电脑一套,每套HTML + CSS 里面都做 REM自适应布局,尤其移动端 。方案二是 只写一套 HTML + CSS ,在 CSS里使用媒体查询 来更改样式,通过隐藏一些元素来适配移动设备和PC,而且移动端还要做动态REM。个人觉得方案一比较好一点,从一开始就是加载不同的 页面,开发时候条理也清晰,而且代码相对只有一套要小。在体验了几个小时的方案二以后,感觉容易出错。

解决图片变形问题

问如何解决 背景图div.banner 的拉伸问题,如果banner是图片,就很容易造成图片的拉伸,而且一般背景都是使用大图,.jpg 格式。

要想图片不拉伸,不要使用img标签

解决方法是使用 divbackground-image 属性,给div加背景图片,这样是最安全的,不会出现任何问题,图片不会拉伸变形的。

.banner {
  ...
  background: transparent url(https://i.loli.net/2019/05/03/5ccc47da7e1de.jpg) no-repeat center;
  /* 背景色透明,图片url,背景图不重复,图片居中显示*/
  background-size: cover;  /* 图片显示得更全 */
 ....
}

效果如图:

CSS布局 - 图11

完整 demo

实现固定比例的图片

如果要想实现固定比例的图片,搜索固定比例div

grid 布局

具体原理在另一篇博客,本博客注重的是应用。

直接用别人写好的UI框架

方法就是照着UI框架官方文档,粘贴复制。

优点:节约时间,不动脑。干业务啊

缺点:写个页面,引入了一堆类一堆代码。

平时开发布局技巧

要么左浮

要么 flex