这是我参与更文挑战的第 1 天,活动详情查看: 更文挑战
2021-06-01 总结 TANGJIE 流 元素 HTML5 CSS3 基本尺寸
重学CSS系列,CSS的基本构建
1. 盒子构成
1.1 认识html元素的基本构造
首先明确这样一个概念html的元素,都可以看成一个装东西的盒子
如图:
这样很多属性就好理解了,display:block
其实就是display:block-block
(非标准写法,下面的类同,这里这样写是为了方便理解,做项目时请使用标准写法);display:table
其实就是display:block-table
;display:inline-block
;因此当我们写display:inline-table
其实就会得到一个一行显示的表格可以和文字嵌在一起
总结起来就是:
- 每个元素都有两个盒子,一个外在盒子,一个内在盒子
- 外在盒子负责排版性的东西,如,是可以一行展示还是必须要换行展示
- 内在盒子负责内容性的东西,如,控制宽高,内容呈现
- 某些元素还有标记盒子,可以说是附加盒子
2. 块级/内联元素
2.1 块级元素
什么是块级元素,通过上面的盒子,我们可以清楚的认识到一个,外在盒子是block的元素就是块级元素,所以块级元素不仅仅是display:block
的元素,像table
,li
啊都是,其表现就是一个水平流上只能单独显示一个元素,多个块级元素换行显示。
开发实用点:因为块级元素具有换行特性,通常配合clear:both
来清除浮动,通常清浮代码如下:
.clear::after{
content:'';
display:block;
clear:both;
}
复制代码
2.2 内联元素
在认识了元素的盒子构造之后,内联元素就好理解了,什么是内联元素——就是外在盒子是inline
的元素,如inline-block
、inline-table
,inline-inline
,其表现就是,可以和文字一行显示。
2.3 html5的空白节点
在html5中,例如这样的代码:
div{
background-color:pink;
}
span{
display:inline-block;
}
复制代码
<div><span></span></div>
复制代码
会发现,此时<div>
的高度并不是0,这就很奇怪,明明内部<span>
的高度是0啊,标签之间也没有换行符。产生这样的效果的原因是:css规范中有提到在内联元素前有一个同时具有该元素字体和行高属性的0宽度的内联盒子。
2.4 解决img标签的间隙: 幽灵空白节点
- 只有元素是行内元素或行内块元素,
vertical-align
这个属性才生效。所以我们想让vertical-align
失效,那么就让img变成块级元素—设置display
属性值为block
- 设置
vertical-align
的值不使用baseline
,使用其他的比如bottom
top
middle
等等都可以 - 这个缝隙是文字的大小改变的,所有我们可以对文字设置font-size为0 前提是这个行框不能出现文字
- 改变文字的高度也是可以解决间隙的问题,将高度设置为0即可,但是文字的高度也可以由
line-height
决定,所以设置line-height
为0也可以解决
3. width/height
的作用细节
首先了解一个点,width和height都是作用在内在盒子上面的
3.1 被忽视的width:auto
为什么说是被忽视的呢?
- width的默认值就是auto
- 充分的利用了可用空间(div,p这些标签是默认宽度100%于父级的)
- 收缩和包裹(当元素处于浮动和绝对定位状态其宽度由内容决定)
- 收缩到最小(在table-layout:auto的表格中,表现为收缩到可展示内容的最小宽度)
这些特点很少有人去注意它,因为在实现项目的时候,很多开发者习惯把父级等宽度给设置死,或者不考虑情况,直接加上width:100%
这种不必要的代码
3.2 外部尺寸和流体特征
- 正常宽度流,也就是外在盒子为
block
的元素,在正常文档流下,其尺寸表现就和流水一样会充满整个父容器,因此很多元素设置width:100%
是不必要的,同时之前也说过,宽度是作用在内在盒子的,所以这里设置了宽为100%是把内在盒子设置成父容器的宽度大小,实际大小其实是父容器大小+该元素的margin/padding/border
。而不设置,利用其流动性,margin/padding/border/content
是一种自动分配水平空间的机制,能够很好的确保该元素width是父级的宽度。(这是下面css宽度分离的由来) - 包裹收缩性宽度,存在于绝对定位模型(
position:absolute/fixed
)和浮动模型当中,简单来说就是,默认的情况下,绝对定位的元素的宽度是由其内部尺寸(内容) - 格式化宽度,存在于绝对定位模型当中(
position:absolute/fixed
)。那什么情况下呈现呢,那就是对于非替换元素
,当left/right
或top/bottom
对立方位的属性同时存在,其宽度大小是按最近具有定位特性的祖先元素计算的。
例如:
// 最近的祖先定位元素宽度是1000px
div{
position:absolute;
left:20px;
right:20px;
}
复制代码
这个div的宽度大小就是 1000 -20-20px = 960px
,然后其padding/margin/border/content都会自动分配空间
补充:什么是非替换元素?
非替换元素就是:通过修改某个属性值呈现的内容不可以被替换,与之相对应的就是替换元素
3.3 内部尺寸和流体特性
- 包裹性,内联元素的包裹性最佳呈现就是
display:inline-block
,也就是内部尺寸由内容决定,相当于给了一个值max-width:100%
;开发实践当中,可能遇到这么一个需求:一个文字居中,多行文字居左,其实现方式如下面代码
.box{
text-align:center
}
.content{
text-aligin:left;
display:inline-block;
}
复制代码
<div class="box">
<p class="content">我喜欢前端,你喜欢吗?</p>
</div>
复制代码
display:inline-block
下的首选最小宽度,也就是元素最合适的最小宽度;其原理就是图片和文字的权重大于布局,因此有文字的div,即便是设置了width:0,也会被撑开成文字或图片大小
例如这段代码:
<div style="display: inline-block;width: 0">
我爱前端
</div>
复制代码
其表现就变成了单个文字一行排列,至于开发有什么作用,就需要各位的奇思妙想了
3.4 width和height的作用细节
这里就涉及到了基础面试,老生常谈的东西,什么是CSS 盒子模型(Box Model)?
简单来说如图:
按照本节1大点所说的内容,width
是作用在内在盒子上面的,因此内在盒子被分成了4个盒子——content-box
、padding-box
、border-box
、border-box
、margin-box
;在css规范中描述到:content-box
是环绕着width和height给定的矩形即,width
和height
都是作用在content-box
上面的,这也就是为什么当一个元素有margin,padding,border
值的时候,加width:100%一般来说要比父级宽的原因
在css3中就有一个属性box-sizing
可以来改变width
和height
的作用细节
box-sizing:border-box
从代码实践角度觉得有如下2点可以参考
- 还是尽量不用使用,尽量采取宽度分离原则(下一大点),因为它不能把元素的width和height的作用细节改到margin-box上
- 元素的width和height作用细节被打乱了,不是很利于项目维护
3.5 为流体而生的max-width/min-width/max-height/min-height
最大的作用细节和width/height都一样,但是以上属性更适合出现在自适应或流体布局中
4. CSS宽度分离原则
CSS宽度分离原则,是样式开发中很重要的一条原则,总结起来就是:父元素定宽,子元素定margin,padding等值,这样的就不会破坏父元素的宽度。
5. 实战:任意高度元素的展开收起动画
参考代码:
.content{
max-height: 0;
overflow: hidden;
transition: max-height 5s;
background-color: pink;
}
.content.active{
max-height: 100vh;
}
复制代码
<div class="content">...</div>
<button id="btn">展开</button>
复制代码
btn.addEventListener('click',()=>{
const content = document.querySelector('.content');
content.classList.add('active');
})
复制代码