CSS定位元素

定位元素(一)


一、 理解盒子模型

每一个元素都会在页面上生成一个盒子,HTML页面实际上就是由一堆盒子组成的,默认情况下,每个盒子的边框都不可见,背景也是透明的。

那么,盒模型有哪些属性呢,总的来说盒子的属性可分为三组:

  • border(边框) 可以设置边框的宽窄、样式和颜色
  • padding(内边距)可以设置盒子内容区与边框的间距
  • margin(外边距)可以设置盒子与相邻元素的间距

一个盒子模型如下图所示
Alt text


1. 盒子边框(border)

盒子边框有 3 个相关属性

  • boder-width 可以使用 thin、medium、thick等文本值,也可以使用除百分比和负值之外的任何绝对值。
  • border-style 有none、hidden、dotted(虚线)、dashed、solid、double(双实线)、groove、ridge、inset、outset(这四个是边框的内凹外凹)等值。
  • border-color 可以使用包括 RGB 、HSL 在内的任意颜色值和关键字。

其中boder-width 、border-style 的值在不同浏览器中的显示可能有所不同。

默认情况下,边框的三个属性值分别为:

  • border-width : medium
  • border-style : none
  • border-color : black

因此默认情况下不会显示盒子边框,开发中我们常常会临时设定盒子的边框,为了快速把盒子边框显示出来,我们可以应用这条规则

1
p { border:solid 1px ; }


2. 盒子的内边距(padding)

内边距是盒子内容区与盒子边框之间的距离。

这是没有加 padding 的 p 元素
Alt text

当我们给他加上 10px 的 padding 之后
Alt text

注意,由于内边距在盒子的内部,所以padding也会取得盒子的背景
仔细两幅图可以发现,内边距实际加在了声明的盒子的宽度之上(后面解释)


3. 盒子的外边距(margin)

我们举三组标题和段落来说明盒子的外边距

Alt text

第一组和第二组都使用默认的样式,而第二组跟第一组的区别就是多了边框,对比之后,我们可以看到浏览器给标题和段落都设定了默认的 margin 样式。第三组我设定了 margin : 0 ,可以看到该组的标题和段落全部紧挨在一起。
因此,建议大家在写网页的时候,把这条规则作为样式表的第一条规则:

1
*{margin:0;padding:0;}

这个也叫重置CSS样式,作用是为了将浏览器给元素添加的默认样式都清除。网上有很多重置样式表(如 reset.css),还对很多元素在跨浏览器显示时的外观进行了标准化,想了解更多可以自行百度“CSS重置”

关于外边距需要注意的几点

  • 垂直外边距会叠加

假设有三个段落,我们均设定

1
p { margin-top:50px; margin-bottom:3opx;}

你可能会认为每两个段落之间的间距是 50 + 30 = 80px ,这种认知错误的,实际上他们之间的间距是50px!

像这样上下外边距相遇时,它们就会相互重叠,直至一个外边距碰到另一个元素的边框,第二段较宽的上外边距会碰到第一段的边框,也就是说,较宽的外边距决 定两个元素终离多远,这就叫做外边距的叠加。

注意,只有垂直外边距会叠加,水平外边距并不会叠加。对于水平相邻的元素他们的水平间距是相邻外边距之和。

  • 外边距的单位

根据经验,为文本元素设置外边距时通常需要混合使用不同的单位。
比如说,一个段落的左、右外边距可以使用像素,以便该段文本始终与包含元素边界保持固定间 距,不受字号变大或变小的影响。而对于上、下外边距,以 em为单位则可以让段间 距随字号变化而相应增大或缩小。

比如:

1
2
/*这里使用了简写属性把上、下外边距设置为.75em,把左、右外边距设置为 30 像素*/ 
p {font-size:1em; margin:.75em 30px;}

这样,段落的垂直间距始终会保持为字体高度的四分之三(上下外边距都是.75em, 叠加后还是.75em)。如果用户增大了字号,那么不仅段落中的文本会变大,段间距也会成比例变大。这样,页面的整体布局就会比较协调一致。与此同时,使用像素 单位的左、右外边距不会改变。



二、 盒子的大小是如何变化的

