相信全部前端开发者的入门课,都是从div和css开始的,CSS做为基础中的基础,除了让页面由于样式而变得丰富美观外,更是决定了页面元素的排列布局,然而不少时候,当咱们对CSS只知其一;不知其二,咱们总会在开发中遇到元素不能按照咱们所想的那样呈现出来的问题,因此本文就来系统的讲讲CSS的布局定位。css
首先,咱们来了解构成页面的元素。在CSS中,咱们的每一个元素本质上都是一个盒子,盒模型决定了一个元素的大小和他所占大小,盒模型由如下几部分组成:html
那么元素的大小到底取决于什么呢?目前有两种盒模型:W3C盒模型
和IE盒模型
,两种盒模型的计算方法不一样,在CSS中,咱们能够用box-sizing
指定使用哪一种方式计算:前端
看个例子:css3
// W3C盒模型
<style>
.box {
width: 200px;
height: 200px;
padding: 10px;
margin: 10px;
border: 5px solid red;
background-color: yellowgreen;
}
</style>
<div class="box"></div>
复制代码
效果:chrome
// IE盒模型
<style>
.box {
width: 200px;
height: 200px;
padding: 10px;
margin: 10px;
border: 5px solid red;
background-color: yellowgreen;
box-sizing: border-box;
}
</style>
<div class="box"></div>
复制代码
效果:浏览器
display
属性display
用于定义创建布局时元素生成的显示框类型,会影响到兄弟元素之间的布局,他的取值有如下几种:bash
下面咱们将对inline-block
,flex
,run-in
这几个属性作详细讲解。布局
inline-block
和float
,flex
并称实现元素行内显示的“三巨头”,相比较flex的丰富属性,inline-block就略显朴素,使用也十分简单,看起来彷佛彻底不值得对它进行详细介绍,但不知道大家在使用的时候是否也踩过那些inline-block的坑,因此这里咱们来说讲inline-block的必坑指南post
咱们先来看一个例子:学习
<div class="content">
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
</div>
.content {
background-color: yellow;
width: 350px;
height: 100px;
}
.cell {
display: inline-block;
width: 100px;
height: 50px;
background-color: red;
}
复制代码
实现的效果:
font-size:0
。
<div class="content">
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
</div>
.content {
background-color: yellow;
font-size: 0;
width: 350px;
height: 100px;
}
.cell {
display: inline-block;
width: 100px;
height: 50px;
background-color: red;
}
复制代码
效果:
这个问题,是在开发的时候偶然碰见的,话很少说,先看看这两个例子:
<div class="content">
<div class="cell">有内容</div>
<div class="cell"></div>
<div class="cell">有内容</div>
</div>
.content {
background-color: #eee;
font-size: 0;
width: 350px;
height: 100px;
}
.cell {
display: inline-block;
width: 100px;
height: 50px;
font-size: 16px;
background-color: #666;
color: #fff;
}
复制代码
效果:
<div class="content">
<div class="cell">有内容</div>
<div class="cell" id="spec">有内容</div>
<div class="cell">有内容</div>
</div>
.content {
background-color: #eee;
font-size: 0;
width: 350px;
height: 100px;
}
.cell {
display: inline-block;
box-sizing: border-box;
width: 100px;
height: 50px;
line-height: 50px;
border-radius: 50px;
margin: 5px;
font-size: 16px;
text-align: center;
background-color: #fff;
color: #333;
}
.active {
border: 2px solid #E20000;
color: #E20000;
}
let spec = document.getElementById("spec");
let flag = false;
spec.addEventListener("click", () => {
flag = !flag;
if (flag) {
spec.classList.add('active')
} else {
spec.classList.remove('active')
}
});
复制代码
效果:
测量结果显示,这三个元素的高度同样,并无发生改变,那么到底是什么缘由致使了行内元素高度塌陷、上下抖动的呢?
其实形成这一结果的是vertical-align
属性。inline-block
做为行内块元素,也遵循行内元素的vertical-align
垂直对齐方式,vertical-align
的取值有如下几种:
<length>
:将元素的基线对准给定长度高于其父元素的基线。<percentage>
:像<长度>值,百分比是line-height属性的百分比。在默认状况下,会根据baseline
进行定位,文字的定位不一样,最终致使了整个块元素的高度塌陷。想要解决这一问题,咱们只需将vertical-align
设置为top
,以下: 状况一:
<div class="content">
<div class="cell">有内容</div>
<div class="cell"></div>
<div class="cell">有内容</div>
</div>
.content {
background-color: #eee;
font-size: 0;
width: 350px;
height: 100px;
}
.cell {
display: inline-block;
vertical-align: top;
width: 100px;
height: 50px;
font-size: 16px;
background-color: #666;
color: #fff;
}
复制代码
<div class="content">
<div class="cell">有内容</div>
<div class="cell" id="spec">有内容</div>
<div class="cell">有内容</div>
</div>
.content {
background-color: #eee;
font-size: 0;
width: 350px;
height: 100px;
}
.cell {
display: inline-block;
vertical-align: top;
box-sizing: border-box;
width: 100px;
height: 50px;
line-height: 50px;
border-radius: 50px;
margin: 5px;
font-size: 16px;
text-align: center;
background-color: #fff;
color: #333;
}
.active {
border: 2px solid #E20000;
color: #E20000;
}
let spec = document.getElementById("spec");
let flag = false;
spec.addEventListener("click", () => {
flag = !flag;
if (flag) {
spec.classList.add('active')
} else {
spec.classList.remove('active')
}
});
复制代码
run-in
这个属性值是在css3中被引入的,官方对他的描述是:
此元素会根据上下文做为块级元素或内联元素显示。
这个说法让人会有些摸不着头脑,因此咱们直接来看个例子。
在设计文章样式的时候,也许你遇到过须要在一行内显示一个标题和一段内容的场景,若是使用h
标签和p
标签咱们可能获得的是下面这种结果:
<div class="article">
<h1>One Point.</h1><p>Here is the description.If a run-in element precedes a block level element, the run in element will behave structurally as if it has become the block level elements first inline child element.</p>
</div>
复制代码
h
标签的display属性变成
run-in
时,结果就变成了这样。
h1 {
display: run-in;
}
<div class="article">
<h1>One Point.</h1><p>Here is the description.If a run-in element precedes a block level element, the run in element will behave structurally as if it has become the block level elements first inline child element.</p>
</div>
复制代码
h1 {
float: left;
}
<div class="article">
<h1>One Point.</h1><p>Here is the description.If a run-in element precedes a block level element, the run in element will behave structurally as if it has become the block level elements first inline child element.</p>
</div>
复制代码
h1 {
display: inline-block;
}
<div class="article">
<h1>One Point.</h1><p>Here is the description.If a run-in element precedes a block level element, the run in element will behave structurally as if it has become the block level elements first inline child element.</p>
</div>
复制代码
run-in
究竟作了什么:
block
时,该元素将表现为inline-block
inline-block
时,该元素将表现为block
虽然这个属性看起来十分便利,可是这个属性已经被大多数浏览器舍弃了,这也是为何咱们平时听到的不是特别多的缘由,浏览器认为run-in破坏了HTML的表现,这些样式上的实现,应该经过CSS去调节。 因此对于这个属性,你们作个了解就能够啦。
Flex box
多是目前用来作自适应用的最多的布局方式了,Flex使用的丰富,也为开发者提供了更便捷更可靠的布局。
决定主轴的方向(即项目的排列方向)。取值:
决定了子元素如何换行。取值:
是flex-direction属性和flex-wrap属性的简写形式,默认值为row nowrap。
决定了项目在主轴上的对齐方式。取值:
决定了项目在交叉轴上如何对齐。取值:
决定了多根轴线的对齐方式。若是项目只有一根轴线,该属性不起做用。取值:
决定项目的排列顺序。数值越小,排列越靠前,默认为0。
决定项目的放大比例,默认为0,即若是存在剩余空间,也不放大。
决定项目的缩小比例,默认为1,即若是空间不足,该项目将缩小。
决定在分配多余空间以前,项目占据的主轴空间(main size)。浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为auto,即项目的原本大小。
是flex-grow, flex-shrink 和 flex-basis的简写,默认值为0 1 auto。后两个属性可选。
容许单个项目有与其余项目不同的对齐方式,可覆盖align-items属性。默认值为auto,表示继承父元素的align-items属性,若是没有父元素,则等同于stretch。
在Flex box被普遍使用之前,咱们常常会利用float来实现块元素行内两端显示,它的使用也十分简单,float属性有如下几种取值:
float自己没有什么难度,可是设置了float会致使父元素的没法被撑开,margin失效,因此清除float也就成了开发必备知识。
原始效果:
<div class="content">
<div class="cell spe1">块1</div>
<div class="cell spe2">块2</div>
</div>
.content {
background-color: #eee;
font-size: 0;
width: 350px;
}
.cell {
font-size: 16px;
background-color: #666;
color: #fff;
}
.spe1 {
width: 80px;
height: 20px;
float: left;
}
.spe2 {
width: 80px;
height: 30px;
float: right;
}
复制代码
<div class="content">
<div class="cell spe1">块1</div>
<div class="cell spe2">块2</div>
<div class="clr"></div>
</div>
.clr {
clear: both;
}
复制代码
.content:after {
content: '';
display: block;
visibility: hidden;
clear: both;
}
复制代码
该方法也是利用clear:both来清除浮动,与方法一的区别在于,方法一添加了一个clear元素,而这一个是在元素内部增长一个相似于clear的效果,其中有几个注意点:
.content {
overflow: hidden;
}
复制代码
经过设置overflow达到清除浮动效果,其原理是建立了一个BFC,有关BFC的知识,咱们会在后面章节里详细介绍。
最终效果:
position
定位position
属性决定了某个元素的定位方式,它的取值有如下几种:
在这些属性里,其中relative
咱们称之为相对定位,absolute
为绝对定位,fixed
为固定定位,sticky
为粘性定位,而这几个定位又能够区分为Normal flow(常规流)
和Unnormal Flow(很是规流)
。
属于常规流的取值:
常规流具有如下特性:
常规流里的元素属于格式上下文(formatting context),块元素和行内元素表现不一样会产生快格式上下文和行内格式上下文,也就是咱们常说的BFC
和IFC
。
BFC的建立方法:
BFC的本质就是建立一个隔离的空间,他的具体效果以下:
对于上述效果,除了1和3,彷佛都让人有些摸不着头脑,那么就让咱们经过几个例子来仔细研究一下。
首先咱们来了解一下什么是外边距折叠(margin collapse)。 在CSS中,两个或多个毗邻的普通流中的盒子(多是父子元素,也多是兄弟元素)在垂直方向上的外边距会发生折叠,这种造成的外边距称之为外边距折叠。
那么何时外边距会发生折叠呢?发生折叠须要知足这几种状况:
下面让咱们来看看代码实例:
<div class="top"></div>
<div class="content">
<div class="cell"></div>
<div class="cell"></div>
</div>
<div class="foot">
<div class="cell2"></div>
<div class="spe"></div>
<div class="cell2"></div>
</div>
.top {
background-color: #60acfc;
width: 100px;
height: 50px;
}
.content {
margin-top: 10px;
background-color: #eee;
width: 350px;
margin-bottom: 10px;
}
.cell {
margin-top: 20px;
background-color: #5bc49f;
height: 20px;
margin-bottom: 30px;
}
.foot {
background-color: #60acfc;
width: 100px;
}
.spe {
margin: 20px 0 30px;
}
.cell2 {
height: 20px;
background-color: #eee;
}
复制代码
效果:
.content
和.cell
的上边距折叠属于第一条,最终.content
和.top
之间的边距为20px。.cell
之间的边距折叠属于第二条,最终.cell
之间的边距为30px。.cell
和.content
的下边距折叠属于第三条,最终.content
和.foot
之间的边距为30px。.spe
本身的上下边距折叠属于第四条,最终.spe
占据的间隔为30px。如今咱们知道了margin collapse发生的状况,那咱们盖如何避免边距折叠呢?方法有如下几种:
<div class="BFC">
<div class="left"></div>
<div class="right"></div>
</div>
.BFC {
background-color: #eee;
}
.left {
float: left;
background-color: #60acfc;
width: 100px;
height:50px;
opacity: 0.6;
}
.right {
width: 150px;
background-color: #5bc49f;
height:30px;
}
复制代码
在咱们没有建立BFC的时候,父元素的高度不包含浮动元素高度。
.BFC {
background-color: #eee;
overflow: hidden;
}
复制代码
建立BFC后,父元素就会加上浮动元素高度,这个就是咱们在以前提到的清除浮动的方法之一。
<div class="BFC content">
<div class="left"></div>
<div class="right BFC">
<div class="cell"></div>
<div class="cell"></div>
</div>
</div>
.BFC {
overflow: hidden;
}
.content {
background-color: #eee;
}
.left {
float: left;
background-color: #60acfc;
width: 100px;
height:50px;
opacity: 0.6;
}
.right {
width: 150px;
background-color: #5bc49f;
height:30px;
}
.cell {
width: 20px;
margin: 5px;
background-color: #fff;
height:20px;
display: inline-block;
}
复制代码
效果:
IFC由inline元素构成,它的布局规则是这样的:
那么IFC通常有什么用呢?
属于很是规流的取值:
对于很是规流,由于他们脱离了正常的文档流,因此他们不会对正常流的元素形成影响,不少时候咱们都会配合z-index
使用,前两种相信你们都不陌生,因此就再也不多作介绍啦,下面咱们来说讲sticky
。
粘性定位(sticky)能够被认为是相对定位和固定定位的混合。元素在跨越特定阈值前为相对定位,以后为固定定位。
<div class="content">
<h1 class="title">我是一块内容</h1>
<div class="sticky"></div>
<div class="main"></div>
</div>
.content {
background-color: #eee;
}
.title {
color: #333;
}
.sticky {
position: sticky;
top: 0px;
background-color: #60acfc;
width: 100px;
height:50px;
}
.main {
width:150px;
height: 900px;
}
复制代码
效果:
VFC,也就是Visual formatting context
,虚拟格式上下文,他有BFC
,IFC
,GFC
和FFC
这几种类型,在前文中,咱们已经介绍了BFC
,IFC
,这里再简单介绍下GFC
和FFC
。
GFC(GridLayout Formatting Contexts),"网格布局格式化上下文",当为一个元素设置display值为grid的时候,此元素将会得到一个独立的渲染区域。
咱们能够经过在网格容器(grid container)上定义网格定义行(grid definition rows)和网格定义列(grid definition columns)属性各在网格项目(grid item)上定义网格行(grid row)和网格列(grid columns)为每个网格项目(grid item)定义位置和空间。
那么GFC有什么用呢,和table又有什么区别呢?首先一样是一个二维的表格,但GridLayout会有更加丰富的属性来控制行列,控制对齐以及更为精细的渲染语义和控制。
FFC(Flex Formatting Contexts),"自适应格式化上下文",display值为flex或者inline-flex的元素将会生成自适应容器(flex container)。 因此当咱们使用flex布局的时候,咱们就建立了一个FFC。
至此,有关CSS布局和定位的知识就结束了,文中若有解释不到位的地方,欢迎你们评论指正。
参考连接: