盒模型
在 css 中,有两种盒模型:
- 标准盒模型(
box-sizing: content-box
):
这是我们熟悉的符合 W3C 标准的盒子模型
尺寸计算公式:
width = 内容的宽度
height = 内容的高度
不包含border
,padding
- IE 盒模型(
box-sizing: border-box
):
这种模型更适合制作宽度固定的布局。
尺寸计算公式:
width = border + padding + 内容的宽度
height = border + padding + 内容的高度
css 选择器
选择器 | 示例 |
---|---|
通配符选择器 | * { } |
类选择器 | .box{ } |
id 选择器 | #app { } |
标签选择器 | p{ } |
标签属性选择器 | p[title]{ } |
伪类选择器 | p:first-child{ } |
伪元素选择器 | p::first-line{ } |
后代选择器(可以是 article 后任意层级的 p 标签) | article p { } |
子代选择器(只能匹配 article 下一级的 p 标签) | article > p { } |
相邻兄弟选择器 | h1 + p { } |
通用兄弟选择器 | h1 ~ p { } |
权重的五个等级及其权重
!important; +∞
行内样式; 1000
ID 选择器, 权重:100;
class,属性选择器和伪类选择器,权重:10;
属性选择器指的是:根据元素的属性及属性值来选择元素,比如button[type]
属性等。
伪类选择器::active
:focus
等选项.标签选择器和伪元素选择器,权重:1;
伪元素选择器: :before :after
等级关系:
!important>行内样式>ID 选择器 > 类选择器 | 属性选择器 | 伪类选择器 > 元素选择器
如何判断选择器的优先级
选择器 | ID | 类 | 元素 | 优先级 |
---|---|---|---|---|
h1 | 0 | 0 | 1 | 0-0-1 |
h1 + p::first-letter | 0 | 0 | 3 | 0-0-3 |
li > a[href*=”en-US”] > .inline-warning | 0 | 2 | 2 | 0-2-2 |
#identifier | 1 | 0 | 0 | 1-0-0 |
button:not(#mainBtn, .cta) | 1 | 0 | 1 | 1-0-1 |
Web 坐标轴(CSS 坐标系统)
web 坐标轴不同于数学上的坐标轴,web 坐标轴的默认原点是给定上下文的左上角,就是元素盒子的左上角。它们分别为以下三种:
- x 轴(水平方向) 向右为正值,向左为负值
- y 轴(垂直方向) 向下为正值,向上为负值
- z 轴(用于给定位元素控制层叠顺序,即 position 属性为非
static
的元素),使用z-index
控制元素的层叠顺序,值越大,层级越靠前(类似于 ps 的图层)
css 浮动(Float)以及其工作原理
- 浮动元素从网页的正常流中移出,但是保留了部分流动性。会影响其他元素的定位(比如文字会围绕着浮动元素)。这一点和绝对定位(absolute)不同,absolute 元素完全脱离的文档流
- 如果浮动元素的父元素只包含浮动元素,那么该父元素的高度会坍塌为 0,我们可以通过清除从浮动元素后到父元素关闭前之间的浮动来修复这个问题(
clear: both | left | right
)。如, 给父元素加伪类
.father::after {
content: " ";
display: block;
clear: both;
}
- 把浮动元素的父元素属性设置为
overflow: auto | hidden
,会使其内部形成 BFC , 并且父元素会扩张自己,使其能够包围它的子元素
CSS 盒模型中的四种布局模式
IFC(Inline Formatting Contexts,行内格式化上下文)
IFC(Inline Formatting Contexts)直译为”内联格式化上下文”,IFC 的 line box(线框)高度由其包含行内元素中最高的实际高度计算而来(不受到竖直方向的 padding/margin 影响)
IFC 中的 line box 一般左右都贴紧整个 IFC,但是会因为 float 元素而扰乱。float 元素会位于 IFC 与与 line box 之间,使得 line box 宽度缩短。 同个 ifc 下的多个 line box 高度会不同。 IFC 中时不可能有块级元素的,当插入块级元素时(如 p 中插入 div)会产生两个匿名块与 div 分隔开,即产生两个 IFC,每个 IFC 对外表现为块级元素,与 div 垂直排列。
那么 IFC 一般有什么用呢?
水平居中:当一个块要在环境中水平居中时,设置其为 inline-block 则会在外层产生 IFC,通过 text-align 则可以使其水平居中。
垂直居中:创建一个 IFC,用其中一个元素撑开父元素的高度,然后设置其 vertical-align:middle,其他行内元素则可以在此父元素下垂直居中。
BFC(Block Formatting Contexts,块级格式化上下文)
BFC 是一种属性,它会影响元素的定位以及与其兄弟元素之间的互相作用。 中文常译为 块级格式化上下文 。是 W3C CSS 2.1 规范中的一个概念,它决定了元素如何对其内容进行定位,以及与其他元素的关系和相互作用。 在进行盒子元素布局的时候,BFC 提供了一个环境,在这个环境中按照一定规则进行布局不会影响到其它环境中的布局。比如浮动元素会形成 BFC,浮动元素内部子元素的主要受该浮动元素影响,两个浮动元素之间是互不影响的。 也就是说,如果一个元素符合了成为 BFC 的条件,该元素内部元素的布局和定位就和外部元素互不影响(除非内部的盒子建立了新的 BFC),是一个隔离了的独立容器。(在 CSS3 中,BFC 叫做 Flow Root)
形成条件
- 浮动元素,float 除 none 以外的值;
- 绝对定位元素,position(absolute,fixed);
- display 为以下其中之一的值 inline-blocks,table-cells,table-captions;
- overflow 除了 visible 以外的值(hidden,auto,scroll)
参考:
MDN
FFC(Flex Formatting Contexts,弹性格式化上下文)
用于排列弹性盒子,其中弹性盒子具有更灵活的布局方式,可以通过指定伸缩比例、对齐方式等属性来调整布局。
GFC(Grid Formatting Contexts,网格格式化上下文)
用于排列网格盒子,其中网格盒子具有二维的排列方式,可以通过指定行列数、单元格大小、对齐方式等属性来调整布局。
移动端适配方案
在正常开发中,UI/UX 给出的都是一个具体设计稿,都是px
尺寸的。那么无论是下面那种适配方案,其核心都是需要根据设计稿上的元素占设计稿的比例。
比如常见的 750 设计稿(通常是指以 iPhone 6/7/8 为基准的设计稿),它的屏幕宽度为 750px(像素)
,屏幕高度为 1334px(像素)
。
那么我们可以选择一个可以让我们在后面填写元素尺寸时比较好计算的 750px / 7.5 = 100px
。也就是说,我们将屏幕的宽度分成了7.5份
,每一份占100px
。
如果使用rem
布局,那么需要在根元素设置font-size
,表示我们的1em
为 100px
html {
font-size: 100px;
}
后面,我们通过设计稿绘制页面的时候,如果遇到需要绘制一个 div 为 200px * 200px ,内部字体为 16px 的,那么我们只需要根据设计稿上元素的尺寸 / 100
就可以得到各种元素所占屏幕的比例,来完成在各种不同移动端设备下的适配
div {
font-size: 0.16em;
width: 2em;
height: 2em;
}
- 媒体查询可用于响应式网站样式,也可针对不同型号手机的尺寸写不同的样式
- 通过 rem 布局
- 通过 vw/vh 布局移动端 css
px、em、rem 区别
- px 是固定的像素,一旦设置了就无法因为适应页面大小而改变
- em 和 rem 相对于 px 更具有灵活性,它们是相对长度单位,即长度不固定,适合响应式布局
- em 是相对其父元素来设置字体大小的,一般都是以 body 的 font-size 为基准。这样会有一个问题,进行任何元素设置,
都可能需要知道他父元素的大小。 - rem 是相对于根元素 html 的
font-size
;
em 相对于父元素
<div>
父元素div
<p>
子元素p
<span>孙元素span</span>
</p>
</div>
div {
font-size: 40px;
width: 7.5em; /* 300px */
height: 7.5em;
border: solid 2px black;
}
p {
font-size: 0.5em; /* 20px */
width: 7.5em; /* 150px */
height: 7.5em;
border: solid 2px blue;
color: blue;
}
span {
font-size: 0.5em;
width: 7em;
height: 6em;
border: solid 1px red;
display: block;
color: red;
}
rem 相对于更元素 html。
<div>
父元素div
<p>
子元素p
<span>孙元素span</span>
</p>
</div>
html {
font-size: 10px;
}
div {
font-size: 4rem; /* 40px */
width: 20rem; /* 200px */
height: 20rem;
border: solid 2px black;
}
p {
font-size: 2rem; /* 20px */
width: 10rem;
height: 10rem;
border: solid 1px blue;
color: blue;
}
span {
font-size: 1.5rem;
width: 7rem;
height: 6rem;
border: solid 2px red;
display: block;
color: red;
}
如果设计中使用了非标准的字体,你该如何去实现?
- 用图片代替
- web fonts 在线字库,如Google Webfonts,Typekit 等等;
浏览器如何判断元素是否匹配某个 CSS 选择器?
从后往前判断。
浏览器先产生一个元素集合,这个集合往往由最后一个部分的索引产生(如果没有索引就是所有元素的集合)。
然后向上匹配,如果不符合上一个部分,就把元素从集合中删除,直到真个选择器都匹配完,还在集合中的元素就匹配这个选择器了。
举个例子,有选择器:body.ready #wrapper > .lol233
先把所有 class 中有 lol233 的元素拿出来组成一个集合,然后上一层,对每一个集合中的元素,如果元素的 parent id 不为 #wrapper 则把元素从集合中删去。 再向上,从这个元素的父元素开始向上找,没有找到一个 tagName 为 body 且 class 中有 ready 的元素,就把原来的元素从集合中删去。
至此这个选择器匹配结束,所有还在集合中的元素满足。
大体就是这样,不过浏览器还会有一些奇怪的优化。
为什么从后往前匹配因为效率和文档流的解析方向。效率不必说,找元素的父亲和之前的兄弟比遍历所有儿子快而且方便。关于文档流的解析方向,是因为现在的 CSS,一个元素只要确定了这个元素在文档流之前出现过的所有元素,就能确定他的匹配情况。应用在即使 html 没有载入完成,浏览器也能根据已经载入的这一部分信息完全确定出现过的元素的属性。为什么是用集合主要也还是效率。基于 CSS Rule 数量远远小于元素数量的假设和索引的运用,遍历每一条 CSS Rule 通过集合筛选,比遍历每一个元素再遍历每一条 Rule 匹配要快得多。
伪元素 (pseudo-elements) 及其用途
inline 和 inline-block 的区别
- inline(行内元素): 无法设置宽高,不独占一行, 竖直方向的 margin(margin-top、margin-bottom)不生效。
- inline-block(行内块元素): 可以设置宽高,不独占一行
relative、fixed、absolute、static、sticky 元素的区别
relative | fixed | absolute | static | sticky | |
---|---|---|---|---|---|
含义 | 相对定位 | 固定定位 | 绝对定位 | 静态定位 | 相对定位 |
是否脱离正常文档流 | 是 | 是 | 是 | 否 | 否 |
是否还占用正常文档流的位置 | 是 | 否 | 否 | - | 是 |
相对于什么定位 | 元素本身在正常文档流的位置 | 相对于浏览器窗口 | 相对于 static 定位以外的第一个父元素左上角 border 与 padding 交界处定位 | - | 相对它的最近滚动祖先(当该祖先的 overflow 是 hidden, scroll, auto, 或 overlay 时) 和 最近块级祖先,包括 table-related 元素,基于 top, right, bottom, 和 left 的值进行偏移。 |
响应式和自适应的区别
响应式和自适应都是为了解决不同设备上的适配问题,但它们的实现方式有所不同。
响应式(Responsive Design) = 所有设备的代码是一样的
比如使用弹性网格布局(Flexible Grid Layout):通过使用弹性布局和百分比来设计网格系统,使网格布局能够适应不同的屏幕尺寸。
自适应(Adaptive Design)= 不同设备的代码是不一样的
使用@media
规则定义不同屏幕尺寸下的样式,比如:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>自适应设计</title>
<style>
/* 默认样式 */
body {
font-size: 16px;
}
/* 在窗口宽度小于等于600px时的样式 */
@media (max-width: 600px) {
body {
font-size: 14px;
}
}
/* 在窗口宽度大于600px且小于等于1200px时的样式 */
@media (min-width: 601px) and (max-width: 1200px) {
body {
font-size: 18px;
}
}
/* 在窗口宽度大于1200px时的样式 */
@media (min-width: 1201px) {
body {
font-size: 20px;
}
}
</style>
</head>
<body>
<h1>自适应设计</h1>
<p>这是一段自适应设计的示例文本。</p>
</body>
</html>
translate() 和 absolute position,或反之的理由?为什么?
通过 absolute 定位属性实现的移动,通过 translate 也可以实现,两者结合使用可以实现元素的居中。
1. 文档流上的差异:
absolute 会脱离文档流,而 translate 不会脱离文档流
2. 基点上的差异:
absolute 是基于第一个非 static 父元素的左上角 border 与 padding 交界处,而 translate 是子元素整体平移,没有所谓的基点而言,当然通过 transform-origin 改变旋转的基准点?
3. 视图属性上的差异:
可以看出使用 translate 的例子的 offsetTop 和 offsetLeft 的数值与没有产生位移的元素没有然后区别,无论位移多少这两个数值都是固定不变的。
而使用相对定位的例子 offsetTop 和 offsetLeft 的数值则根据位移的长度发生了改变。
4. 动画表现上的差异:
使用绝对定位的动画效果会受制于利用像素(px)为单位进行位移,而使用 translate 函数的动画则可以不受像素的影响,以更小的单位进行位移。
另外,绝对定位的动画效果完全使用 CPU 进行计算,而使用 translate 函数的动画则是利用 GPU,因此在视觉上使用 translate 函数的动画可以有比绝对定位动画有更高的帧数。
css3 动画
@keyframes first {
from {
background: yellow;
width: 100px;
}
to {
background: green;
width: 200px;
}
}
div {
animation: first 2s;
}