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;
.clearfix::after{
content:'';
display:block;
clear:both;
}
.clearfix{
zoom: 1;
}
两栏布局(百分比布局,弹性布局)
- 原理:
div.parent
不定宽,内部两个div.child
固定形成弹性布局。
注意上面都是不定宽的版本,定宽版本在这。
两栏布局(定宽)
效果:
.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实现均匀布局
- 效果
- 方法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
。
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;
}
效果如图:
优点:因为使用了 flex
布局,当卡片(.pictures
)的总宽度未知时,也就是width: 600px;
未知,使用width: calc(25% - 20px);
能始终保持一行占4个卡片,此时卡片总宽度始终等于视口宽度,缩放浏览器时卡片宽度也自动缩放。
.pictures {
width: 600px; /* 跟banner等宽 */
margin: 0 auto;
}
上面代码是我们在 最优 写的。
当卡片总宽度未知时,即:
.pictures {
margin: 0 auto; // 没有设置width,这句也没用了
}
div.pictures
宽度此时就是浏览器视口的宽度。效果如下图:
可以看到当卡片的总宽度未知时,缩放浏览器时每张卡片宽度也自动缩放。
广告图:1:3布局,而且中间留有间隙空白
效果如下:
- 方法1:利用
div.inner
留空白 。
展示核心 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; }
目前页面效果
现在将上面的布局做成手机布局
效果
核心步骤及代码
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标签。
解决方法是使用 div
的background-image
属性,给div加背景图片,这样是最安全的,不会出现任何问题,图片不会拉伸变形的。
.banner {
...
background: transparent url(https://i.loli.net/2019/05/03/5ccc47da7e1de.jpg) no-repeat center;
/* 背景色透明,图片url,背景图不重复,图片居中显示*/
background-size: cover; /* 图片显示得更全 */
....
}
效果如图:
实现固定比例的图片
如果要想实现固定比例的图片,搜索固定比例div
grid 布局
具体原理在另一篇博客,本博客注重的是应用。
直接用别人写好的UI框架
方法就是照着UI框架官方文档,粘贴复制。
优点:节约时间,不动脑。干业务啊
缺点:写个页面,引入了一堆类一堆代码。