CSS常用布局

CSS 常用布局包括:

  • 正常布局流
  • 弹性盒
  • 网格
  • 浮动
  • 定位
  • 多列布局
  • 响应式设计

本篇文章我们主要来介绍CSS的浮动与定位两者布局方式。

浮动(float)

float 语法

1
float: none|left|right|initial|inherit;

属性值

描述
left 元素向左浮动。
right 元素向右浮动。
none 默认值。元素不浮动,并会显示在其在文本中出现的位置。
inherit 规定应该从父元素继承 float 属性的值。

技术细节

默认值: none
继承性: no
版本: CSS1
JavaScript 语法: object.style.cssFloat=”left”

clear 语法

1
clear: none|left|right|both|initial|inherit;

属性值

描述
left 在左侧不允许浮动元素。
right 在右侧不允许浮动元素。
both 在左右两侧均不允许浮动元素。
none 默认值。允许浮动元素出现在两侧。
inherit 规定应该从父元素继承 clear 属性的值。

技术细节

默认值: none
继承性: no
版本: CSS1
JavaScript 语法: object.style.clear=”left”

所谓浮动,就是让一个元素脱离标准文档流,漂浮在标准流之上,然后按照指定的方向向左或向右移动,碰到父级边界或者另外一个浮动元素停止。

示例,我们给框1一个向左浮动的样式:

1
2
3
div1{
float:right
}

实例

当把框 1 向右浮动时,它脱离文档流并且向右移动,直到它的右边缘碰到包含框的右边缘:

浮动1

再请看下图,当框 1 向左浮动时,它脱离文档流并且向左移动,直到它的左边缘碰到包含框的左边缘。因为它不再处于文档流中,所以它不占据空间,实际上覆盖住了框 2,使框 2 从视图中消失。

如果把所有三个框都向左移动,那么框 1 向左浮动直到碰到包含框,另外两个框向左浮动直到碰到前一个浮动框。

实例

浮动2

再请看下图,当框 1 向左浮动时,它脱离文档流并且向左移动,直到它的左边缘碰到包含框的左边缘。因为它不再处于文档流中,所以它不占据空间,实际上覆盖住了框 2,使框 2 从视图中消失。

如果把所有三个框都向左移动,那么框 1 向左浮动直到碰到包含框,另外两个框向左浮动直到碰到前一个浮动框。

实例

浮动3

浮动带来的问题

浮动元素脱离标准文档流,会导致元素重叠或者父元素的高度塌陷。

这时候就要用到清除浮动。

清除浮动,顾名思义就是为了解决浮动带来的一系列问题,也可以理解为打破横向排列。

清除浮动的这个规则,只能影响使用清除的元素本身,不能影响其他元素。


接下来我们以一个实际的例子来说明带来的问题及解决的办法。

例子

其实浮动(float)最开始是用来实现文字环绕图片的。

元素重叠实例

浮动4

但是我们发现,图片直接使用向左浮动,并不能达到我们想要的效果,因为,有部分文字实际上被遮挡了。

实际上,我们可以给两个段落的元素的上外边距添加足够的空间,来解决元素重叠的问题

float5

高度坍塌实列

针对上面的例子,我们来做另一种效果即我们可以将图片靠左浮动,包含文字的元素靠右浮动,这样我们得到了这样的效果:

float6

虽然看起来效果并没有什么问题,但是,实际上,浮动元素不占据空间,导致原本的高度坍塌

为了解决这个问题,可以使用三种方法来清理浮动,

解决方法一(不推荐)

我们可以新添一个div来清理浮动:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
.news {
background-color: gray;
border: solid 1px black;
}

.news img {
float: left;
}

.news p {
float: right;
}

.clear {
clear: both;
}

<div class="news">
<img src="news-pic.jpg" />
<p>some text</p>
<div class="clear"></div>
</div>

解决方法二(不推荐)

方法一这样可以实现我们希望的效果,但是需要添加多余的代码。常常有元素可以应用 clear,但是有时候不得不为了进行布局而添加无意义的标记。

不过我们还有另一种办法,那就是对容器 div 进行浮动:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
.news {
background-color: gray;
border: solid 1px black;
float: left;
}

.news img {
float: left;
}

.news p {
float: right;
}

<div class="news">
<img src="news-pic.jpg" />
<p>some text</p>
</div>

这样会得到我们希望的效果。不幸的是,下一个元素会受到这个浮动元素的影响。为了解决这个问题,有些人选择对布局中的所有东西进行浮动,然后使用适当的有意义的元素(常常是站点的页脚)对这些浮动进行清理。这有助于减少或消除不必要的标记。

