Appearance
盒模型
CSS 盒模型描述了以文档树中的元素而生成的矩形框,并根据排版模式进行布局。每个盒子都有一个内容区域(例如文本,图像等)以及周围可选的 padding、border 和 margin 区域。
CSS 盒模型负责计算:
- 块级元素占用多少空间
- 边框是否重叠,边距是否合并
- 盒子的尺寸
盒模型有以下规则:
- 块级元素的大小由 width、height、padding、border 和 margin 决定
- 如果没有指定 height,则块级元素的高度等于其包含子元素的内容高度加上 padding(除非有浮动元素,请参阅下文)
- 如果没有指定 width,则非浮动块级元素的宽度等于其父元素的宽度减去父元素的 padding
- 元素的 height 是由内容的 height 来计算的
- 元素的 width 是由内容的 width 来计算的。
- 默认情况下,padding 和 border 不是元素 width 和 height 的组成部分
* { box-sizing: border-box; } 会产生怎样的效果?
元素默认应用了
box-sizing: content-box,元素的宽高只会决定内容(content)的大小box-sizing: border-box改变计算元素width和height的方式,border和padding的大小也将计算在内元素的
height = 内容(content)的高度 + 垂直方向的 padding + 垂直方向 border 的宽度元素的
width = 内容(content)的宽度 + 水平方向的 padding + 水平方向 border 的宽度
inline, block, inline-block 有什么区别?
inline- 大小:取决于内容
- 定位:与其他内容一起流动,并允许旁边有其他元素
- 能否设置
width和height:不能 - 是否可以使用
vertical-align对齐:可以 - 边距(
margin)和填充(padding):只有水平方向存在。垂直方向会被忽略。尽管border和padding在content周围,但垂直方向上的空间取决于line-height - 浮动(
float):表现为一个block元素,可以设置垂直边距和填充
block- 大小:填充其父容器的宽度
- 定位:从新的一行开始,并且不允许旁边有 HTML 元素(除非是
float) - 能否设置
width和height:能 - 是否可以使用
vertical-align对齐:不可以 - 边距(
margin)和填充(padding):各个方向都存在 - 浮动(
float):-
inline-block- 大小:取决于内容
- 定位:与其他内容一起流动,并允许旁边有其他元素
- 能否设置
width和height:能 - 是否可以使用
vertical-align对齐:可以 - 边距(
margin)和填充(padding):各个方向都存在 - 浮动(
float):-
static, relative, absolute, fixed, sticky 定位有什么区别?
经过定位的元素,其 position 属性值必然是 relative / absolute / fixed / sticky
static: 默认定位属性值。该关键字指定元素使用正常的布局行为,即元素在文档常规流中当前的布局位置。此时top,right,bottom,left和z-index属性无效relative: 该关键字下,元素先放置在未添加定位时的位置,在不改变页面布局的前提下调整元素位置(因此会在此元素未添加定位时所在位置留下空白)absolute: 不为元素预留空间,通过指定元素相对于最近的非static定位祖先元素的偏移,来确定元素位置。绝对定位的元素可以设置外边距(margin),且不会与其他边距合并fixed: 不为元素预留空间,而是通过指定元素相对于屏幕视口(viewport)的位置来指定元素位置。元素的位置在屏幕滚动时不会改变。打印时,元素会出现在的每页的固定位置。fixed属性会创建新的层叠上下文。当元素祖先的transform属性非none时,容器由视口改为该祖先sticky: 盒位置根据正常流计算(这称为正常流动中的位置),然后相对于该元素在流中的 flow root(BFC)和 containing block(最近的块级祖先元素)定位。在所有情况下(即便被定位元素为 table 时),该元素定位均不对后续元素造成影响。当元素 B 被粘性定位时,后续元素的位置仍按照 B 未定位时的位置来确定。position: sticky对table元素的效果与position: relative相同
flex 布局
flex 主要用于一维布局。
flex 容器中存在两条轴,横轴和纵轴,容器中的每个单元称为 flex item。
在容器上可以设置6个属性:flex-direction, flex-wrap, flex-flow, justify-content, align-items, align-content
**注意:**当设置 flex 布局之后,子元素的 float, clear, vertical-align 的属性将会失效。
有六种属性可运用在 item 项目上: order, flex-basis, flex-grow, flex-shrink, flex, align-self
参考资料:
grid 布局
Grid 主要用于二维布局。
CSS 网格布局用于将页面分割成数个主要区域,或者用来定义组件内部元素间大小、位置和图层之间的关系。
像表格一样,网格布局让我们能够按行或列来对齐元素。但是,使用 CSS 网格可能还是比 CSS 表格更容易布局。例如,网格容器的子元素可以自己定位,以便它们像 CSS 定位的元素一样,真正的有重叠和层次。
Grid 布局与 Flex 布局有一定的相似性,都可以指定容器内部多个项目的位置。但是,它们也存在重大区别。
Flex 布局是轴线布局,只能指定「项目」针对轴线的位置,可以看作是一维布局。Grid 布局则是将容器划分成「行」和「列」,产生单元格,然后指定「项目所在」的单元格,可以看作是二维布局。Grid 布局远比 Flex 布局强大。
容器属性:display: grid;, grid-template-columns, grid-template-rows, grid-column-gap, grid-row-gap, grid-gap, grid-template-areas, grid-auto-flow, justify-items, align-items, justify-content, align-content, grid-auto-columns, grid-auto-rows
项目属性:grid-column-start, grid-column-end, grid-row-start, grid-row-end, grid-area, justify-self, align-self
**注意:**设为网格布局以后,容器子元素(项目)的 float、display: inline-block、display: table-cell、vertical-align 和 column-* 等设置都将失效。
参考资料:
css 单位
px, em, rem, vw, vh, vmin, vmax, %
扩展至 rem & vw 移动端适配问题
css 选择器
css 选择符(css 选择器)有哪些?
- 标签选择器(如:
body,div,p,ul,li) - 类选择器(如:
class="head",class="head_logo") - ID选择器(如:
id="name",id="name_txt") - 全局选择器(如:
*号) - 组合选择器(如:
.head .head_logo, 注意两选择器用空格键分开) - 后代选择器 (如:
#head .nav ul li从父集到子孙集的选择器) - 群组选择器(如:
div, span, img { color: red }即具有相同样式的标签分组显示) - 继承选择器(如:
div p,注意两选择器用空格键分开) - 伪类选择器(如:就是链接样式,a 元素的伪类,4种不同的状态:
link,visited,active,hover) - 字符串匹配的属性选择符(
^,$,*三种,分别对应开始、结尾、包含) - 子选择器 (如:
div > p,带大于号>) - CSS 相邻兄弟选择器 (如:
h1 + p,带加号+)
CSS 选择器的优先级是如何计算的?
浏览器通过优先级规则,判断元素展示哪些样式。CSS 优先级是由四个级别和各级别的出现次数决定的。四个级别分别为:行内选择符、ID选择符、类别选择符、元素选择符。我们假定以a、b、c、d命名,分别代表以下含义:
- a. 表示是否使用内联样式(inline style),如果使用,a 为 1,否则为 0
- b. 表示 ID 选择器的数量
- c. 表示类选择器、属性选择器和伪类选择器数量之和
- d. 表示标签(类型)选择器和伪元素选择器之和。
优先级的结果并非通过以上四个值生成一个得分,而是每个值分开比较。a、b、c、d 权重从左到右,依次减小。判断优先级时,从左到右,一一比较,直到比较出最大值,即可停止。所以,如果 b 的值不同,那么 c 和 d 不管多大,都不会对结果产生影响。比如 0, 1, 0, 0 的优先级高于 0, 0, 10, 10。
当出现优先级相等的情况时,最晚出现的样式规则会被采纳。如果你在样式表里写了相同的规则(无论是在该文件内部还是其它样式文件中),那么最后出现的(在文件底部的)样式优先级更高,因此会被采纳。
在写样式时,我会使用较低的优先级,这样这些样式可以轻易地覆盖掉。尤其对写 UI 组件的时候更为重要,这样使用者就不需要通过非常复杂的优先级规则或使用 !important 的方式,去覆盖组件的样式了。
总结排序:!important > 行内样式 > ID选择器 > 类选择器 > 标签 > 通配符 > 继承 > 浏览器默认属性
参考资料:
怎样覆盖 !important
- 添加一样选择器,把它的位置放在原有声明的后面(总之,最后定义一条规则比胜)
- 添加一条 带
!important的 CSS 规则,再给这个给选择器更高的优先级(添加一个标签,ID 或类)
比如:
css
table td { height: 50px !important; }
table td { height: 60px !important; }
/* or */
table td { height: 50px !important; }
#myTable td { height: 60px !important; }BFC 清除浮动
什么是 BFC?
BFC 是 W3C CSS2.1 规范中的一个概念,它决定了元素如何对其子元素进行定位,以及与其它元素的关系和相互作用。
当涉及到可视化布局的时候,BFC 提供了一个环境,HTML 元素在这个环境中按照一定规则进行布局。一个环境中的元素不会影响到其它环境中的布局。比如浮动元素会形成 BFC,浮动元素内部子元素的主要受该浮动元素影响,两个浮动元素之间是互不影响的。这里有点类似一个 BFC 就是一个独立的行政单位的意思。
怎样才能形成 BFC
float的值不为noneoverflow的值不为visibledisplay的值为inline-block,flex,inline-flex,table-cell,table-caption中的任何一个position的值不为relative和static
BFC 的特点:
- 不和浮动元素重叠
- 清除元素内部浮动
- 嵌套元素 margin 边距折叠问题的解决 按照 BFC 的定义,只有同属于一个 BFC 时,两个元素才有可能发生垂直
margin的重叠,这个包括相邻元素,嵌套元素,只要他们之间没有阻挡(例如边框,非空内容,padding等)就会发生margin重叠。因此要解决margin重叠问题,只要让它们不在同一个 BFC 就行了。
扩展:
- IFC(Inline formatting contexts) 内联格式上下文 IFC 的 line box(线框)高度由其包含行内元素中最高的实际高度计算而来(不受到竖直方向的
padding/margin影响)。IFC 中的 line box 一般左右都贴紧整个 IFC,但是会因为float元素而扰乱。float元素会位于 IFC 与 line box 之间,使得 line box 宽度缩短。 同个 IFC 下的多个 line box 高度会不同。IFC 中是不可能有块级元素的,当插入块级元素时(如span中插入div)会产生两个匿名块与div分隔开,即产生两个 IFC,每个 IFC 对外表现为块级元素,与div垂直排列。那么 IFC 一般有什么用呢? + 水平居中:当一个块要在环境中水平居中时, 设置其为inline-block则会在外层产生 IFC,通过text-align则可以使其水平居中 + 垂直居中:创建一个 IFC,用其中一个元素撑开父元素的高度,然后设置其vertical-align: middle,其他行内元素则可以在此父元素下垂直居中 - GFC(GrideLayout formatting contexts) 网格布局格式化上下文当为一个元素设置
display值为grid的时候,此元素将会获得一个独立的渲染区域,我们可以通过在网格容器(grid container)上定义「网格定义行」(grid definition rows)和「网格定义列」(grid definition columns)属性,和在网格项目(grid item)上定义网格行(grid row)和网格列(grid columns) 为每一个网格项目(grid item)定义位置和空间。那么 GFC 有什么用呢,和 table 又有什么区别呢? 首先同样是一个二维的表格,但 GridLayout 会有更加丰富的 属性来控制行列,控制对齐以及更为精细的渲染语义和控制。 - FFC(Flex formatting contexts) 自适应格式上下文
display值为flex或者inline-flex的元素将会生成自适应容器(flex container)。Flex Box 由伸缩容器和伸缩项目组成。通过设置元素的display属性为flex或inline-flex可以得到一个伸缩容器。设置为flex的容器被渲染为一个块级元素, 而设置为inline-flex的容器则渲染为一个行内元素。伸缩容器中的每一个子元 素都是一个伸缩项目。伸缩项目可以是任意数量的。伸缩容器外和伸缩项目内的一切元素都不受影响。简单地说,Flexbox 定义了伸缩容器内伸缩项目该如何布局。
请阐述 z-index 属性,并说明如何形成层叠上下文
CSS 中的 z-index 属性控制重叠元素的垂直叠加顺序。z-index 只能影响 position 值不是 static 的元素。
没有定义 z-index 的值时,元素按照它们出现在 DOM 中的顺序堆叠(层级越低,出现位置越靠上)。非静态定位的元素(及其子元素)将始终覆盖静态定位(static)的元素,而不管 HTML 层次结构如何。
层叠上下文是包含一组图层的元素。在一组层叠上下文中,其子元素的 z-index 值是相对于该父元素而不是 document root 设置的。每个层叠上下文完全独立于它的兄弟元素。如果元素 B 位于元素 A 之上,则即使元素 A 的子元素 C 具有比元素 B 更高的 z-index 值,元素 C 也永远不会在元素 B 之上。
每个层叠上下文是自包含的:当元素的内容发生层叠后,整个该元素将会在父层叠上下文中按顺序进行层叠。少数 CSS 属性会触发一个新的层叠上下文,例如 opacity 小于 1,filter 不是 none,transform 不是 none。
常见页面布局
响应式设计与自适应设计有何不同?
响应式设计和自适应设计都以提高不同设备间的用户体验为目标,根据视窗大小、分辨率、使用环境和控制方式等参数进行优化调整。
响应式设计的适应性原则:网站应该凭借一份代码,在各种设备上都有良好的显示和使用效果。响应式网站通过使用媒体查询,自适应栅格和响应式图片,基于多种因素进行变化,创造出优良的用户体验。就像一个球通过膨胀和收缩,来适应不同大小的篮圈。
自适应设计更像是渐进式增强的现代解释。与响应式设计单一地去适配不同,自适应设计通过检测设备和其他特征,从早已定义好的一系列视窗大小和其他特性中,选出最恰当的功能和布局。与使用一个球去穿过各种的篮筐不同,自适应设计允许使用多个球,然后根据不同的篮筐大小,去选择最合适的一个。
CSS 预处理,后处理
使用 CSS 预处理的优缺点分别是什么?
优点:
- 提高 CSS 可维护性
- 易于编写嵌套选择器
- 引入变量,增添主题功能,可以在不同的项目中共享主题文件
- 通过混合(Mixins)生成重复的 CSS
- 可将代码分割成多个文件,方便维护(未使用预处理的 CSS,虽然也可以分割成多个文件,但需要建立多个 HTTP 请求加载这些文件)
缺点:
- 需要预处理工具
- 重新编译的时间可能会很慢
对于你使用过的 CSS 预处理,说说喜欢和不喜欢的地方?
喜欢:
- 绝大部分优点上题以及提过
- Less 用 JavaScript 实现,与 NodeJS 高度结合
Dislikes:
- 通过 node-sass 使用 Sass,它用 C ++ 编写的 LibSass 绑定。在 Node 版本切换时,我必须经常重新编译。
- Less 中,变量名称以
@作为前缀,容易与 CSS 关键字混淆,如@media、@import和@font-face
CSS3 新特性
animation 和 transiton 的相关属性 animate 和 translate
display 哪些取值
none, block, inline, inline-block, table, table-row, table-cell, list-item 等。
相邻的两个 inline-block 节点为什么会出现间隔,该如何解决
这个特性的原因可以上述到 SGML(标准通用标记语言) 和 TeX(排版工具),它实际上是一个行内(inline)的问题,它由空格/换行/回车所产生空白符所致。
去除 inline box 元素之间间隙的方法:
- 干掉元素之间的空格/换行/回车
- 使用
margin负值margin负值的大小与上下文的字体和文字大小相关。由于外部环境的不确定性及最后一个元素多出的父margin值等问题,这个方法不适合大规模使用。 - 使用
font-size: 0(基本上可以解决大部分浏览器下 inline box 类元素之间间距导致的问题) letter-spacing/word-spacing(在不同浏览器下表现不同,同样不适合大规模使用)
实际应用上,以上四种方法其实都不实用,第一种不方便书写,后几种会导致内容和格式的依赖性较强,违背内容与样式分离的要求。在实际布局中也很少单纯用 inline-block 排版,经常和 float,position, flex 等配合使用
meta viewport 移动端适配
viewport 是用户网页的可视区域。
手机浏览器是把页面放在一个虚拟的「窗口」(viewport)中,通常这个虚拟的「窗口」(viewport)比屏幕宽,这样就不用把每个网页挤到很小的窗口中(这样会破坏没有针对手机浏览器优化的网页的布局),用户可以通过平移和缩放来看网页的不同部分。
一个常用的针对移动网页优化过的页面的 viewport meta 标签大致如下:
html
<meta name="viewport" content="width=device-width, initial-scale=1" />viewport 属性值:
width:控制 viewport 的大小,可以指定的一个值,如600,或者特殊的值,如device-width为设备的宽度(单位为缩放为 100% 时的 CSS 的像素)height:和 width 相对应,指定高度initial-scale:初始缩放比例,也即是当页面第一次 load 的时候缩放比例。maximum-scale:允许用户缩放到的最大比例minimum-scale:允许用户缩放到的最小比例user-scalable:用户是否可以手动缩放(yes/no)
CSS 实现宽度自适应 100%,宽高 16:9 的比例的矩形
html
<div class="box">
<div class="scale">
<p class="item">这是一个16:9的矩形</p>
</div>
</div>css
.box {
width: 80%;
}
.scale {
position: relative;
width: 100%;
height: 0;
padding-bottom: 56.25%;
}
.item {
width: 100%;
height: 100%;
background-color: aquamarine;
position: absolute;
}rem 布局的优缺点
优点:
- 兼容性强
- 能够较完美实现弹性布局
缺点:
- 非标准移动端适配方案,依赖 JS
- 由于设置了根元素字体的大小,会影响所有没有设置字体大小的元素(可以在
body上做字体修正解决) - 字体大小不能使用
rem,字体的大小和字体宽度,并不成线性关系
参考资料:
画三角形
css
.info-tab {
position: relative;
}
.info-tab::after {
content: '';
border: 4px solid transparent;
border-top-color: #2c8ac2;
position: absolute;
top: 0;
}1像素边框问题
逻辑像素:CSS 像素 物理像素:设备像素
为什么移动端 CSS 里面写了 1px,实际上看起来比 1px 粗?
CSS 1px 实际占用了 2px 物理像素,在多倍屏下就显得粗了。
- Flexible 方案
@media (-webkit-min-device-pixel-ratio: 2) {}+0.5px方案(iOS7 及以下浏览器0.5px表现为0px)border-image方案background-image方案postcss-write-svg插件(border-image/background+svg)方案box-shadow方案(-webkit-box-shadow: 0 1px 1px -1px rgba(0, 0, 0, 0.5);)::before/::after+transform方案(transform: scale(0.5))
编写高效的 CSS 应该注意什么?
首先,浏览器从最右边的选择器,即关键选择器(key selector),向左依次匹配。根据关键选择器,浏览器从 DOM 中筛选出元素,然后向上遍历被选元素的父元素,判断是否匹配。选择器匹配语句链越短,浏览器的匹配速度越快。避免使用标签和通用选择器作为关键选择器,因为它们会匹配大量的元素,浏览器必须要进行大量的工作,去判断这些元素的父元素们是否匹配。
BEM 原则上建议为独立的 CSS 类命名,并且在需要层级关系时,将关系也体现在命名中,这自然会使选择器高效且易于覆盖。
搞清楚哪些 CSS 属性会触发重新布局(reflow)、重绘(repaint)和合成(compositing)。在写样式时,避免触发重新布局的可能。
什么情况下,用 translate() 而不用绝对定位?什么时候,情况相反。
translate() 是 transform 的一个值。改变 transform 或 opacity 不会触发浏览器重新布局(reflow)或重绘(repaint),只会触发复合(compositions)。而改变绝对定位会触发重新布局,进而触发重绘和复合。transform 使浏览器为元素创建一个 GPU 图层,但改变绝对定位会使用到 CPU。因此 translate() 更高效,可以缩短平滑动画的绘制时间。
当使用 translate() 时,元素仍然占据其原始空间(有点像 position:relative),这与改变绝对定位不同。
文本超出部分显示省略号
单行:
css
.ellips {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}多行:
css
.ellips-multi {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3; /* 最多显示几行 */
overflow: hidden;
}link 和 @import 的区别浅析
- 从属关系区别
@import是 CSS 提供的语法规则,只有导入样式表的作用;link是 HTML 提供的标签,不仅可以加载 CSS 文件,还可以定义 RSS、rel 连接属性等 - 加载顺序区别 加载页面时,
link标签引入的 CSS 被同时加载;@import引入的 CSS 将在页面加载完毕后被加载 - 兼容性区别
@import是 CSS2.1 才有的语法,故只可在 IE5+ 才能识别;link标签作为 HTML 元素,不存在兼容性问题 - DOM可控性区别 可以通过 JS 操作 DOM ,插入
link标签来改变样式;由于 DOM 方法是基于文档的,无法使用@import的方式插入样式 - 权重区别
link引入的样式权重大于@import引入的样式
如何仅使用 CSS 提升页面渲染速度?
- 内容可见性
content-visibility - 合理使用
will-change - 让元素及其内容尽可能独立于文档树的其余部分
contain - 使用
font-display解决由于字体造成的布局偏移 - 使用
scroll-behavior让滚动更流畅 - 开启 GPU 渲染动画
- 减少阻塞渲染的时间(拆分多个 stylesheet,通过添加 media 属性附加媒体查询,告诉浏览器何时应用样式表)
- 避免
@import包含多个样式表(@import是一个阻塞调用) - 注意动态修改自定义属性方式(通过
style.setProperty修改根自定义属性会影响 Web 的性能)
参考资料:
