Webcourse/02-CSS基础/07-浮动.md
2019-10-05 11:59:34 +08:00

977 lines
26 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

> 本文最初发表于[博客园](http://www.cnblogs.com/smyhvae/p/7297736.html),并在[GitHub](https://github.com/qianguyihao/Web)上持续更新。以下是正文。
## 文本主要内容
- 标准文档流
- 标准文档流的特性
- 行内元素和块级元素
- 行内元素和块级元素的相互转换
- 浮动的性质
- 浮动的清除
- 浏览器的兼容性问题
- 浮动中margin相关
- 关于margin的IE6兼容问题
## 标准文档流
宏观地讲我们的web页面和photoshop等设计软件有本质的区别web页面的制作是个必须从上而下织毛衣而设计软件想往哪里画个东西都能画
### 标准文档流的特性
**1空白折叠现象**
无论多少个空格换行tab都会折叠为一个空格
比如如果我们想让img标签之间没有空隙必须紧密连接
```
<img src="images/0.jpg" /><img src="images/1.jpg" /><img src="images/2.jpg" />
```
**2高矮不齐底边对齐**
举例如下
![](http://img.smyhvae.com/20170729_1508_2.png)
**3自动换行一行写不满换行写**
### 行内元素和块级元素
学习的初期我们就要知道标准文档流等级森严标签分为两种等级
- 行内元素
- 块级元素
我们可以举一个例子看看块级元素和行内元素的区别
![](http://img.smyhvae.com/20170729_1529_2.png)
上图中可以看到`h1`标签是块级元素占据了整行`span`标签是行内元素只占据内容这一部分
现在我们尝试给两个标签设置宽高效果如下
![](http://img.smyhvae.com/20170729_1532_2.png)
上图中我们尝试给两个标签设置宽高但发现宽高属性只对块级元素`h1`生效于是我们可以做出如下总结
**行内元素和块级元素的区别**非常重要
行内元素
- 与其他行内元素并排
- 不能设置宽默认的宽度就是文字的宽度
块级元素
- 霸占一行不能与其他任何元素并列
- 能接受宽如果不设置宽度那么宽度将默认变为父亲的100%
**行内元素和块级元素的分类**
在以前的HTML知识中我们已经将标签分过类当时分为了文本级容器级
从HTML的角度来讲标签分为
- 文本级标签pspanabiuem
- 容器级标签divh系列lidtdd
> PS为甚么说p是文本级标签呢因为p里面只能放文字&图片&表单元素p里面不能放h和ulp里面也不能放p
现在从CSS的角度讲CSS的分类和上面的很像就p不一样
- 行内元素除了p之外所有的文本级标签都是行内元素p是个文本级但是是个块级元素
- 块级元素所有的容器级标签都是块级元素还有p标签
我们把上面的分类画一个图即可一目了然
![](http://img.smyhvae.com/20170729_1545.png)
### 行内元素和块级元素的相互转换
我们可以通过`display`属性将块级元素和行内元素进行相互转换display即显示模式
#### 块级元素可以转换为行内元素
一旦给一个块级元素比如div设置
```
display: inline;
```
那么这个标签将立即变为行内元素此时它和一个span无异inline就是行内也就是说
- 此时这个div不能设置宽度高度
- 此时这个div可以和别人并排了
举例如下
![](http://img.smyhvae.com/20170729_1629.png)
#### 行内元素转换为块级元素
同样的道理一旦给一个行内元素比如span设置
```
display: block;
```
那么这个标签将立即变为块级元素此时它和一个div无异block的意思也就是说
- 此时这个span能够设置宽度高度
- 此时这个span必须霸占一行了别人无法和他并排
- 如果不设置宽度将撑满父亲
举例如下
![](http://img.smyhvae.com/20170729_1638.png)
标准流里面的限制非常多导致很多页面效果无法实现如果我们现在就要并排并且就要设置宽高那该怎么办呢办法是移民**脱离标准流**
css中一共有三种手段使一个元素脱离标准文档流
- 1浮动
- 2绝对定位
- 3固定定位
这便引出我们今天要讲的内容浮动
## 浮动的性质
> 浮动是css里面布局用的最多的属性
现在有两个div分别设置宽高我们知道它们的效果如下
![](http://img.smyhvae.com/20170729_1722.png)
此时如果给这两个div增加一个浮动属性比如`float: left;`效果如下
![](http://img.smyhvae.com/20170729_1723.png)
这就达到了浮动的效果此时两个元素并排了并且两个元素都能够设置宽度高度了这在上一段的标准流中不能实现
浮动想学好一定要知道三个性质接下来讲一讲
### 性质1浮动的元素脱标
脱标即脱离标准流我们来看几个例子
证明1
![](http://img.smyhvae.com/20170729_2028.png)
上图中在默认情况下两个div标签是上下进行排列的现在由于float属性让上图中的第一个`<div>`标签出现了浮动于是这个标签在另外一个层面上进行排列而第二个`<div>`还在自己的层面上遵从标准流进行排列
证明2
![](http://img.smyhvae.com/20180111_2320.png)
上图中span标签在标准流中是不能设置宽高的因为是行内元素但是一旦设置为浮动之后即使不转成块级元素也能够设置宽高了
所以能够证明一件事**一旦一个元素浮动了那么将能够并排了并且能够设置宽高了无论它原来是个div还是个span**所有标签浮动之后已经不区分行内块级了
### 性质2浮动的元素互相贴靠
我们来看一个例子就明白了
我们给三个div均设置了`float: left;`属性之后然后设置宽高当改变浏览器窗口大小时可以看到div的贴靠效果
![](http://img.smyhvae.com/20170730_1910.gif)
上图显示3号如果有足够空间那么就会靠着2号如果没有足够的空间那么会靠着1号大哥
如果没有足够的空间靠着1号大哥3号自己去贴左墙
不过3号自己去贴墙的时候注意
![](http://img.smyhvae.com/20170730_1928.gif)
上图显示3号贴左墙的时候并不会往1号里面挤
同样float还有一个属性值是`right`这个和属性值`left`是对称的
### 性质3浮动的元素有字围效果
来看一张图就明白了我们让div浮动p不浮动
![](http://img.smyhvae.com/20170730_2005.png)
上图中我们发现**div挡住了p但不会挡住p中的文字**形成字围效果
总结**标准流中的文字不会被浮动的盒子遮挡住**文字就像水一样
关于浮动我们要强调一点浮动这个东西为避免混乱我们在初期一定要遵循一个原则**永远不是一个东西单独浮动浮动都是一起浮动要浮动大家都浮动**
### 性质4收缩
收缩一个浮动的元素如果没有设置width那么将自动收缩为内容的宽度这点非常像行内元素
举例如下
![](http://img.smyhvae.com/20170801_1720.png)
上图中div本身是块级元素如果不设置width它会单独霸占整行但是设置div浮动后它会收缩
### 浮动的补充做网站时注意
![](http://img.smyhvae.com/20170731_2248.png)
上图所示将para1和para2设置为浮动它们是div的儿子此时para1+para2的宽度小于div的宽度效果如上图所示可如果设置para1+para2的宽度大于div的宽度我们会发现para2掉下来了
![](http://img.smyhvae.com/20170731_2252_2.png)
### 布置一个作业
布置一个作业要求实现下面的效果
![](http://img.smyhvae.com/20170801_0858.png)
为实现上方效果代码如下
```html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>Document</title>
<style type="text/css">
*{
margin: 0;
padding: 0;
}
.header{
width: 970px;
height: 103px;
/*居中。这个语句的意思是:居中:*/
margin: 0 auto;
}
.header .logo{
float: left;
width: 277px;
height: 103px;
background-color: red;
}
.header .language{
float: right;
width: 137px;
height: 49px;
background-color: green;
margin-bottom: 8px;
}
.header .nav{
float: right;
width: 679px;
height: 46px;
background-color: green;
}
.content{
width: 970px;
height: 435px;
/*居中,这个语句今天没讲,你照抄,就是居中:*/
margin: 0 auto;
margin-top: 10px;
}
.content .banner{
float: left;
width: 310px;
height: 435px;
background-color: gold;
margin-right: 10px;
}
.content .rightPart{
float: left;
width: 650px;
height: 435px;
}
.content .rightPart .main{
width: 650px;
height: 400px;
margin-bottom: 10px;
}
.content .rightPart .links{
width: 650px;
height: 25px;
background-color: blue;
}
.content .rightPart .main .news{
float: left;
width: 450px;
height: 400px;
}
.content .rightPart .main .hotpic{
float: left;
width: 190px;
height: 400px;
background-color: purple;
margin-left: 10px;
}
.content .rightPart .main .news .news1{
width: 450px;
height: 240px;
background-color: skyblue;
margin-bottom: 10px;
}
.content .rightPart .main .news .news2{
width: 450px;
height: 110px;
background-color: skyblue;
margin-bottom: 10px;
}
.content .rightPart .main .news .news3{
width: 450px;
height: 30px;
background-color: skyblue;
}
.footer{
width: 970px;
height: 35px;
background-color: pink;
/*没学,就是居中:*/
margin: 0 auto;
margin-top: 10px;
}
</style>
</head>
<body>
<!-- 头部 -->
<div class="header">
<div class="logo">logo</div>
<div class="language">语言选择</div>
<div class="nav">导航条</div>
</div>
<!-- 主要内容 -->
<div class="content">
<div class="banner">大广告</div>
<div class="rightPart">
<div class="main">
<div class="news">
<div class="news1"></div>
<div class="news2"></div>
<div class="news3"></div>
</div>
<div class="hotpic"></div>
</div>
<div class="links"></div>
</div>
</div>
<!-- 页尾 -->
<div class="footer"></div>
</body>
</html>
```
其实这个页面的布局是下面这个网站
![](http://img.smyhvae.com/20170801_0900.png)
## 浮动的清除
> 这里所说的清除浮动指的是清除浮动与浮动之间的影响
### 前言
通过上面这个例子我们发现此例中的网页就是通过浮动实现并排的
比如说一个网页有headercontentfooter这三部分就拿content部分来举例如果设置content的儿子为浮动但是这个儿子又是一个全新的标准流于是儿子的儿子仍然在标准流里
从学习浮动的第一天起我们就要明白浮动有开始就要有清除我们先来做个实验
下面这个例子有两个块级元素divdiv没有任何属性每个div里有li效果如下
![](http://img.smyhvae.com/20170801_2122.png)
上面这个例子很简单可如果我们给里面的`<li>`标签加浮动效果却成了下面这个样子
代码如下
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
*{
}
li{
float: left;
width: 100px;
height: 20px;
background-color: pink;
}
</style>
</head>
<body>
<div class="box1">
<ul>
<li>生命壹号1</li>
<li>生命壹号2</li>
<li>生命壹号3</li>
<li>生命壹号4</li>
</ul>
</div>
<div class="box2">
<ul>
<li>许嵩1</li>
<li>许嵩2</li>
<li>许嵩3</li>
<li>许嵩4</li>
</ul>
</div>
</body>
</html>
```
效果如下
![](http://img.smyhvae.com/20170801_2137.png)
上图中我们发现第二组中的第1个li去贴靠第一组中的最后一个li了我们本以为这些li会分成两排
这便引出我们要讲的清除浮动的第一种方式
那该怎么解决呢
### 方法1给浮动元素的祖先元素加高度
造成前言中这个现象的根本原因是li的**父亲div没有设置高度**导致这两个div的高度均为0px我们可以通过网页的审查元素进行查看div的高度为零导致不能给自己浮动的孩子撑起一个容器
撑不起一个容器导致自己的孩子没办法在自己的内部进行正确的浮动
现在就算给这个div设置高度可如果div自己的高度小于孩子的高度也会出现不正常的现象
![](http://img.smyhvae.com/20170801_2152.png)
给div设置一个正确的合适的高度至少保证高度大于儿子的高度就可以看到正确的现象
![](http://img.smyhvae.com/20170801_2153.png)
**总结**
**如果一个元素要浮动那么它的祖先元素一定要有高度**
**有高度的盒子才能关住浮动**记住这句过来人的经验之语
只要浮动在一个有高度的盒子中那么这个浮动就不会影响后面的浮动元素所以就是清除浮动带来的影响了
![](http://img.smyhvae.com/20170801_2200.png)
![](http://img.smyhvae.com/20170801_2201.png)
### 方法2clear:both;
网页制作中高度height其实很少出现为什么因为能被内容撑高也就是说刚刚我们讲解的方法1工作中用得很少
那么能不能不写height也把浮动清除了呢也让浮动之间互不影响呢
这个时候我们可以使用`clear:both;`这个属性如下
![](http://img.smyhvae.com/20170801_2233.png)
```
clear:both;
```
clear就是清除both指的是左浮动右浮动都要清除`clear:both`的意思就是**不允许左侧和右侧有浮动对象**
这种方法有一个非常大的致命的问题**它所在的标签margin属性失效了**读者可以试试看
margin失效的本质原因是上图中的box1和box2高度为零
### 方法3隔墙法
上面这个例子中为了防止第二个div贴靠到第二个div我们可以在这两个div中间用一个新的div隔开然后给这个新的div设置`clear: both;`属性同时既然这个新的div无法设置margin属性我们可以给它设置height以达到margin的效果曲线救国这便是隔墙法
我们看看例子效果就知道了
![](http://img.smyhvae.com/20170802_1109.png)
上图这个例子就是隔墙法
**内墙法**
近些年有演化出了内墙法
![](http://img.smyhvae.com/20170802_1123.png)
上面这个图非常重要当作内墙法的公式先记下来
为了讲内墙法我们先记住一句重要的话**一个父亲是不能被浮动的儿子撑出高度的**举例如下
1我们在一个div里放一个有宽高的p效果如下很简单
![](http://img.smyhvae.com/20170802_1716.png)
2可如果在此基础之上给p设置浮动却发现父亲div没有高度了
![](http://img.smyhvae.com/20170802_1730.png)
3此时我么可以在div的里面放一个div作为内墙就可以让父亲div恢复高度
![](http://img.smyhvae.com/20170802_1812.png)
于是我们采用内墙法解决前言中的问题
![](http://img.smyhvae.com/20170802_1834.png)
与外墙法相比内墙法的优势本质区别在于内墙法可以给它所在的家撑出宽度让box1有高box1的高度可以自适应内容
而外墙法虽然一道墙可以把两个div隔开但是这两个div没有高也就是说无法wrap_content
### 清除浮动方法4overflow:hidden;
我们可以使用如下属性
```
overflow:hidden;
```
overflow即溢出 hidden即隐藏这个属性的意思是溢出隐藏顾名思义所有溢出边框的内容都要隐藏掉如下
![](http://img.smyhvae.com/20170804_1449.png)
上图显示`overflow:hidden;`的本意是清除溢出到盒子外面的文字但是前端开发工程师发现了它能做偏方如下
一个父亲不能被自己浮动的儿子撑出高度但是只要给父亲加上`overflow:hidden`; 那么父亲就能被儿子撑出高了这是一个偏方
举个例子
![](http://img.smyhvae.com/20170804_1920.png)
那么对于前言中的例子我们同样可以使用这一属性
![](http://img.smyhvae.com/20170804_1934.png)
## 浮动清除的总结
> 我们在上一段讲了四种清除浮动的方法本段来进行一个总结
浮动的元素只能被有高度的盒子关住 也就是说如果盒子内部有浮动这个盒子有高那么妥妥的浮动不会互相影响
### 1加高法
工作上我们绝对不会给所有的盒子加高度这是因为麻烦并且不能适应页面的快速变化
```html
<div> //设置height
<p></p>
<p></p>
<p></p>
</div>
<div> //设置height
<p></p>
<p></p>
<p></p>
</div>
```
### 2`clear:both;`
最简单的清除浮动的方法就是给盒子增加clear:both表示自己的内部元素不受其他盒子的影响
```html
<div>
<p></p>
<p></p>
<p></p>
</div>
<div> //clear:both;
<p></p>
<p></p>
<p></p>
</div>
```
浮动确实被清除了不会互相影响了但是有一个问题就是margin失效两个div之间没有任何的间隙了
### 3隔墙法
在两部分浮动元素中间建一个墙隔开两部分浮动让后面的浮动元素不去追前面的浮动元素
墙用自己的身体当做了间隙
```html
<div>
<p></p>
<p></p>
<p></p>
</div>
<div class="cl h10"></div>
<div>
<p></p>
<p></p>
<p></p>
</div>
```
我们发现隔墙法好用但是第一个div还是没有高度如果我们现在想让第一个div自动根据自己的儿子撑出高度我们就要想一些小伎俩
内墙法
```html
<div>
<p></p>
<p></p>
<p></p>
<div class="cl h10"></div>
</div>
<div>
<p></p>
<p></p>
<p></p>
</div>
```
内墙法的优点就是不仅仅能够让后部分的p不去追前部分的p了并且能把第一个div撑出高度这样这个div的背景边框就能够根据p的高度来撑开了
### 4`overflow:hidden;`
这个属性的本意就是将所有溢出盒子的内容隐藏掉但是我们发现这个东西能够用于浮动的清除
我们知道一个父亲不能被自己浮动的儿子撑出高度但是如果这个父亲加上了overflow:hidden那么这个父亲就能够被浮动的儿子撑出高度了这个现象不能解释就是浏览器的偏方
并且,overflow:hidden;能够让margin生效
**清除浮动的例子**
我们现在举个例子要求实现下图中无序列表部分的效果
![](http://img.smyhvae.com/20170804_2321.png)
对比一下我们讲的四种清除浮动的方法如果用外墙法ul中不能插入div标签因为ul中只能插入li如果插入li的墙会浪费语义如果用内墙法不美观综合对比还是用第四种方法来实现吧这会让标签显得极其干净整洁
![](http://img.smyhvae.com/20170805_1615.png)
上方代码中如果没有加`overflow:hidden;`那么第二行的li会紧跟着第一行li的后面
## 浏览器的兼容性问题
> 讲一下上述知识点涉及到的浏览器兼容问题
### 兼容性1微型盒子
**兼容性的第一条**IE6不支持小于12px的盒子任何小于12px的盒子在IE6中看都大IE 6不支持微型盒子
举个例子我们设置一个height为 5px 宽度为 200px的盒子看下在IE 8 IE 6中的显示效果
![](http://img.smyhvae.com/20170805_1726.png)
解决办法很简单就是将盒子的字号大小设置为**小于盒子的高**比如如果盒子的高为5px那就把font-size设置为0px(0px < 5px)如下
```
height: 5px;
_font-size: 0px;
```
我们现在介绍一下浏览器hackhack就是黑客就是使用浏览器提供的后门针对某一种浏览器做兼容
IE6留了一个**后门**只要给css属性之前加上**下划线**这个属性就是IE6的专有属性
比如说我们给背景颜色这个属性加上下划线就变成了`_background-color: green;`效果如下
![](http://img.smyhvae.com/20170805_2026.png)
于是乎为了解决微型盒子即height小于12px的问题正确写法注意不要忘记下划线
```
height: 10px;
_font-size:0;
```
### 兼容性2
**兼容性的第二条**IE6不支持用`overflow:hidden;`来清除浮动
解决办法以毒攻毒追加一条
```
_zoom:1;
```
完整写法
```
overflow: hidden;
_zoom:1;
```
实际上`_zoom:1;`能够触发浏览器hasLayout机制这个机制不要深究了因为只有IE6有我们只需要让IE6好用具体的实现机制可以自行查阅
需要强调的是`overflow:hidden;`的本意就是让溢出盒子的border的内容隐藏这个功能是IE6兼容的不兼容的是`overflow:hidden;`清除浮动的时候
**总结**
我们刚才学习的两个IE6的兼容问题都是通过多写一条hack来解决的这个我们称为伴生属性即两个属性要写一起写
属性1
```
height:6px;
_font-size:0;
```
属性2
```
overflow:hidden;
_zoom:1;
```
## margin相关
> 我们来讲一下浮动中和margin相关的知识
### margin塌陷/margin重叠
**标准文档流中竖直方向的margin不叠加**较大的值**作为margin(水平方向的margin是可以叠加的即水平方向没有塌陷现象)如下图所示
![](http://img.smyhvae.com/20170805_0904.png)
如果不在标准流比如盒子都浮动了那么两个盒子之间是没有塌陷现象的
### 盒子居中`margin:0 auto;`
margin的值可以为auto表示自动当leftright两个方向都是auto的时候盒子居中了
```
margin-left: auto;
margin-right: auto;
```
盒子居中的简写为
```
margin:0 auto;
```
对上方代码的理解上下的margin为0左右的margin都尽可能的大于是就居中了
注意
- 1只有标准流的盒子才能使用`margin:0 auto;`居中也就是说当一个盒子浮动了绝对定位了固定定位了都不能使用margin:0 auto;
- 2使用`margin:0 auto;`的盒子必须有width有明确的width可以这样理解如果没有明确的witdh那么它的witdh就是霸占整行没有意义
- 3`margin:0 auto;`是让盒子居中不是让盒子里的文本居中文本的居中要使用`text-align:center;`
对上面的第三条总结一下非常重要
```
margin:0 auto; //让这个div自己在大容器中的水平方向上居中。
text-align: center; //让这个div内部的文本居中。
```
顺便普及一下知识text-align还有
```
text-align:left; //没啥用,因为默认居左
text-align:right; //文本居右
```
### 善于使用父亲的padding而不是儿子的margin
我们来看一个奇怪的现象现在有下面这样一个结构div中放一个p
```
<div>
<p></p>
</div>
```
上面的结构中我们尝试通过给儿子`p`一个`margin-top:50px;`的属性让其与父亲保持50px的上边距结果却看到了下面的奇怪的现象
![](http://img.smyhvae.com/20170806_1537.png)
此时我们给父亲div加一个border属性就正常了
![](http://img.smyhvae.com/20170806_1544.png)
如果父亲没有border那么儿子的margin实际上踹的是踹的是这所以父亲整体也掉下来了
**margin这个属性本质上描述的是兄弟和兄弟之间的距离 最好不要用这个marign表达父子之间的距离**
所以如果要表达父子之间的距离我们一定要善于使用父亲的padding而不是儿子的margin
## 关于margin的IE6兼容问题
### IE6的双倍margin的bug
当出现连续浮动的元素携带与浮动方向相同的margin时队首的元素会双倍marign
```
<ul>
<li></li>
<li></li>
<li></li>
</ul>
```
![](http://img.smyhvae.com/20170806_1558.png)
解决方案
1使浮动的方向和margin的方向相反
所以你就会发现我们特别喜欢浮动的方向和margin的方向相反并且前端开发工程师把这个当做习惯了
```
float: left;
margin-right: 40px;
```
2使用hack没必要别惯着这个IE6
单独给队首的元素写一个一半的margin
```
<li class="no1"></li>
```
```
ul li.no1{
_margin-left:20px;
}
```
PS双倍margin的问题面试经常问哦
### IE6的3px bug
![](http://img.smyhvae.com/20170806_1616.png)
解决办法不用管因为根本就不允许用儿子踹父亲即描述父子之间的距离请用padding而不是margin所以如果你出现了3px bug说明你的代码不标准
IE6千万不要跟他死坑较劲它不配 格调要高我们讲IE6的兼容性问题就是为了增加面试的成功率不是为了成为IE6的专家
## Fireworks和others
### Fireworks
fireworks是Adobe公司的一个设计软件功能非常多我们以后用啥讲啥Fireworks的默认文件格式是png
标尺的快捷键Ctrl + Alt+ R
### others
首行缩进两个汉字
```
text-indent: 2em;
```
上方属性中单位比较奇怪叫做emem就是汉字的一个宽度indent的意思是缩进
## 我的公众号
想学习**代码之外的技能**不妨关注我的微信公众号**千古壹号**id`qianguyihao`
扫一扫你将发现另一个全新的世界而这将是一场美丽的意外
![](http://img.smyhvae.com/20190101.png)