解决方法三(推荐)

我们可以使用伪元素来实现清除浮动的效果。

伪元素:用于创建一些不在DOM树中的元素,并为其添加样式。

例如,我们可以通过:before来在一个元素之前添加一些文本,并为这些文本添加样式,虽然用户可以看见 这些文本,但是它实际上并不在DOM文档中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
.news {
background-color: gray;
border: solid 1px black;
float: left;
}

.news img {
float: left;
}

.news p {
float: right;
}

.clear::after{
content: "";
display: table;
clear: both;
}
<div class="news">
<img src="news-pic.jpg" />
<p>some text</p>
</div>

注意:单独设置.clear::after{clear: both;}是不够严谨的。

伪元素选择器的权重通常比单独的类选择器高,所以通常起到了清除浮动的作用。

但是,这个选择器的设置不够严谨,因为没有设置content属性,它不会在页面上绘制任何合法的内容。这会导致选择器被浏览器忽略,从而无法正确起到清除浮动的作用。

因此,更好的做法是将content属性设置为””或其他值,以确保浏览器可以正确解析该选择器,从而成功清除浮动。示例代码如下:

1
2
3
4
5
clear::after {
content: "";
display: block;
clear: both;
}
那display: block;是必须的吗?

在这个情况下,并不是必需的,但是建议使用。因为after伪元素是一个内联元素,不会在页面上占据空间。如果没有将其设置为block,则该元素可能无法正确清除浮动,导致布局问题。

将display属性设置为block,可以让该元素在页面上显示为一个块级元素(尽管它实际上是一个伪元素),并占据一定的空间。这样可以确保它在页面上正确地起到清除浮动的作用,同时不会影响其他元素的布局。因此,建议在清除浮动的选择器中将display属性设置为block。

除了display: block;还可以将display设为什么

除了使用 display: block;,在清除浮动(clear float)的选择器中,还可以设置 display: table; 或者 display: flow-root; 来保证清除浮动的效果。

  1. display: table;

display 值设置为 table; 会将伪元素的表现形式更改为表格元素,此时伪元素的宽度自动调整到最宽的内部内容相同(哪个更宽就会自动填充哪一栏),高度也可以自适应调整,能够确保浏览器正确解析,并占据页面上的位置。

例如:

1
2
3
4
5
clearfix::after {
content: "";
display: table;
clear: both;
}

在此代码中,clearfix::after 由于 display: table; 能够添加内容并占据页面上的空间。

解决方法四

display: flow-root;(CSS3新增特性)

在新版本的浏览器中,我们还可以设置 display: flow-root; 来清除浮动,这种方法比较简洁,能确保浏览器正确解析,并占据页面上的位置。

例如:

1
2
3
clearfix {
display: flow-root;
}

在此代码中,清除浮动的作用体现在了 clearfix 这个类选择器上,不需要使用 after 伪元素,能够简化代码。

总之,使用 display: block;, display: table;, 或者 display: flow-root; 都是在清除浮动时使用的有效选择器,其具体使用还需要根据具体情境而定。

当两个子元素进行左右浮动,但是它们的父元素无法正常展示高度时,可以使用 display: flow-root; 来清除子元素的浮动:

HTML代码:

1
2
3
4
<div class="parent">
<div class="left"></div>
<div class="right"></div>
</div>

CSS代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
.parent {
/* 父元素不浮动 */
}

.left {
float: left;
}

.right {
float: right;
}

/* 清除浮动 */
.parent {
display: flow-root;
}

在上面的代码中,leftright 两个子元素都浮动到了父元素左右两侧,但是父元素的高度却无法展示出来。这时候我们可以在父元素上添加 display: flow-root; 样式来清除浮动,使得父元素能够正常展示高度。

定位

position 语法

属性值

描述
absolute 生成绝对定位的元素,相对于 static 定位以外的第一个父元素进行定位。元素的位置通过 “left”, “top”, “right” 以及 “bottom” 属性进行规定。
fixed 生成绝对定位的元素,相对于浏览器窗口进行定位。元素的位置通过 “left”, “top”, “right” 以及 “bottom” 属性进行规定。
relative 生成相对定位的元素,相对于其正常位置进行定位。因此,”left:20” 会向元素的 LEFT 位置添加 20 像素。
static 默认值。没有定位,元素出现在正常的流中(忽略 top, bottom, left, right 或者 z-index 声明)。
inherit 规定应该从父元素继承 position 属性的值。

技术细节

默认值: static
继承性: no
版本: CSS2
JavaScript 语法: object.style.position=”absolute”