接下来我们用两种盒子来说明盒子的具体大小是如何变化的。

  • 一种是没有宽度的盒子,既没有设定 width 属性。
  • 另一种是带有宽度的盒子,我们设定 width :400px

1. 没有宽度的盒子

没有设定 width 属性的块级元素盒子,他的 width 属性默认值是 auto ,结果会让元素的宽度扩展到父元素同宽。
接下来我们给一个段落添加以下样式

1
2
3
4
5
6
7
8
9
body {
font-family:helvetica, arial, sans-serif;
font-size:1em; margin:0px;
background-color:#caebff;
}
p {
margin:0;
background-color:#fff;
}

显示效果如下:
Alt text

可以看到,段落文本扩展到了body元素同宽。
接下来,我们给文本左右两侧添加内边距 padding:0 20px;
Alt text

可以看到,添加了内边距之后,文本块的宽度会减少。
接下来,我们给文本左右两侧添加边框 border-width:0 6px 0 6px;
Alt text

虽然不太明显,但实际上文本块的宽度又减少了。
最后,我们给左右两侧再加上外边距 margin:0 30px;
Alt text

果不其然,文本块的宽度再一次减少

结论:

没有(就是没有设置 width 的)宽度的元素始终会扩展到填满其父元素的宽度为止。添加水平边框、内边距和外边距,会导致内容宽度减少,减少量等于水平边框、内边距和外边距的和


2. 带有宽度的盒子

我们再用和上面没有宽度的盒子一样的方法,来看看带有宽度的盒子的大小是怎样变化的。
给段落添加样式

1
2
3
4
5
6
7
8
9
10
body {
ont-family:helvetica, arial, sans-serif;
font-size:1em; margin:0px;
background-color:#caebff;
}
p {
width:400px; /* 设定元素宽度为400px*/
margin:0;
background-color:#fff;
}

Alt text

可以看到,明确设定 width 属性后,块级元素就不会再扩展到与父元素(即 body)同宽了。
一样的,我们添加 20px 的内边距
Alt text

这一次,文本块的的宽度并由变化,反而使的元素比原来宽了 40px
一样的,我们再给元素添加 6px 的边框

Alt text

最后,添加外边距

Alt text

为此我们可以得出,带有宽度的盒子模型大小变化的结论:

为设定了宽度的盒子添加边框、内边距和外边距,会导致盒子扩展得更宽。实际上,盒子的 width 属性设定的只是盒子内容区的宽度,而非盒子要占据的水平宽度。

总之,关于盒子大小的变化,我们需要记住一点
设定了元素的 width 属性后,再给元素添加边框、内边距和 外边距,元素的行为与默认的 auto 状态下会有截然不同的表现。



三、 浮动与清除(float clear)


1. 浮动

浮动,意思就是把元素从常规文档流中拿出来。
当你浮动一个元素的时候……这个元素就好像在说:‘尽量把我往上放,能放多高放多高,直到碰到某个元素的边界为止。

浮动元素脱离了常规文档流之后,原来紧跟其后的元素就会在空间允许的情况下,向上提升到与浮动元素平起平坐。

CSS 设计 float 属性的主要目的,是为了实现文本绕排图片的效果。然而,这个属性也成了创建多栏布局简单的方式

让我们先从文本绕排图片这个例子来认识浮动吧!

文本绕排图片

示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
<style type="text/css">
img{
margin: 0 4px 4px 0;
}
p{
margin: 0;
border: solid 1px red;
}
</style>
<body>
<img src="pic03.jpg" />
<p>Lorem ipsum dolor sit amet...</p>
</body>

原始效果
Alt text

可以看到处在常规文档流中的图片跟段落这两个块级元素竖直排列在一起。

接下来,我们要实现文字绕排文字效果了,怎么做呢?

就是让图片浮动起来,我们给图片添加以下样式 img { float:left }
Alt text

解释:

在你浮动一张图片或者其他元素时,你是在要求浏览器把它往上方推,直到它碰到父元素(也就是 body 元素)的内边界。后面的段落(带灰色边框) 不再认为浮动元素在文档流中位于它的前面了,因而它会占据父元素左上角的位置。 不过,它的内容(文本)会绕开浮动的图片。

注意:

由于图片自身带有宽度,因此在浮动的时候无需设定宽度。然而在浮动非图片元素时,必须给非图片元素设定宽度,否则后果难以预料

