盒模型
首先我们可以把每个 dom 元素都理解成为一个盒子,而每个盒子都有一些组成元素,这个就叫做盒模型
我们知道盒子有这几个要素:margin / border / padding / content
盒模型可以分为两类:IE 盒模型和 W3C 标准盒模型
- W3C 盒模型 —— 盒子的 width/height 只包括 content 部分,不包括 border 和 padding
- IE 盒模型 —— 盒子的 width/height 包含 content+border+padding
在 ie8+ 的浏览器上是用什么盒模型可以用 box-sizing
属性控制,默认值是 content-box
,即为标准盒模型,
如果把 box-sizing
设置为 border-box
则使用的是 IE 盒子模型。
在 iE6/7/8 的版本中如果缺失 DOCTYPE 就会触发 IE 盒子模型。其他情况我们可以使用 box-sizing
来指定盒子模型自由切换。
1px 问题产生的原因
设计稿给出的像素是物理像素,手机设备的像素是虚拟CSS像素,而每个设备都有它的 drp(物理像素比)
DRP:物理像素比,描述的是网页未缩放状态下,物理像素与 CSS 像素的初始比例关系,换算关系如下所示:
DPR = 设备像素 / CSS 像素
所以,不同的设备有不同的 dpr,我们可以得出如下的结论:
- DPR=1 时,我们设 1dpi 在 1 倍屏中真实展示 x 个 pt,根据刚刚的公式,我们可以得出,1dpi = 1px = x/1 即 x = 1。
- DPR=2 时,我们设 1dpi 在 2 倍屏中真实展示 x 个 pt,我们可以得出,1dpi = 1px = x/2 即 x = 2,所以 1dip 显示 2个pt。这样造成的问题是我们实际制作出的页面会比设计稿大一倍。
1px 问题解决方式
解决方式有如下几种:
background-image && boder-image
.background-image-1px {
background: url(...) no-repeat left bottom;
-webkit-background-size: 100% 1px;
background-size: 100% 1px;
}
.border-bottom-1px {
border-width: 0 0 1px 0;
-webkit-border-image: url(...) 0 0 2 0 stretch;
border-image: url(...) 0 0 2 0 stretch;
}
缺点:如果需要更改边框的颜色,那就要重新切图,并且可能会出现圆角模糊锯齿化的情况。
border-shadow
通过 css 对 border-shadow 的处理来模拟 0.5px
.box-shadow-1px {
box-shadow: inset 0px -1px 1px -1px #c8c7cc;
}
优点:代码少,还能换颜色 缺点:阴影会导致颜色变浅,而且仔细看很明显能看出是阴影 不是边框。
伪元素 + scale 缩放
这是对比前面的两种方式后的一种比较好的方式,并且 ant-design-mobile 也是使用的这种方式
我们可以先在 less 的变量控制文件中写好方法,然后在具体的页面中调用 less 方法:
@border-color-base : #EBEDF0;
// 伪元素的位置控制
.scale-hairline-common(@color, @top, @right, @bottom, @left) {
content: '';
position: absolute;
background-color: @color;
display: block;
z-index: 1;
top: @top;
right: @right;
bottom: @bottom;
left: @left;
}
//上边框
.hairline(@direction, @color: @border-color-base) when (@direction = 'top') {
border-top: 1PX solid @color;
@media (min-resolution: 2dppx) {
border-top: none;
&::before {
.scale-hairline-common(@color, 0, auto, auto, 0);
width: 100%;
height: 1PX;
transform-origin: 50% 50%;
transform: scaleY(0.5);
@media (min-resolution: 3dppx) {
transform: scaleY(0.33);
}
}
}
}
// 右边框
.hairline(@direction, @color: @border-color-base) when (@direction = 'right') {
border-right: 1PX solid @color;
@media (min-resolution: 2dppx) {
border-right: none;
&::after {
.scale-hairline-common(@color, 0, 0, auto, auto);
width: 1PX;
height: 100%;
background: @color;
transform-origin: 100% 50%;
transform: scaleX(0.5);
@media (min-resolution: 3dppx) {
transform: scaleX(0.33);
}
}
}
}
// 下边框
.hairline(@direction, @color: @border-color-base) when (@direction = 'bottom') {
border-bottom: 1PX solid @color;
@media (min-resolution: 2dppx) {
border-bottom: none;
&::after {
.scale-hairline-common(@color, auto, auto, 0, 0);
width: 100%;
height: 1PX;
transform-origin: 50% 100%;
transform: scaleY(0.5);
@media (min-resolution: 3dppx) {
transform: scaleY(0.33);
}
}
}
}
// 左边框
.hairline(@direction, @color: @border-color-base) when (@direction = 'left') {
border-left: 1PX solid @color;
@media (min-resolution: 2dppx) {
border-left: none;
&::before {
.scale-hairline-common(@color, 0, auto, auto, 0);
width: 1PX;
height: 100%;
transform-origin: 100% 50%;
transform: scaleX(0.5);
@media (min-resolution: 3dppx) {
transform: scaleX(0.33);
}
}
}
}
// 全边框
.hairline(@direction, @color: @border-color-base, @radius: 0) when (@direction = 'all') {
border: 1PX solid @color;
border-radius: @radius;
@media (min-resolution: 2dppx) {
position: relative;
border: none;
&::before {
content: '';
position: absolute;
left: 0;
top: 0;
width: 200%;
height: 200%;
border: 1PX solid @color;
border-radius: @radius * 2;
transform-origin: 0 0;
transform: scale(0.5);
box-sizing: border-box;
pointer-events: none;
}
}
}
在具体的页面中调用:
.div1{
.hairline('top',#eeeeee)
.hairline('right')
.hairline('left',#cccccc)
}
.div2{
.hairline('all',#bbbbbb,3px)
}
优点:使用 less 将 css 接口化,功能灵活,复用性和兼容性较好,通过媒体查询适配了 2 倍屏和 3 倍屏。该代码写在公共 css 样式中即可。 缺点:代码仍然有继续抽象的空间,并且此方案是使用 positon:absolute 进行定位,所以父元素也必须满足绝对定位的触发条件。
viewport + rem
通过设置对应 viewport 的 rem 基准值:
在设备的 dpr=2 时,设置 meta:
<meta name="viewport" content="width=device-width,initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no">
在设备的 dpr=3 时,设置 meta:
<meta name="viewport" content="width=device-width,initial-scale=0.3333333333333333, maximum-scale=0.3333333333333333, minimum-scale=0.3333333333333333, user-scalable=no">
块级元素 / 内联元素 / 替换元素 / 非替换元素
- 块级元素 —— 在浏览器显示时独占一行,默认情况下其宽度自动填满其父元素宽度,可设置 width/height/margin/padding 等属性,对应 display:block。
- 行内元素 —— 也称内联元素,相邻的行内元素会排列在同一行里,直到一行排不下,才会换行,其宽度随元素的内容而变化,设置 width/height 属性无效,边距属性的只有margin-left、margin-right、padding-left、padding-right,其它属性不会起边距效果。对应 display:inline。
- 替换元素 —— 浏览器根据元素的标签和属性,来决定元素的具体显示内容。替换元素一般有内在尺寸,所以具有 width/height 属性。常见的替换元素有 html 中的
<img>
<input>
<textarea>
<select>
<object>
。比如:<input>
标签是根据type属性来决定是显示输入框,还是提交按钮等等。 - 非替换元素 —— html 的大多数元素是不可替换元素,即其内容直接表现给用户端。
inline-block、inline 和 block 的区别
block
block 元素独占一行,多个 block 元素会各自新起一行。默认情况下,block 元素宽度自动填满其父元素宽度。
block 元素可以设置 width/height 属性。块级元素即使设置了宽度,仍然是独占一行。
block 元素可以设置 margin/padding 属性。
inline
inline 元素不会独占一行,多个相邻的行内元素会排列在同一行里,直到一行排列不下,才会新换一行,其宽度随元素的内容而变化。
inline 元素设置 width/height 属性无效。
inline 元素的 margin/padding 属性,水平方向的 padding-left, padding-right, margin-left, margin-right 都产生边距效果;但竖直方向的 padding-top, padding-bottom, margin-top, margin-bottom 不会产生边距效果。
inline-block
简单来说就是将对象呈现为 inline 对象,但是对象的内容作为 block 对象呈现。
之后的内联对象会被排列在同一行内。
比如我们可以给一个 link(a元素)inline-block 属性值,使其既具有 block 的宽度高度特性又具有 inline 的同行特性。
rem 和 em 和 vw 的区别
首先我们知道 px 是物理屏幕上最小的能显示出来的一个点
rem —— 元素相对于 html 根元素的字体大小
em —— 元素相对于父元素的字体大小
vw/vh —— 相对于屏幕的视图的高度和宽度,比如1vh 等于 100% 的视口高度
BFC
定义:块级格式化上下文,它是一个独立的渲染区域,规定了内部 Block-level Box 如何布局,并且与这个区域的外部毫不相关
创建了 BFC的元素就是一个独立的盒子,里面的子元素不会在布局上影响外面的元素(里面怎么布局都不会影响外部),BFC仍属于文档中的普通流
如何产生 BFC:display 属性为 block, list-item ,table 的元素,会产生 BFC。
作用
- 防止外边距重叠 - 在普通文档流中,元素(非BFC元素)的外边距margin会自动折叠,产生如下现象。
这个是 html 的特性不算 bug,但是我们更希望 margin 不产生折叠效果,通过利用 BFC 元素之间的外边距不会折叠的特性来实现。
- 清除浮动的影响 - BFC会包含创建它的元素内部的所有内容(包含浮动元素)
- 防止文字环绕(实现左图右文布局) - 利用浮动元产生BFC以及BFC之间不会互相覆盖实现左图右文布局
如何产生 BFC
这里可以总结称一句话:凡脱离文档流都可以产生 BFC
IFC / FFC / GFC
IFC
Inline Formatting Contexts - 内联格式化上下文
表现形式是:行级盒子在包含块里是从左到右水平排列的,上下文不单会决定盒子内的规则 也会决定自身的特性
FFC
Flex formatting contexts - 弹性盒模型
GFC
GrideLayout formatting contexts - 网格布局格式化上下文
Sass / Less / Stylus
层叠上下文 / z-index
层叠上下文
HTML 中三维的概念,每个盒模型中的位置是三维的,分别是平面画布上的 X 轴,Y 轴以及代表层叠的 Z 轴,通常元素都是沿着 X Y 轴平铺,一旦元素发生堆叠,就会发生某个元素盖着另外一个元素或者被覆盖。
层叠顺序
为什么定位元素会层叠在普通元素的上面
元素一旦成为定位元素,其 z-index 就会自动生效,此时 z-index: auto 也就是0级别, 根据上面的层叠顺序表,就会覆盖 inline 或 block 或 float 元素。 而不支持 z-index 的层叠上下文元素天然 z-index:auto 级别,层叠上下文元素和定位元素是一个层叠顺序的,于是当他们发生层叠的时候,遵循的是“后来居上”准则
position
基础
| 属性 | 解析 | 相对元素 | z-index 是否生效 |
|------|------------|------------|
| static | 默认值,遵循标准文档流中,top/right/bottom/left 等属性失效。 | - | 无效 |
| absolute | 绝对定位,对象脱离标准文档流,依赖 top/right/bottom/left 等属性 | 相对于static 定位以外的第一个父元素进行绝对定位,如果采用absolute的元素直接父容器position值为static,那么则会查询更上一层的父容器的position值,直到<body>
标签。 |有效 |
| relative | 相对定位,对象遵循标准文档流中,依赖 top/right/bottom/left 等属性,但是这些属性并不会改变该对象原本在文档流中的占位空间 |相对于该对象在标准文档流中的位置进行偏移 | 有效 |
| fixed | 固定定位,对象脱离标准文档流,依赖 top/right/bottom/left 等属性 | 相对于浏览器窗口进行绝对定位 | 有效 |
| sticky | 粘性定位,可以简单理解为 relative 和 fixed 布局的混合。 | - |
sticky
粘性定位,可以简单理解为 relative 和 fixed 布局的混合。
在了解粘性定位之前,我们需要知道以下的两个概念:
- 流盒 - 指的是粘性定位元素最近的可滚动元素(overflow 属性值不是 visible 的元素)的尺寸盒子,如果没有可滚动元素,则表示浏览器视窗盒子。
- 粘性约束矩形 - 即粘性布局元素的父级元素矩形
特点:
- 当粘性约束矩形在可视范围内为 relative,反之,则为 fixed
- 粘性定位元素如果和它的父元素一样高,则垂直滚动的时候,粘性定位效果是不会出现的
- 它的定位效果完全受限于父级元素们。如果父元素的 overflow 属性设置了 scroll,auto,overlay 值,那么,粘性定位将会失效
- 同一容器中多个粘贴定位元素独立偏移,因此可能重叠;位置上下靠在一起的不同容器中的粘贴定位元素则会鸠占鹊巢,挤开原来的元素,形成依次占位的效果。
float 原理
浮动出现的意义其实只是用来让文字环绕图片而已,仅此而已
float 的本质是带有方位的 display:inline-block 属性,display:inline-block 某种意义上的作用就是包裹 (wrap),float 无法等同于 display:inline-block,其中原因之一就是浮动 的方向 性,display:inline-block 仅仅一个水平排列方向,就是从左往右,而 float 可以从右往左排列, 这就是两者的差异。
清除浮动
- 给需要清除浮动的元素增加 clear 属性
- 浮动元素的父级增加 :after 伪元素
- 父元素增加 overflow 属性(BFC)