position 属性的作用

position属性用来指定一个元素在网页上的位置,一共有5种定位方式,即position属性主要有五个值。

  • static
  • relative
  • fixed
  • absolute
  • sticky

下面就依次介绍这五个值。最后一个sticky是2017年浏览器才支持的,本文将重点介绍。

static 属性值

staticposition属性的默认值。如果省略position属性,浏览器就认为该元素是static定位。

这时,浏览器会按照源码的顺序,决定每个元素的位置,这称为”正常的页面流”(normal flow)。每个块级元素占据自己的区块(block),元素与元素之间不产生重叠,这个位置就是元素的默认位置。

img

注意,static定位所导致的元素位置,是浏览器自主决定的,所以这时topbottomleftright这四个属性无效。

relative,absolute,fixed

relativeabsolutefixed这三个属性值有一个共同点,都是相对于某个基点的定位,不同之处仅仅在于基点不同。所以,只要理解了它们的基点是什么,就很容易掌握这三个属性值。

这三种定位都不会对其他元素的位置产生影响,因此元素之间可能产生重叠。

relative 属性值

relative表示,相对于默认位置(即static时的位置)进行偏移,即定位基点是元素的默认位置。

img

img

它必须搭配topbottomleftright这四个属性一起使用,用来指定偏移的方向和距离。

img

1
2
3
4
div {
position: relative;
top: 20px;
}

上面代码中,div元素从默认位置向下偏移20px(即距离顶部20px)。

absolute 属性值

absolute表示,相对于上级元素(一般是父元素)进行偏移,即定位基点是父元素。

它有一个重要的限制条件:定位基点(一般是父元素)不能是static定位,否则定位基点就会变成整个网页的根元素html。另外,absolute定位也必须搭配topbottomleftright这四个属性一起使用。

img

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/*
HTML 代码如下
<div id="father">
<div id="son"></div>
</div>
*/

#father {
positon: relative;
}
#son {
position: absolute;
top: 20px;
}

上面代码中,父元素是relative定位,子元素是absolute定位,所以子元素的定位基点是父元素,相对于父元素的顶部向下偏移20px。如果父元素是static定位,上例的子元素就是距离网页的顶部向下偏移20px

注意,absolute定位的元素会被”正常页面流”忽略,即在”正常页面流”中,该元素所占空间为零,周边元素不受影响。

fixed 属性值

fixed表示,相对于视口(viewport,浏览器窗口)进行偏移,即定位基点是浏览器窗口。这会导致元素的位置不随页面滚动而变化,好像固定在网页上一样。

img

它如果搭配topbottomleftright这四个属性一起使用,表示元素的初始位置是基于视口计算的,否则初始位置就是元素的默认位置。

1
2
3
4
div {
position: fixed;
top: 0;
}

上面代码中,div元素始终在视口顶部,不随网页滚动而变化。

sticky 属性值

sticky跟前面四个属性值都不一样,它会产生动态效果,很像relativefixed的结合:一些时候是relative定位(定位基点是自身默认位置),另一些时候自动变成fixed定位(定位基点是视口)。

因此,它能够形成”动态固定”的效果。比如,网页的搜索工具栏,初始加载时在自己的默认位置(relative定位)。

img

页面向下滚动时,工具栏变成固定位置,始终停留在页面头部(fixed定位)。

img

等到页面重新向上滚动回到原位,工具栏也会回到默认位置。

sticky生效的前提是,必须搭配topbottomleftright这四个属性一起使用,不能省略,否则等同于relative定位,不产生”动态固定”的效果。原因是这四个属性用来定义”偏移距离”,浏览器把它当作sticky的生效门槛。

它的具体规则是,当页面滚动,父元素开始脱离视口时(即部分不可见),只要与sticky元素的距离达到生效门槛,relative定位自动切换为fixed定位;等到父元素完全脱离视口时(即完全不可见),fixed定位自动切换回relative定位。

请看下面的示例代码。(注意,除了已被淘汰的 IE 以外,其他浏览器目前都支持sticky。但是,Safari 浏览器需要加上浏览器前缀-webkit-。)

1
2
3
4
5
#toolbar {
position: -webkit-sticky; /* safari 浏览器 */
position: sticky; /* 其他浏览器 */
top: 20px;
}

上面代码中,页面向下滚动时,#toolbar的父元素开始脱离视口,一旦视口的顶部与#toolbar的距离小于20px(门槛值),#toolbar就自动变为fixed定位,保持与视口顶部20px的距离。页面继续向下滚动,父元素彻底离开视口(即整个父元素完全不可见),#toolbar恢复成relative定位。

sticky 的应用

sticky定位可以实现一些很有用的效果。除了上面提到”动态固定”效果,这里再介绍两个。

堆叠效果

堆叠效果(stacking)指的是页面滚动时,下方的元素覆盖上方的元素。下面是一个图片堆叠的例子,下方的图片会随着页面滚动,覆盖上方的图片(查看 demo)。

img

HTML 代码就是几张图片。

1
2
3
<div><img src="pic1.jpg"></div>
<div><img src="pic2.jpg"></div>
<div><img src="pic3.jpg"></div>

CSS 代码极其简单,只要两行。

1
2
3
4
div {
position: sticky;
top: 0;
}

它的原理是页面向下滚动时,每张图片都会变成fixed定位,导致后一张图片重叠在前一张图片上面。详细解释可以看这里

表格的表头锁定

大型表格滚动的时候,表头始终固定,也可以用sticky实现(查看 demo)。

img

CSS 代码也很简单。

1
2
3
4
th {
position: sticky;
top: 0;
}

需要注意的是,sticky必须设在<th>元素上面,不能设在<thead><tr>元素,因为这两个元素没有relative定位,也就无法产生sticky效果。详细解释可以看这里


浮动参考:

定位参考:

定位转载:

CSS三大特性

  • 层叠性
  • 继承性
  • 优先级

层叠性

层叠性:就近原则

  1. 样式冲突遵循的原则就是就近原则,那个样式离结构近,就执行那那个样式
  2. 同类种选择器,第二个选择器相同样式会覆盖第一个选择器
  3. 在同一个选择器中,相同的属性,以最后一个为准
  4. 主要解决样式冲突问题。
  5. 样式不冲突,不会叠加。

继承性

所谓继承性是指书写CSS样式表时,子标签会继承父标签的某些样式,子标签会继承父标签的某些此样式,如文本的颜色和字号。

  • 恰当的使用继承可以简化代码,降低CSS的复杂性。
  • 子元素可以继承父元素的样式(text-,font-,line- 这些元素开头的可以继承,以及color属性)

一,可以被继承的css属性

  1. 字体系列属性:font、font-family、font-weight、font-size、fontstyle;
  2. 文本系列属性:
  • 内联元素:color、line-height、word-spacing(设置单词之间的间距)、letter-spacing(设置文本字符间距)、 text-transform(用于设置文本的大小写:uppercase所有字符强制转为大写,lowercase转小写,capitalize首字符强制转为大写);
  • 块级元素:text-indent、text-align;
  1. 元素可见性:visibility
  2. 表格布局属性:caption-side(标题位置)、border-collapse(设置边框分离还是合并)、border-spacing(边框分离状态下设置边框间距)、empty-cells(定义如何渲染无可视内容的单元格边框和背景)、table-layout(定义用于布局单元格行和列的算法);
  3. 列表布局属性:list-style

二,不可以被继承的css属性

  1. display:规定元素应该生成的框的类型;
  2. 文本属性:vertical-align、text-decoration(用于设置文本的修饰线外观包括上/下划线,管穿线,删除线,闪烁 );
  3. 盒子模型的属性:width、height、margin、border、padding;
  4. 背景属性:background、background-color、background-image;
  5. 定位属性:float、clear、position、top、right、bottom、left、min-width、min-height、maxwidth、max-height、overflow、clip;

优先级

当同一个元素指定多个选择器就会由优先级产生。
选择器相同,则执行层叠性。
选择器不同,则根据选择器权重执行
选择器权重:

选择器 选择器权重
继承或者* 0,0,0,0
元素选择器 0,0,0,1
类选择器,伪类选择器 0,0,1,0
Id选择器 0,1,0,0
行内选择器 style=” “ 1,0,0,0
!important 重要性 无穷大

注意点:

权重是由四组数字组成,但不会有进位。
可以理解为类选择器永远大于元素选择器,id选择器永远大于类选择器。
等级判断,从左向右,如果某一位数值相同,则判断下一位数值。
可以简单记忆法:通配符和继承权重为0,标签选择器为1,类(伪类)选择器10,id选择器为100,行类样式为1000,!important 无穷大。
继承的权重为0,如果该元素没有直接选中,不管父元素权重多高,子元素得到的权重都是0。
权重叠加:如果是复合选择器,则会有权重叠加,需要计算权重多高

  • div ul li ——> 0,0,0,3
  • a:hover ——>0,0,1,1
  • .nav ul li ——>0,0,1,2
  • .nav a ——> 0,0,1,1