2. 围住浮动元素的三种方法

上面我们讲到,当一个元素浮动后,他就脱离了文档流,因而它也不被包含在父元素之内了,因此它也可能会对布局产生破坏性的影响。那么,我们该怎么控制浮动的元素呢?

接下来介绍把浮动元素“控制住”的三种方法

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<style type="text/css">
section {
margin: 0 0 10px 0;
border: solid 1px red;
}
p {
margin: 0;
}
footer{
border: solid 1px red;
}
</style>
<section>
<img src="pic03.jpg" />
<p>It's fun to float</p>
</section>
<footer>
<p>Lorem ipsum dolor sit amet....</p>
</footer>

原始效果
Alt text

现在,一切正常,所有元素自上而下堆叠在一起,接下来,我们让图片标题位于图片右侧,该怎么做呢?从上一节我们知道,就是让图片浮动起来。给图片添加 img { float: left}

Alt text

OK,现在图片标题以及在图片右侧啦。

但是我们也看到,由于图片浮动了,现在图片已经不在父元素section里面了,换句话说,图片脱离了常规文档流,这也就导致了父元素section收缩到了只包含文本高度的高度。 而且,footer元素也被提上来了,紧挨着前一个块级元素,这可不是我们想要的。

所以,我们必须得把浮动元素“控制住”。

方法一:给浮动元素的父元素添加 overflow:hidden
overflow:hidden的用途
> overflow:hidden 原本是使包含元素依然保持其设定的宽度,而超过的子内容则会被容器剪切掉(不被显示),防止包含元素被超大内容撑大。
> **除此之外,overflow:hidden 还有另一个作用,即它能可靠地迫使父元素包含其浮动的子元素。**

现在我们试试给父元素 section 加上overflow : hidden
Alt text

确认过眼神,是我们想要的效果!footer回到了我们期望的位置

方法二:同时浮动父元素

促使父元素包围其浮动子元素的方法,是也让父元素也浮动起来。
来,我们先试试给 section 添加float:left,让父元素浮动起来

Alt text

结果跟我们想象中的不太一样呢,别急,回想一下我们之前的知识点,在浮动非图片元素时,我们得给他们加一个宽度对吧。那么,为什么呢?

原因是,当我们浮动任何元素时,不管其是否有子元素,不管其子元素是否浮动,他都会紧紧地包裹住它的内容,或者是,它的子元素。

那就好解决了,我们给 section 加一个宽度width:100%,让它和浏览器同宽就好了。
Alt text

这效果是对了,但怎么看起来总觉得怪怪的呢?原来是footer给挤上去了!

再回想一下,当我们浮动了一个元素,原本紧跟其后的元素也会在空间允许的情况下不断地往上挤。因此,footer 也无一例外地努力挤到了 section 的旁边了。

那么,我们该怎样使得 footer 依然呆在 section 下方呢?
答案是给footer应用一个清除 clear:left ,这样被清除的元素就不会被提升到浮动元素的旁边。
Alt text


方法三:给父元素添加 .clearfix:after 规则

.clearfix:after 规则:

1
2
3
4
5
6
7
.clearfix:after{
content:".";
display:block;
height:0;
visibility:hidden;
clear:both;
}

说明:

这个 .clearfix 规则只添加了一个清除的包含句点作为非浮动元素(必须得有内容,而句点是最小的内容)。规则中的其他声明是 为了确保这个伪元素没有高度,而且在页面上不可见。
使用 clear:both 意味着 section 中新增的子元素会清除左、右浮动元素(位于左、右浮 动元素下方)。这里当然可以只用 left,但 both 也适用于将来图片 float:right 的情况。

给section元素添加类 class=”clearfix” ,我们可以得到跟上图一样的效果
Alt text

三种方法如何选择?

这三种方法的使用要因地制宜。

比如,不能在下拉菜单的顶级元素上应用 overflow:hidden,否则作为其子元素的下拉菜单就不会显示了。因为下拉菜单会显示在其父元素区域的外部,而这恰恰是 overflow:hidden 所要阻止的。

再比如,不能对已经靠自动外边距居中的元素使用“浮动父元素”技术,否则它就不会再居中,而是根据浮动值浮动到左边或右边了。

推荐使用clearfix规则