《css世界》笔记
何为“流”?
“流”是CSS世界中的基本定位和布局机制;
CSS世界构建的基石是HTML, html最具代表性的两个基石块级元素<div>, 内联元素<span>。
流体布局: 就是利用元素“流”的特性实现的各类布局效果,因为“流”本身具有自适应特性。
流体布局是自适应布局(凡是具有自适应特性的布局统称)的一种实现,例如表格布局设置为100%以后是自适应的,但他不是流体布局(表格和流不是一路的)
注意: “流”的特性对<table>不起作用
“流”如何影响CSS?
- css的基石是html,只要让html默认表现符合“流”,整个css世界就被“流”统治
- 特殊布局与“流”的破坏
- 流向的改变,文档流默认是从左到右从上到下,这个流向是可以改变的
流、元素和基本尺寸
一、块级元素
<div>、<li>、<table>
“块级元素”和“display: block”的元素不是一个概念;
div是display:block;
li是display: list-item;
table是display: table;
之所以都是块级元素,是因为他们符合块级元素的基本特性
特性:一个水平流上只能单独显示一个元素,多个块级元素换行显示。所以可以通过伪元素+块级元素配合清除浮动
二、为什么display:inline-block既可以一行显示也可以设置width/height?
css里每个元素都有两个盒子: 外在盒子(控制一行显示还是换行)和容器盒子(负责宽高,内容呈现等)
根据display的属性值不同, 元素的盒子组成如下:
display:block; 外在的“块级盒子” + 内在的“块级容器盒子”
display: inline-block; 外在的“内联盒子” + 内在的“块级容器盒子”
display: inline; 外在的“内联盒子” + 内在的“内联容器盒子”
综上:display: inline-block的元素,外在盒子控制一行显示,内在容器盒子可以设置宽高。
三、width/height的作用细节
由上得知:元素都由外在盒子和容器盒子组成,容器盒子负责宽高,内容等的呈现。所以我们css里设置的width/height实际上都是作用在内在容器盒子上的。
width:默认值是auto时,元素有以下4个特性:
- 充分利用空间;<div><p>元素的宽度默认是100%于父级容器。
对应的是width/height: -webkit-fill-available
- 收缩和包裹;元素设为浮动,绝对定位,inline-block, table时,表现为包裹性
对应的是css3里的width: fit-content
- 收缩到最小;元素超过容器宽度时,这个时候元素的尺寸由内部元素决定,因为元素有自己的最小宽度,例如汉字因为可以任意处断行,此时就是一个汉字的宽度。英文单词不能断,所以最小宽度就是一个英文单词的宽度。
对应的是css3里width: min-content
- 超出容器限制;设置了white-space:nowrap属性后,或者是很长的英文数字会超出容器限制;否则默认情况下都不会主动超过父级容器。
width: max-content时,表现为外部容器的最终宽度就是内部元素的最大值。超过一屏的滚动展示
外部尺寸与流体特性
外部尺寸:元素尺寸由外部容器决定。
以上特性中的第一条: <div>宽度默认100%显示就是外部尺寸,其他全都是内部尺寸;这个也是“流”精髓;
“外部尺寸”的块级元素一旦设置了宽度,流动性就消失了。(所谓流动性是margin/border/padding/content区域自动分配水平空间的机制)
内部尺寸与流体特性
内部尺寸: 元素尺寸由内部元素决定。
- 包裹性:元素尺寸由内部决定,但不会超过父容器,除非父容器小于元素的首选最小宽度。
如上:按钮是inlint-block元素,按钮的宽度由内容决定,超过父容器宽度时,自动换行显示
2. 首选最小长度:即上面的收缩到最小;
table-layout: auto的元素中,每一列宽度都不够时,汉字可以随便断,英文单词不能。于是第一行被断成这样子
3.最大宽度:有包裹性或者设置了white-space:nowrap属性的元素,最大宽度是内部连续内联盒子的宽度
如果仅有包裹性,容器最大宽度不会超过页面宽度,即不会出现滚动条,自动换行
width: 指定具体值的时候 width: 200px
由前面知道,width是作用在内部容器盒子的。内部容器盒子实际上包含:content-box, padding-box, border-box, margin-box(css盒模型)
css2.1规范中指出,contentbox是环绕着width和height的矩形;
指定具体宽度后会有的影响:
- 流动性消失;
- 实际效果跟预期不一致;
解决办法:
1. 宽度分离
css中,width属性不跟影响宽度的padding, border甚至margin属性共存。
好处是:避免了计算, 利于维护
避免以下写法
.box {
width: 100px;
padding: 10px;
border: 1px solid #eee;
}
采用以下写法,width独占一层标签,内部利用流动性自适应展示
.wrapper {
width: 100px;
}
.box {
padding: 10px;
border: 1px solid #eee;
}
2. 改变box-sizing属性值,改变width/height的作用细节
流的破坏
流的破坏之float
追根溯源,float的起源就是为了实现文字环绕效果;因为最初带宽就那么一点点的时候我们能做的也就是展示文字及零星图片而已
float的特性:
- 包裹性
- 块状化并格式化上下文
- 破坏文档流
- 没有任何margin合并
float的作用机制:
行框盒子: 每一行就是一个行框盒子,每个行框盒子又是由一个一个内联盒子组成的;如下:
在页面中,由几行展示就有几个行框盒子,如下:两个行框盒子
- 会让父元素高度塌陷(初衷就是为了实现文字环绕效果)
- 行框盒子区域限制(如果行框盒子和浮动元素的垂直高度有重叠,则行框盒子在正常定位状态下只会跟随浮动元素,不会发生重叠)
图片高度为100px,float:left, 文字部分高度100以内的跟随浮动元素,超过100的开始重叠发生环绕
要想实现一栏定宽的两栏布局,可以左侧定宽left浮动,右侧margin-left:定宽 ,实现自适应
3. float定位参考的是“行框盒子”;比如right浮动时,如果当前行框盒子满了,就会显示到行框盒子下面
流的保护之clear
clear—专门解决float高度塌陷等问题的属性;
clear:none| right | left | both;
设置了clear属性的元素盒子的边不能和前面的浮动元素相邻
所以,设置了clear后,浮动依然存在,并没有清除;
只是设置了clear的元素分别会具有以下特点;
- none: 默认值,左右都可浮动
- left: 左侧抗浮动
- right:右侧抗浮动
- both: 两侧抗浮动
clear属性只对块级元素生效;这就是通过伪元素清楚浮动时需要设置display属性值的原因
clear只是一定程度上消除浮动的影响,浮动元素的一些不好的特性依然存在;如下:(例如行框盒子区域限制特性)
完美去除浮动影响:
BFC: 块级格式化上下文
如果一个元素有BFC,内部子元素无论怎么翻江倒海,都不会影响外部元素;也不会受到外部元素的影响。像是一个“结界”;
触发BFC的条件:
- html根元素
- float不是none
- overflow的值是auto, scroll, hidden
- display的值是table-cell, table-caption, inline-block
- position不是relative, static
此时实现一栏定宽的两栏布局,就可以左侧float定宽浮动,右侧为BFC;就算不知道左侧宽度时,也可以实现。
如果要两栏之间隔开10px距离,可以左侧添加margin-right, border-right,padding-right,右侧border-left, padding-left为10px;右侧使用margin-left的话,需要10px+左侧定宽。
综上:清除浮动最好的方法就是overflow:hidden
流的破坏之定位
position: absolute
absolute能力比float霸道, 当两者同时存在时,float没有任何效果,当前两个也没理由同时存在;
特性跟float差不多:
- 破坏文档流
- 块状化并格式化上下文
- 包裹性
absolute的的自适应性最大宽度往往不是由父元素决定的,而是由包含块决定的。
何为包含块?
元素用来定位和计算的框;
根元素<html>:也叫初始包含块,尺寸等同于浏览器可视窗口的大小;
position是relative或者static的元素:包含块是最近的块容器的content box;
position是absolute的元素:第一个position不是static的祖先元素的padding box;
position是fixed的元素:包含块是初始包含块
absolute元素的宽度自适应相对于包含块来表现:
有一个有趣的例子https://demo.cssworld.cn/6/5-1.php
实现一个删除图标,鼠标悬浮显示“删除”小提示;通过after,before伪元素实现提示文字和小箭头的展示,通过图标设置relative属性实现精确的定位;
会出现的问题是,图标宽度很小,不足两个字的宽度,于是“删除”两个字换行显示。
解决办法,设置white-space: nowrap;让宽度表现从“包裹性”变成“最大可用宽度”。
absolute无依赖绝对定位:
元素只设置了position:absolute,没有设置top等属性;
它是脱离css文档流的相对定位特性;
通过这个特性可以实现表单输入提示,具有可维护性强的特性;
见https://demo.cssworld.cn/6/5-6.php
通过absolute和margin实现提示信息的定位。
absolute设置top/bottom, left/right来定位:
如果left, right同时设置为0,那么定位元素在水平方向依然就有流的特性,即padding,content, border自动分配;垂直方向也如此
利用这个特性可是设置绝对定位元素水平垂直居中;即四个方向定位设置为0, 指定宽度后margin设置为auto
absolute元素的height:
绝对定位元素的height设置为100%和inherit时实际计算是完全不同的。
100%: 相对于包含块计算高度。
inherit: 相对于父元素计算高度,继承父元素的高度值。
无依赖absolute也可能受到text-align的影响:
前提是定位元素前有个内联元素(内联元素有个幽灵空白节点),内联元素的位置被text-align影响,此时后面的absolute定位元素在无依赖定位时,默认就在这个幽灵空白节点后面
absolute和overflow
包含块及其父元素的的overflow属性才能影响到absolute的溢出处理。
overflow溢出采用的是content-box为边界;
position: relative
相对定位,定位的位置相对于自身进行偏移
relative定位是相对于它的包含块(父级元素)的content-box来计算的。
relative定位不会影响它之外的元素的显示位置;
例如,原本一个正常文档流的排版,div设置relative并top: -20px; 那么div跟他后面的元素之间会有一个20px的空白。其后的元素位置不会受到影响。这一点跟margin不同。
relative可以决定absolute的位置计算,所以relative要遵循最小影响范围原则,便于代码扩展和维护。
position:fixed
该定位的包含块是初始包含块,也就是<html>;
fixed的裁剪需要使用clip属性,因为它的包含块是html。
clip属性值为定位元素上,右,下,左四个方向要裁剪掉的距离。