前言
大家好,我是抹茶,一个已经工作了五年+的前端。 在日常的工作当中,会听到一些声音——“css很难,没有逻辑性”。如果只是孤立的看每一个规则,确实是很分散,但如果结合HTML布局规则去看,我们会能从中发现一些设计的规律。
以每个DOM的大小及位置是如何确定的为主线,我们来研究这其中是哪些规则、样式在起作用。
1. html的布局规则
首先,html的布局规则遵循“从左到右,从上到下”。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.up {
background-color: skyblue;
height: 100px;
}
.down {
background-color:pink;
height: 100px;
}
</style>
</head>
<body>
<div class="up">
<span>我是第一句话</span>
<span>我是第二句话</span>
</div>
<div class="down"></div>
</body>
</html>
如果所示,浏览器是先绘制了第一个.up的dom,然后再绘制.down的dom,这就是从上到下。
先绘制了 <span>我是第一句话</span>,再绘制<span>我是第二句话</span>,这就是从左到右。
2.块级元素和内联元素的特性与转换
html标签是会分为块级元素和内联元素。 块状元素的宽度会默认占完整个容器,像水流一样。
如图,块状元素默认会如同水流一样占满整个容器,所以又叫文档流,相当于这些html的标签会流动铺开,渲染好整个页面。
块级元素好比书架上一个个的盒子,负责搭建框架,内联元素好比书架里的一本本书,负责内容填充。
常见的块级元素有: div、setion、header、nav、footer、p
常见的内联标签有: span
内联元素的宽高默认是由内容的内容撑开的,通过style设置宽高是无效的。
<body>
<div class="up">
<span style="margin-right: 40px;width:500px;height:500px">我是第一句话</span>
<span>我是第二句话</span>
</div>
<div class="down"></div>
</body>
如图所示,给span设置宽高是无效的,因为它默认display:inline,margin左右是生效的。因为内容是可以隔开的。
如果对span设置display:block,它就变成一个块,块是可以设置宽高的。
同样的,对块级元素设置display:inline,它就失去了扩张性,大小是由内容撑开。
3.盒模型
如图,一个DOM元素,从里到外是由content-box、padding-box、border-box、margin-box构成的。每个盒子是有4个面的,所以可以分别设置四个方位的样式。
一般来说,整个DOM占据的宽高是content-box + padding-box + border-box 的总和(默认box-sizing:content-box),我们设置的width是作用在content-box上。如图DOM在整个文档流中占据的宽高是244 * 144.
如果我们设置box-sizing:border-box那就把width设置的作用范围扩大到border-box,整个DOM占据的宽度就是设置的200px,content-box的宽度也就自动缩小到200 - border部分- padding部分。
4.内容盒子的高度
默认情况下,内容盒子(inline元素)的高度是由文字的line-height撑起来的。 一般情况的时刻,可以内容盒子的高是22.5px。
在设置line-height之后,文字往下掉了。
添加设置display:inline-block,我们能更直观看到效果。
当我们把font-size设置成一个很大的值的时候,元素高度变成了320px;
这320px是怎么来的呢?首先font-size设置是80px,文字换行变成两行,line-height设置为160px,
160 * 2 = 320px
如果没有换行,就还是160px.
把font-size设置成一个比行高还要大的值,可以发现高度还是160px,所以可以说一般情况下line-height决定了内联元素的高度。
5.DOM的位置
css中有positon的属性,默认是static。也就是按顺序从上到下,从左到右排列。如果不是static,则一般有下面的规则。
- relative 相对于原来的位置进行定位,可以设置left、right、top、bottom
- absolute 会相对第一个非static的父级元素定位,可以设置left、right、top、bottom
- fixed 默认是相对视窗进行定位,当元素祖先的
transform、perspective、filter或backdrop-filter属性非none时,容器由视口改为该祖先。 - sticky 基于用户的滚动位置来定位,与left、right、top、bottom组合使用。当距离满足方位设置值时,表现同fixed,被黏住了一样。
6.DOM的间隔
可以用position结合left、right、top、bottom来创建间隔,一般用的是margin。
6.1 margin无效的情况
inline元素的margin-top和margin-bottom是无效的,因为放置的东西不能悬空。但是margin-left和margin-right是有效的。也就是说inline作为内容,只可以设置它距离左右的间隔,如下图
6.2 margin合并的情况
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
body {
margin: 0;
}
.up {
background-color: skyblue;
height: 100px;
margin-bottom: 40px;
}
.down{
margin-top:20px;
background-color: brown;
height: 200px;
}
.content{
margin-left:20px;
margin-right:20px;
margin-top:20px;
margin-bottom: 20px;
}
</style>
</head>
<body>
<div class="up">
<span class="content">hello world</span>
</div>
<div class="down">
<span class="content">hello world</span>
</div>
</body>
</html>
我们给上面盒子设置了margin-bottom:40px,给下方盒子设置了margin-top:20px,浏览器实际上只间隔了40px,也就是合并了,取间隔的最大值。
7.层级堆叠
我们有时候会希望A叠加到B上面,这个时候一个图层就不够了,需要A图层叠加到B图层上面。从Layers面板就可以看到有三个图层。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
body {
margin: 0;
}
.up {
position: relative;
background-color: skyblue;
height: 200px;
margin-bottom: 40px;
}
.B {
top: 20px;
width: 100px;
height: 100px;
background-color: aqua;
position: absolute;
}
.C {
z-index: 1;
top: 50px;
width: 100px;
height: 100px;
background-color: yellow;
position: absolute;
}
</style>
</head>
<body>
<div class="up">
A
<div class="C">c</div>
<div class="B">B</div>
</div>
</body>
</html>
看body部分的代码,B在C后面,正常来说是后渲染的会覆盖前面的,但因为我们对C设置了z-index:1,C的层级比B高,我们就看到C覆盖在B上面了。
总结
这篇文章从HTML的布局规则,结合块级元素和内联元素的特性,把DOM元素的位置、大小、间隔、层级涉及的相关属性做了探究,以DOM的排布枝干为主线,穿插容易忽略的细节讲解,让大家可以知道DOM的位置是怎么确定、大小是如何收到关键属性的影响的。这些是作为布局的主干属性,其他的css属性属于更好描绘,希望通过这篇文章不再迷茫css如何影响到DOM的大小与布局。