推荐大家的使用本篇文章的方式:
先看问题自己会不会,如果会的话,要自己说一遍,组织好语言。
CSS的面试内容主要可以分四个部分:
CSS基础、页面布局、定位与浮动和场景应用
CSS部分会涉及到代码的编写,需要自己动手敲一下,面试的时候可能会涉及让你手写或者口述代码。
选择器 | 格式 | 优先级权重 |
---|---|---|
id选择器 | #id | 100 |
类选择器 | .classname | 10 |
属性选择器 | a[ref=“lll”] | 10 |
伪类选择器 | li:last-child | 10 |
标签选择器 | div | 1 |
伪元素选择器 | li:after | 1 |
相邻兄弟选择器 | h1+p | 0 |
子选择器 | ul>li | 0 |
后代选择器 | li a | 0 |
通配符选择器 | * | 0 |
需要特别说明的点:
属性值 | 作用 |
---|---|
none | 元素不显示,并且会从文档流中移除 |
block | 块类型。默认宽度为父元素宽度,可设置宽高,换行显示 |
inline | 行内元素类型。默认宽度为内容宽度,不可设置宽高,但可以设置水平方向的宽度,同行显示 |
inline-block | 默认宽度为内容宽度,可以设置宽高,同行显示 |
list-item | 和block显示方式相同,并铁剑样式列表标记 |
table | 块级表格来显示 |
inherit | 从父元素继承display属性的值 |
注意:block、inline和inline-block的区别,这也是一个常问的点
注意:display:none 和 visibility:hidden的区别也是常考的问题
1) display会让元素完全从渲染树中消失,在页面中不会占据任何位置
visibility不会让元素从渲染树中消失,在页面中会占据空间
2) 是否是继承属性
display是非继承属性,子孙节点也会消失,即使修改子孙节点的属性也无法显示
visibility是继承属性,子孙节点消失是因为继承乐hidden,如果更改属性为visible就可以让子孙节点显示
3) 修改常规文档刘中元素的display会导致文档的重排,但是修改visibility只会造成本元素的重绘
4) 如果使用读屏器,display:none的内容不会被读取,visibility:hidden会被读取
盒模型有两种:
width和height的范围不同
通过box-sizing属性来改变元素的盒模型:
box-sizing:content-box 表示标准盒模型
box-sizing:border-box 表示怪异盒模型(IE盒模型)
最全CSS3新特性总结
这篇文章里面有每一点详细的讲解
● 单行文本溢出
overflow: hidden; // 溢出隐藏
text-overflow: ellipsis; // 溢出用省略号显示
white-space: nowrap; // 规定段落中的文本不进行换行
● 多行文本溢出
overflow: hidden; // 溢出隐藏
text-overflow: ellipsis; // 溢出用省略号显示
display:-webkit-box; // 作为弹性伸缩盒子模型显示。
-webkit-box-orient:vertical; // 设置伸缩盒子的子元素排列方式:从上到下垂直排列
-webkit-line-clamp:3; // 显示的行数
注意:由于上面的三个属性都是 CSS3 的属性,没有浏览器可以兼容,所以要在前面加一个-webkit- 来兼容一部分浏览器。
一、无继承性的属性
二、有继承性的属性
两者都是外部引用CSS的方式。
它们的区别如下:
● link是XHTML标签,除了加载CSS外,还可以定义RSS等其他事务;@import属于CSS范畴,只能加载CSS。
● link引用CSS时,在页面载入时同时加载;@import需要页面网页完全载入以后加载。
● link是XHTML标签,无兼容问题;@import是在CSS2.1提出的,低版本的浏览器不支持。
● link支持使用Javascript控制DOM去改变样式;而@import不支持。
伪元素和伪类的区别总结
伪类和伪元素的根本区别在于:是否创造了新的元素
伪元素:不存在在DOM文档中,是虚拟的元素,是创建新元素。代表某个元素的子元素,这个子元素虽然在逻辑上存在,但却并不实际存在于文档树中。在内容元素的前后插入额外的元素或样式,但是这些元素实际上并不在文档中生成。它们只在外部显示可见,但不会在文档的源代码中找到它们,因此,称为“伪”元素。
p::before {content:"第一章:";}
p::after {content:"Hot!";}
p::first-line {background:red;}
p::first-letter {font-size:30px;}
伪类:存在DOM文档中,逻辑上存在但在文档树中却无须标识的“幽灵”分类。将特殊的效果添加到特定选择器上。它是已有元素上添加类别的,不会产生新的元素。
a:hover {color: #FF00FF}
p:first-child {color: red}
伪类是通过在元素选择器上加入伪类改变元素状态,而伪元素通过对元素的操作进行对元素的改变
是无损的、既支持索引色也支持直接色的点阵图。这种图片格式几乎没有对数据进行压缩,所以BMP格式的图片通常是较大的文件
是有损的、采用直接色的点阵图。JPEG的图片的优点是采用了直接色,得益于更丰富的色彩,JPEG非常适合用来存储照片,与GIF相比,JPEG不适合用来存储企业Logo、线框类的图。因为有损压缩会导致图片模糊,而直接色的选用,又会导致图片文件较GIF更大。
支持的颜色比较少,支持简单透明。支持动图
颜色单一的图片,动图
是无损的、使用索引色的点阵图。PNG是一种比较新的图片格式,PNG-8是非常好的GIF格式替代者,在可能的情况下,应该尽可能的使用PNG-8而不是GIF,因为在相同的图片效果下,PNG-8具有更小的文件体积。除此之外,PNG-8还支持透明度的调节,而GIF并不支持。除非需要动画的支持,否则没有理由使用GIF而不是PNG-8。
是无损的、使用直接色的点阵图。PNG-24的优点在于它压缩了图片的数据,使得同样效果的图片,PNG-24格式的文件大小要比BMP小得多。当然,PNG24的图片还是要比JPEG、GIF、PNG-8大得多。
是谷歌推出的专门用来表示网页中图片的一种格式
具备其他图片格式的所有优点,而且文件还特别的小
缺点:兼容性不好
将图片使用base64,这样可以将图片转换为字符,通过字符的形式来引入图片
一般都是一些需要和网页一起加载的图片才会使用base64
是无损的矢量图。SVG是矢量图意味着SVG图片由直线和曲线以及绘制它们的方法组成。当放大SVG图片时,看到的还是线和曲线,而不会出现像素点。SVG图片在放大时,不会失真,所以它适合用来绘制Logo、Icon等。
CSSSprites(精灵图),将一个页面涉及到的所有图片都包含到一张大图中去,然后利用CSS的 background-image,background-repeat,background-position属性的组合进行背景定位。
优点:
● 利用CSS Sprites能很好地减少网页的http请求,从而大大提高了页面的性能,这是CSS Sprites最大的优点;
● CSS Sprites能减少图片的字节,把3张图片合并成1张图片的字节总是小于这3张图片的字节总和。
缺点:
● 在图片合并时,要把多张图片有序的、合理的合并成一张图片,还要留好足够的空间,防止板块内出现不必要的背景。在宽屏及高分辨率下的自适应页面,如果背景不够宽,很容易出现背景断裂;
● CSSSprites在开发的时候相对来说有点麻烦,需要借助photoshop或其他工具来对每个背景单元测量其准确的位置。
● 维护方面:CSS Sprites在维护的时候比较麻烦,页面背景有少许改动时,就要改这张合并的图片,无需改的地方尽量不要动,这样避免改动更多的CSS,如果在原来的地方放不下,又只能(最好)往下加图片,这样图片的字节就增加了,还要改动CSS。
sass和less的区别以及如何使用
sass 和 less都是css预处理器,是CSS上的一种抽象层。他们是一种特殊的语法/语言编译成 CSS。 例如 Less 是一种动态样式语言,将 CSS 赋予了动态语言的特性,如变量,继承,运算, 函数,LESS 既可以在客户端上运行 (支持 IE 6+, Webkit, Firefox),也可以在服务端运行 (借助 Node.js)。
为什么要使用它们?
● 结构清晰,便于扩展。 可以方便地屏蔽浏览器私有语法差异。封装对浏览器语法差异的重复处理, 减少无意义的机械劳动。
● 可以轻松实现多重继承。 完全兼容 CSS 代码,可以方便地应用到老项目中。LESS 只是在 CSS 语法上做了扩展,所以老的 CSS 代码也可以与 LESS 代码一同编译。
预处理器,如:less,sass,stylus,用来预编译sass或者less,增加了css代码的复用性。层级,mixin, 变量,循环, 函数等对编写以及开发UI组件都极为方便。
后处理器, 如: postCss,通常是在完成的样式表中根据css规范处理css,让其更加有效。目前最常做的是给css属性添加浏览器私有前缀,实现跨浏览器兼容性的问题。
css预处理器为css增加一些编程特性,无需考虑浏览器的兼容问题,可以在CSS中使用变量,简单的逻辑程序,函数等在编程语言中的一些基本的性能,可以让css更加的简洁,增加适应性以及可读性,可维护性等。
其它css预处理器语言:Sass(Scss), Less, Stylus, Turbine, Swithch css, CSS Cacheer, DT Css。
使用原因:
● 结构清晰, 便于扩展
● 可以很方便的屏蔽浏览器私有语法的差异
● 可以轻松实现多重继承
● 完美的兼容了CSS代码,可以应用到老项目中
(1)line-height的概念:
● line-height 指一行文本的高度,包含了字间距,实际上是下一行基线到上一行基线距离;
● 如果一个标签没有定义 height 属性,那么其最终表现的高度由 line-height 决定;
● 一个容器没有设置高度,那么撑开容器高度的是 line-height,而不是容器内的文本内容;
● 把 line-height 值设置为 height 一样大小的值可以实现单行文字的垂直居中;
● line-height 和 height 都能撑开一个高度;
(2)line-height 的赋值方式:
● 带单位:px 是固定值,而 em 会参考父元素 font-size 值计算自身的行高
● 纯数字:会把比例传递给后代。例如,父级行高为 1.5,子元素字体为 18px,则子元素行高为 1.5 * 18 = 27px
● 百分比:将计算后的值传递给后代
使用@media查询,可以针对不同的媒体类型定义不同的样式,@media可以针对不同的屏幕尺寸设置不同的样式,当你重置浏览器大小的过程中,页面也会根据浏览器的宽度和高度重新渲染页面。
什么是媒体查询
● transition是过渡属性,强调过度,它的实现需要触发一个事件(比如鼠标移动上去,焦点,点击等)才执行动画。它类似于flash的补间动画,设置一个开始关键帧,一个结束关键帧。
● animation是动画属性,它的实现不需要触发事件,设定好时间之后可以自己执行,且可以循环一个动画。它也类似于flash的补间动画,但是它可以设置多个关键帧(用@keyframe定义)完成动画。
物理像素、逻辑像素都是什么?
px、em、rem
px: 固定的像素,无法因为适应屏幕大小而改变。
em 和 rem :是相对的长度单位,长度不是固定的,更适用于响应式布局。
em 和 rem 的区别:em 是相对父元素的单位, rem 是相对根元素的,rem 中的 r 是 root (根源),这样就更容易理解了。
em:
子元素中设置的字体大小是相对于父元素的。
元素的 width / height / padding / margin 用em的话,是相对于该元素的 font-size。
rem:
rem 全部的长度都是相对于根元素(html)的。通常给根元素(html) 设置一个font-size,然后其他元素的长度单位是 rem。
为什么移动端需要@2x或者@3x的图片
● 需要在border外侧添加空白,且空白处不需要背景(色)时,使用 margin;
● 需要在border内测添加空白,且空白处需要背景(色)时,使用 padding。
CSS优化、提高性能的方法
加载性能:
(1)css压缩:将写好的css进行打包压缩,可以减小文件体积。
(2)css单一样式:当需要下边距和左边距的时候,很多时候会选择使用 margin:top 0 bottom 0;但margin-bottom:bottom;margin-left:left;执行效率会更高。
(3)减少使用@import,建议使用link,因为后者在页面加载时一起加载,前者是等待页面加载完成之后再进行加载。
选择器性能:
(1)关键选择器(key selector)。选择器的最后面的部分为关键选择器(即用来匹配目标元素的部分)。CSS选择符是从右到左进行匹配的。当使用后代选择器的时候,浏览器会遍历所有子元素来确定是否是指定的元素等等;
(2)如果规则拥有ID选择器作为其关键选择器,则不要为规则增加标签。过滤掉无关的规则(这样样式系统就不会浪费时间去匹配它们了)。
(3)避免使用通配规则,如*{}计算次数惊人,只对需要用到的元素进行选择。
(4)尽量少的去对标签进行选择,而是用class。
(5)尽量少的去使用后代选择器,降低选择器的权重值。后代选择器的开销是最高的,尽量将选择器的深度降到最低,最高不要超过三层,更多的使用类来关联每一个标签元素。
(6)了解哪些属性是可以通过继承而来的,然后避免对这些属性重复指定规则。
渲染性能:
(1)慎重使用高性能属性:浮动、定位。
(2)尽量减少页面重排、重绘。
(3)去除空规则:{}。空规则的产生原因一般来说是为了预留样式。去除这些空规则无疑能减少css文档体积。
(4)属性值为0时,不加单位。
(5)属性值为浮动小数0.**,可以省略小数点之前的0。
(6)标准化各种浏览器前缀:带浏览器前缀的在前。标准属性在后。
(7)不使用@import前缀,它会影响css的加载速度。
(8)选择器优化嵌套,尽量避免层级过深。
(9)css雪碧图,同一页面相近部分的小图标,方便使用,减少页面的请求次数,但是同时图片本身会变大,使用时,优劣考虑清楚,再使用。
(10)正确使用display的属性,由于display的作用,某些样式组合会无效,徒增样式体积的同时也影响解析性能。
(11)不滥用web字体。对于中文网站来说WebFonts可能很陌生,国外却很流行。web fonts通常体积庞大,而且一些浏览器在下载web fonts时会阻塞页面渲染损伤性能。
可维护性、健壮性:
(1)将具有相同属性的样式抽离出来,整合并通过class在页面中进行使用,提高css的可维护性。
(2)样式与内容分离:将css代码定义到外部css中。
● 有空格时会有间隙,可以删除空格解决;
● margin正值时,可以让margin使用负值解决;
● 使用font-size时,可通过设置font-size:0、letter-spacing、word-spacing解决;
CSS 工程化是为了解决以下问题:
以下三个方向都是时下比较流行的、普适性非常好的 CSS 工程化实践:
● 预处理器:Less、 Sass 等;
● 重要的工程化插件: PostCss;
● Webpack loader 等 。
基于这三个方向,可以衍生出一些具有典型意义的子问题,这里我们逐个来看:
(1)预处理器:为什么要用预处理器?它的出现是为了解决什么问题?
预处理器,其实就是 CSS 世界的“轮子”。预处理器支持我们写一种类似 CSS、但实际并不是 CSS 的语言,然后把它编译成 CSS 代码:
那为什么写 CSS 代码写得好好的,偏偏要转去写“类 CSS”呢?这就和本来用 JS 也可以实现所有功能,但最后却写 React 的 jsx 或者 Vue 的模板语法一样——为了爽!要想知道有了预处理器有多爽,首先要知道的是传统 CSS 有多不爽。随着前端业务复杂度的提高,前端工程中对 CSS 提出了以下的诉求:
这三点是传统 CSS 所做不到的,也正是预处理器所解决掉的问题。预处理器普遍会具备这样的特性:
● 嵌套代码的能力,通过嵌套来反映不同 css 属性之间的层级关系 ;
● 支持定义 css 变量;
● 提供计算函数;
● 允许对代码片段进行 extend 和 mixin;
● 支持循环语句的使用;
● 支持将 CSS 文件模块化,实现复用。
(2)PostCss:PostCss 是如何工作的?我们在什么场景下会使用 PostCss?
PostCss 仍然是一个对 CSS 进行解析和处理的工具,它会对 CSS 做这样的事情:
它和预处理器的不同就在于,预处理器处理的是 类CSS,而 PostCss 处理的就是 CSS 本身。Babel 可以将高版本的 JS 代码转换为低版本的 JS 代码。PostCss 做的是类似的事情:它可以编译尚未被浏览器广泛支持的先进的 CSS 语法,还可以自动为一些需要额外兼容的语法增加前缀。更强的是,由于 PostCss 有着强大的插件机制,支持各种各样的扩展,极大地强化了 CSS 的能力。
PostCss 在业务中的使用场景非常多:
● 提高 CSS 代码的可读性:PostCss 其实可以做类似预处理器能做的工作;
● 当我们的 CSS 代码需要适配低版本浏览器时,PostCss 的 Autoprefixer 插件可以帮助我们自动增加浏览器前缀;
● 允许我们编写面向未来的 CSS:PostCss 能够帮助我们编译 CSS next 代码;
(3)Webpack 能处理 CSS 吗?如何实现?
Webpack 能处理 CSS 吗:
● Webpack 在裸奔的状态下,是不能处理 CSS 的,Webpack 本身是一个面向 JavaScript 且只能处理 JavaScript 代码的模块化打包工具;
● Webpack 在 loader 的辅助下,是可以处理 CSS 的。
如何用 Webpack 实现对 CSS 的处理:
● Webpack 中操作 CSS 需要使用的两个关键的 loader:css-loader 和 style-loader
● 注意,答出“用什么”有时候可能还不够,面试官会怀疑你是不是在背答案,所以你还需要了解每个 loader 都做了什么事情:
○ css-loader:导入 CSS 模块,对 CSS 代码进行编译处理;
○ style-loader:创建style标签,把 CSS 内容写入标签。
在实际使用中,css-loader 的执行顺序一定要安排在 style-loader 的前面。因为只有完成了编译过程,才可以对 css 代码进行插入;若提前插入了未编译的代码,那么 webpack 是无法理解这坨东西的,它会无情报错。
通过判断图片是否达到可视区域可以实现图片的懒加载。
● window.innerHeight 是浏览器可视区的高度;
● document.body.scrollTop || document.documentElement.scrollTop 是浏览器滚动的过的距离;
● imgs.offsetTop 是元素顶部距离文档顶部的高度(包括滚动条的距离);
● 内容达到显示区域的:img.offsetTop < window.innerHeight + document.body.scrollTop;
translate 是 transform 属性的⼀个值。改变transform或opacity不会触发浏览器重新布局(reflow)或重绘(repaint),只会触发复合(compositions)。⽽改变绝对定位会触发重新布局,进⽽触发重绘和复合。transform使浏览器为元素创建⼀个 GPU 图层,但改变绝对定位会使⽤到 CPU。 因此translate()更⾼效,可以缩短平滑动画的绘制时间。 ⽽translate改变位置时,元素依然会占据其原始空间,绝对定位就不会发⽣这种情况。
浏览器会把inline内联元素间的空白字符(空格、换行、Tab等)渲染成一个空格。为了美观,通常是一个放在一行,这导致
换行后产生换行字符,它变成一个空格,占用了一个字符的宽度。
解决办法:
(1)为设置float:left。不足:有些容器是不能设置浮动,如左右切换的焦点图等。
(2)将所有写在同一行。不足:代码不美观。
(3)将
内的字符尺寸直接设为0,即font-size:0。不足:
中的其他字符尺寸也被设为0,需要额外重新设定其他字符尺寸,且在Safari浏览器依然会出现空白间隔。
(4)消除
的字符间隔letter-spacing:-8px,不足:这也设置了内的字符间隔,因此需要将
内的字符间隔设为默认letter-spacing:normal。
通过修改某个属性值呈现的内容就可以被替换的元素就称为“替换元素”。
替换元素除了内容可替换这一特性以外,还有以下特性:
● 内容的外观不受页面上的CSS的影响:用专业的话讲就是在样式表现在CSS作用域之外。如何更改替换元素本身的外观需要类似appearance属性,或者浏览器自身暴露的一些样式接口。
● 有自己的尺寸:在Web中,很多替换元素在没有明确尺寸设定的情况下,其默认的尺寸(不包括边框)是300像素×150像素,如
● 在很多CSS属性上有自己的一套表现规则:比较具有代表性的就是vertical-align属性,对于替换元素和非替换元素,vertical-align属性值的解释是不一样的。比方说vertical-align的默认值的baseline,很简单的属性值,基线之意,被定义为字符x的下边缘,而替换元素的基线却被硬生生定义成了元素的下边缘。
● 所有的替换元素都是内联水平元素:也就是替换元素和替换元素、替换元素和文字都是可以在一行显示的。但是,替换元素默认的display值却是不一样的,有的是inline,有的是inline-block。
替换元素的尺寸从内而外分为三类:
● 固有尺寸: 指的是替换内容原本的尺寸。例如,图片、视频作为一个独立文件存在的时候,都是有着自己的宽度和高度的。
● HTML尺寸: 只能通过HTML原生属性改变,这些HTML原生属性包括的width和height属性、的size属性。
● CSS尺寸: 特指可以通过CSS的width和height或者max-width/min-width和max-height/min-height设置的尺寸,对应盒尺寸中的content box。
这三层结构的计算规则具体如下:
(1)如果没有CSS尺寸和HTML尺寸,则使用固有尺寸作为最终的宽高。
(2)如果没有CSS尺寸,则使用HTML尺寸作为最终的宽高。
(3)如果有CSS尺寸,则最终尺寸由CSS属性决定。
(4)如果“固有尺寸”含有固有的宽高比例,同时仅设置了宽度或仅设置了高度,则元素依然按照固有的宽高比例显示。
(5)如果上面的条件都不符合,则最终宽度表现为300像素,高度为150像素。
(6)内联替换元素和块级替换元素使用上面同一套尺寸计算规则。
JS:使用定时器setTimeout
CSS3:transition && animation
HTML5: canvas && requestAnimationFrame
requestAnimationFrame 拿出来详细讲一下:
window.requestAnimationFrame()
告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行。
语法: window.requestAnimationFrame(callback); 其中,callback是下一次重绘之前更新动画帧所调用的函数(即上面所说的回调函数)。该回调函数会被传入DOMHighResTimeStamp参数,它表示requestAnimationFrame() 开始去执行回调函数的时刻。该方法属于宏任务,所以会在执行完微任务之后再去执行。
取消动画:使用cancelAnimationFrame()来取消执行动画,该方法接收一个参数——requestAnimationFrame默认返回的id,只需要传入这个id就可以取消动画了。
优势:
● CPU节能:使用SetTinterval 实现的动画,当页面被隐藏或最小化时,SetTinterval 仍然在后台执行动画任务,由于此时页面处于不可见或不可用状态,刷新动画是没有意义的,完全是浪费CPU资源。而RequestAnimationFrame则完全不同,当页面处理未激活的状态下,该页面的屏幕刷新任务也会被系统暂停,因此跟着系统走的RequestAnimationFrame也会停止渲染,当页面被激活时,动画就从上次停留的地方继续执行,有效节省了CPU开销。
● 函数节流:在高频率事件( resize, scroll 等)中,为了防止在一个刷新间隔内发生多次函数执行,RequestAnimationFrame可保证每个刷新间隔内,函数只被执行一次,这样既能保证流畅性,也能更好的节省函数执行的开销,一个刷新间隔内函数执行多次时没有意义的,因为多数显示器每16.7ms刷新一次,多次绘制并不会在屏幕上体现出来。
● 减少DOM操作:requestAnimationFrame 会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率,一般来说,这个频率为每秒60帧。
setTimeout执行动画的缺点:它通过设定间隔时间来不断改变图像位置,达到动画效果。但是容易出现卡顿、抖动的现象;原因是:
● settimeout任务被放入异步队列,只有当主线程任务执行完后才会执行队列中的任务,因此实际执行时间总是比设定时间要晚;
● settimeout的固定时间间隔不一定与屏幕刷新间隔时间相同,会引起丢帧。