css 面试题总结(后续会补充)

120 阅读32分钟

参考了很多资料整合的,主要是如果单纯过一遍不整合一下,印象不太深刻,而且不同资料所包含的考点不同,将多个资料整合处理在一起,方便日后复习查看。后续如果面试到其他的题目或者查看到新的面试题资料也会相应补充的。

一、css相关考题

css 有哪些基本选择器?它们的权重是如何表示的?

css 基本选择器有类选择器、属性选择器和 ID 选择器。

权重

css 选择器的权重预示着 css 选择器样式渲染的先后顺序,元素样式渲染时,权重 高的选择器样式会覆盖权重低的选择器样式。 通常将权重分为 4 个等级,可用 0.0.0.0 来表示这 4 个等级。 !important 关键字优先级最高。

方式例子优先级
内联样式(非元素器)<p style="color:red">标题</p>1.0.0.0
ID 选择器#title{}0.1.0.0
类属性选择器
属性选择器
伪类
.title{}
input[value] {color: red;}
li:first-child{color: red;} , a:hover{ color:red }
0.0.1.0
元素选择器
伪元素选择器
p{color: red;}
div::before {content: "标题";font-size: 30px;}
0.0.0.1
通配符选择器*{margin:0;padding:0;}没有任何贡献值

css 优先级如何排序?

!important>style(内联)>id(权重 100)>class(权重 10)>标签(权重1)。 同类别的样式中,后面的会覆盖前面的 。

css 选择器 (符)有哪些?

名称例子
id 选择器#myid
类选择器.myClassName
标签选择器div,p,h1
相邻选择器h1+p
子选择器ul>li
后代选择器li a
通配符选择器*
属性选择器button[disabled="true"]
伪类选择器a:hover、 li:nth-child 表示一种状态
伪元素选择器li::before,li::after,li::first-child 表示文档某个部分的表现

在 CSS3 规范申 , 为了区分伪元素和伪类, CSS3 建议伪类用单冒号: , 伪元素用双冒号 :: 当把选择器组合使用的时候,相应的层级权重也会递增, 例如#id.class 的权重为 0.1.1.0。

浮动元素引起的问题和解决方法是什么?

引起的问题

  1. 父元素的高度无法被撑开,影响与父元素同级的元素。
  2. 与元素同级的非浮动元素会紧随其后(类似遮盖现象)。
  3. 如果一个元素浮动,贝1]该元素之前的元素也需要浮动;否则,会影响页面显示 的结构(即通常所说的串行现象)

解决方法

  1. 为父元素设置固定高度。
  2. 为父元素设置 overfiow:hidden 即可清除浮动,让父元素的高度被撑开。
  3. 外墙法是指在父元素外面,添加“一道墙”,设置属性 clear:both。
<body>
    <div>
        <div style="float: left;background: red;">浮动元素</div>
    </div>
    <!-- 外墙法 添加下面的代码 清除浮动 -->
    <div style="clear: both;"></div>
    <div>与浮动元素父级同级别的元素</div>
</body>
  1. 内墙法是才旨在父元素内部,浮动元素的最后面,添加“一道墙”,也就是在浮动元素的父元素结束标签之前添加一个空的块级元素,然后为块级元素添加clear:both CSS属性。
<body>
    <div>
        <div style="float: left;background: red;">浮动元素</div>
        <!-- 添加下面的代码 清除浮动 -->
        <div style="clear: both;"></div>
    </div>
    <div>与浮动元素父级同级别的元素</div>
</body>
  1. 伪元素是指为了少创建元素,对父元素添加 after 伪元素,可以使用通用类 clearfix(父元素添加该样式), clearfix 的实现如下
.clearfix:after{
    content:'';
    display: block;
    clear:both;
}

position 的值分别是相对于哪个位置定位的?

  • relative 表示相对定位,相对于自己本身所在正常文档流中的位直进行定位。
  • absolute 表示绝对定位,相对于最近一级(从直接父级元素往上数,直到根元素) 定位,相对于 static 的 父元素进行定位。
  • fixed 用于生成绝对定位,相对于浏览器窗口或 frame 进行定位。
  • static 是默认值,没有定位,元素出现在正常的文档流中 。
  • sticky 是生成和性定位的元素,容器的位置根据正常文档流计算得出 。

position:absolute 和 float 属性的异同

  • 共同点: 是对内联元素设置 float 和 absolute 属性,可以让元素脱离文档流,并且 可以设置其宽高 。
  • 不同点: 是 float 仍可占据位直 ,不会覆盖在另一个 BFC 区域上, 浮动的框可以向左 或向右移动,直到它的外边缘碰到包含框或另 一个浮动柜的边柜为止。 absolute 会覆盖 文档流中的其他元素 , 即遮盖现象。

如何避免文档流中的空白符合并现象?

空白符合并是标准文档流的特征之一,可以通过设置white-space修改这一特征,属性值如下。

  • pre表示不会合并空白符,渲染换行符,不会自动换行,相当于pre元素。
  • pre-wrap表示不会合并空白符,渲染换行符,自动换行。
  • pre-line表示合并空白符,渲染换行符,自动换行。
  • nowrap表示合并空白符,不会渲染换行符,不会自动换行。
  • normal表示默认值,按照文档流特点渲染,合并空白符,不会渲染换行符,自动换行。

如何使英文单词发生词内断行?【实现文本换行】

使用 word-wrap 属性。

  • normal,只在九许的断字点换行(浏览器保持默认处理)。
  • break-word,在长单词或 URL 地址内部进行换行。

word-wrap: break-word;

display 有哪些值?说明它们的作用

display 的值有 block、 none、 inline、 inline-block、 list-item、 table 和 inherit。 其作用如下 。

  • block 是指块类型 。默认宽度为父元素宽度, 可设置宽高, 换行显示。 (可以设置width,height,margin和padding)
  • none 是指元素不会显示,已脱离文档流。
  • inline 是指行内元素类型 。默认宽度为内容宽度, 不可设置宽高,同行显示。(不能设置垂直方向的margin和padding)
  • inline-block 是指默认宽度为内容宽度,可以设置宽高, 同行显示。
  • list-item 是指像块类型元素一样显示 ,并添加样式列表标记。
  • table 是指此元素合作为块级表格显示。
  • inherit 是指从父元素继承 display 属性的值。

简要描述块级元素和行内元素的区别。

块级元素的前后都会自动换行。默认情况下,块级元素会独占一行。例如 <p><hl-6><div>都是块级元素。当显示这些元素中间的文本时,都将从新行中开始显示,其后的内容也将在新行中显示。 行内元素可以和其他行内元素位于同一行,在浏览器中显示时不会换行。例如 <a><span>等。对于行内元素,不能设置其高度和宽度。 还有一种元素是行内块级元素,比如<img><input>元素等。 这些元素可以和其他行 内元素位于同 一行,同时可以设置其高度和宽度。

CSS盒模型

CSS 中的盒子模型包括 IE 盒子模型和标 准的 W3C 盒子模型。

  1. 标准盒子模型 image.png
  2. IE盒子模型 image.png

标准盒子模型和IE盒子模型主要区别wdiht

--width包含
标准盒子模型左右border+左右padding+width
IE盒子模型width

在 CSS3中引入了 box-sizing 属性: box-sizing:content-box 表示标准的盒子模型, box-sizing:border-box 表示的是 IE 盒子模型

box-sizing设置的盒模型了解

布局所占宽布局所占高
content-box盒模型Width = width + padding(左右) + border(左右)Height = height + padding(上下) + border(上下)
padding-box盒模型Width = width (包含 padding左右 + border左右)Height= height (包含 padding上下 + border上下
border-box盒模型Width= width(包含 padding左右 + border左右)Height = height(包含 padding上下 + border上下)

BFC,IFC,FFC,GFC的规范理解

类型详细
BFC (Block Formatting Context)指块级格式化上下文即一个创建了新的 BFC 的盒子是独立布局的 ,盒子里面的子元素的样式不会影响到外面的元素。 在同一个 BFC 中,两个毗邻的块级盒在垂直方向(和布局方向有关系 )的 margin 会发生折叠。 BFC 决定元素如何对其内容进行布局,也决定与其他元素的关系和相王作用
IFC (Inline Formatting Context )指内联格式化上下文IFC的线柜(linebox)高度由其包含行内元素中最高的实际高度计算而来(不受竖直方向的padding/margin的影响)。IFC中的线框一般左右都贴紧整个IFC,但是会被float元素扰乱。同一个IFC下的多个线柜高度不同。IFC中是不可能有块级元素的,当插入块级元素时(如在p中插入div),会产生两个匿名块,两者与div分隔开,即产生两个IFC,每个IFC对外表现为块级元素,与div垂直排列 。
FFC (Flex Formatting Context)指自适应格式化上下文即display值为flex或inline-flex的元素将会生成自适应容器。伸缩容器中的每一个子元素都是一个伸缩单元。伸缩单元可以是任意数量的。伸缩羊元内和伸缩容器外的一切元素都不受影响。简单地说,Flexbox定义了伸缩容器内伸缩单元的布局 。
GFC (GridLayout Formatting Context)指网格布局格式化上下文即当把一个元素的display值设为grid的时候,此元素将会获得一个独立的渲染区域。可以通过在网格容器(grid container)上定义网格定义行(grid definition row)和网格定义列(grid definition column),在网格项目(grid item)上定义网格行(grid row)和网格列(grid column)来为每一个网格项目定义位置和空间。

对 BFC 的理解,如何创建 BFC

相关概念

先来看两个相关的概念:

  • Box: Box 是 CSS 布局的对象和基本单位,⼀个⻚⾯是由很多个 Box组成的,这个 Box 就是我们所说的盒模型。
  • Formatting context:块级上下⽂格式化,它是⻚⾯中的⼀块渲染区 域,并且有⼀套渲染规则,它决定了其⼦元素将如何定位,以及和其 他元素的关系和相互作⽤。

块格式化上下文(Block Formatting Context,BFC) 是 Web 页面的可视化 CSS 渲染的一部分,是布局过程中生成块级盒子的区域,也是浮动元素与其他元素的交互限定区域。 通俗来讲: BFC 是一个独立的布局环境,可以理解为一个容器,在这个容器中按照一定规则进行物品摆放,并且不会影响其它环境中的物品。如果一个元素符合触发 BFC 的条件,则 BFC 中的元素布局不受外部影响。

创建 BFC 的条件

  • 根元素:body;
  • 元素设置浮动:float 除 none 以外的值;
  • 元素设置绝对定位:position (absolute、fixed);
  • display 值为:inline-block、table-cell、table-caption、flex 等;
  • overflow 值为:hidden、auto、scroll;(即不为visible的元素)

BFC 的特点:

  • 垂直方向上,自上而下排列,和文档流的排列方式一致。
  • 在 BFC 中上下相邻的两个容器的 margin 会重叠
  • 计算 BFC 的高度时,需要计算浮动元素的高度
  • BFC 区域不会与浮动的容器发生重叠
  • BFC 是独立的容器,容器内部元素不会影响外部元素
  • 每个元素的左 margin 值和容器的左 border 相接触

BFC 的作用

  1. 解决 margin 的重叠问题:由于 BFC 是一个独立的区域,内部的元素和外部的元素互不影响,将两个元素变为两个 BFC,就解决了 margin重叠的问题。
  2. 解决高度塌陷的问题:在对子元素设置浮动后,父元素会发生高度塌陷,也就是父元素的高度变为 0。解决这个问题,只需要把父元素变成一个 BFC。常用的办法是给父元素设置 overflow:hidden。

例子

创建自适应两栏布局:可以用来创建自适应两栏布局:左边的宽度固定,右边的宽度自适应。

左侧设置 float:left,右侧设置 overflow: hidden。这样右边就触发了 BFC,BFC 的区域不会与浮动元素发生重叠,所以两侧就不会发生重叠,实现了自适应两栏布局。

image.png

<style>
    .left{
        width: 100px;
        height: 200px;
        background-color: red;
        float: left;
    }
    .right{
        height: 300px;
        background-color: yellow;
        overflow: hidden;
    }
</style>
<body>
    <div class="left"></div>
    <div class="right"></div>
</body>

image.png

Flex布局

详细可往这里看: Flex 布局教程:语法篇Flex 布局教程:实例篇 Flex 是 FlexibleBox 的缩写,意为"弹性布局",用来为盒状模型提供最大的灵活性。布局的传统解决方案,基于盒状模型,依赖display属性+position属性+float属性。它对于那些特殊布局非常不方便,比如,垂直居中就不容易实现。

简单的分为容器属性和元素属性

容器的属性:

  1. flex-direction:决定主轴的方向(即子 item 的排列方法)
.box { 
    flex-direction: row | row-reverse | column | column-reverse; 
} 
  1. flex-wrap:决定换行规则
.box{ 
    flex-wrap: nowrap | wrap | wrap-reverse; 
} 
  1. flex-flow:flex-flow属性是flex-direction属性和flex-wrap属性的简写形式
.box { 
    flex-flow: <flex-direction> || <flex-wrap>; 
} 
  1. justify-content:对其方式,水平主轴对齐方式
  2. align-items:对齐方式,竖直轴线方向

项目的属性(元素的属性):

  • order 属性:定义项目的排列顺序,顺序越小,排列越靠前,默认为 0
  • flex-grow 属性:定义项目的放大比例,即使存在空间,也不会放大
  • flex-shrink 属性:定义了项目的缩小比例,当空间不足的情况下会等比例的缩小,如果 定义个 item 的 flow-shrink 为 0,则为不缩小
  • flex-basis 属性:定义了在分配多余的空间,项目占据的空间。
  • flex:是 flex-grow 和 flex-shrink、flex-basis 的简写,默认值为 0 1 auto。
  • align-self:允许单个项目与其他项目不一样的对齐方式,可以覆盖 align-items,默认属性为 auto,表示继承父元素的 align-items 比如说,用 flex 实现圣杯布局

display:table 和本身的 table 有什么区别?

Display:table 和本身 table 是相对应的,区别在于,display:table 的 css 声明能够让一个 html 元素和它的子节点像 table 元素一样,使用基于表格的 css 布局,是我们能够轻松定 义一个单元格的边界,背景等样式,而不会产生因为使用了 table 那样的制表标签导致的语义化问题。

之所以现在逐渐淘汰了 table 系表格元素,是因为用 div+css 编写出来的文件比用 table 边写出来的文件小,而且 table 必须在页面完全加载后才显示,div 则是逐行显示,table 的嵌套性太多,没有 div 简洁

双边距重叠问题(外边距折叠)

多个相邻(兄弟或者父子关系)普通流的块元素垂直方向 marigin 会重叠 折叠的结果为:

  • 两个相邻的外边距都是正数时,折叠结果是它们两者之间较大的值。
  • 两个相邻的外边距都是负数时,折叠结果是两者绝对值的较大值。
  • 两个外边距一正一负时,折叠结果是两者的相加的和。

常见的 CSS 布局单位

常用的布局单位包括像素(px),百分比(%),em,rem,vw/vh。

单位详情
像素(px)一个像素表示终端(电脑、手机、平板等)屏幕所能显示的最小的区域,像素分为两种类型:CSS像素和物理像素

CSS 像素:为 web 开发者提供,在 CSS 中使用的一个抽象单位;
物理像素:只与设备的硬件密度有关,任何设备的物理像素都是固定的。
百分比(%)当浏览器的宽度或者高度发生变化时,通过百分比单位可以使得浏览器中的组件的宽和高随着浏览器的变化而变化,从而实现响应式的效果。一般认为子元素的百分比相对于直接父元素
em(em 相对于父元素)文本相对长度单位。相对于当前对象内文本的字体尺寸。如果当前行内文本的字体尺寸未被人为设置,则相对于浏览器的默认字体尺寸(默认 16px)。(相对父元素的字体大小倍数)
rem (rem 相对于根元素)rem 是 CSS3 新增的一个相对单位,相对于根元素(html 元素)的 font-size 的倍数。
作用:利用 rem 可以实现简单的响应式布局,可以利用 html 元素中字体的大小与屏幕间的比值来设置 font-size的值,以此实现当屏幕分辨率变化时让元素也随之变化。
vw相对于视窗的宽度,视窗宽度是 100vw
vh相对于视窗的高度,视窗高度是 100vh

vw/vh 和百分比很类似,两者的区别:

单位区别
百分比(%)大部分相对于祖先元素,也有相对于自身的情况比如(border-radius、translate 等)
vw/vm相对于视窗的尺寸

px 和 em,rem 的区别是什么?

单位详细
pxpx 的值是固定的,指定为多少就是多少,计算比较容易
emem 的值不是固定的,是相对于容器字体的大小,并且 em 会继承父级元素的字体大小
remrem 是指相对于根元素(通常是HTML元素)字体的大小

如何解决 1px 问题?

1px 问题指的是:在一些 Retina 屏幕(主要是苹果)的机型上,移动端页面的1px会变得很粗,呈现出不止 1px 的效果。原因很简单——CSS中的1px并不能和移动设备上的1px划号。它们之间的比例关系有一个专门的属性来描述:

    window.devicePixelRatio = 设备的物理像素 / CSS像素 

打开 Chrome 浏览器,启动移动端调试模式,在控制台去输出这个devicePixelRatio 的值。这里选中 iPhone6/7/8 这系列的机型,输出的结果就是 2:

image.png 这就意味着设置的 1px CSS 像素,在这个设备上实际会用 2 个物理像素单元来进行渲染,所以实际看到的一定会比 1px 粗一些。

解决 1px 问题的三种思路:

1. 直接写 0.5px

如果之前 1px 的样式这样写:

border: 1px solid #000

可以先在 JS 中拿到 window.devicePixelRatio 的值,然后把这个值通过 JSX 或者模板语法给到 CSS 的 data 里,达到这样的效果(这里用 JSX 语法做示范):

    <div id="container" data-device="{{window.devicePixelRatio}}"></div>

然后就可以在 CSS 中用属性选择器来命中 devicePixelRatio 为某一值的情况,比如说这里尝试命中 devicePixelRatio 为 2 的情况:

    #container[data-device="2"]{
        border: 0.5px solid #000
    }

直接把 1px 改成 1/devicePixelRatio 后的值,这是目前为止最简单的一种方法。这种方法的缺陷在于兼容性不行,IOS 系统需要 8 及以上的版本,安卓系统则直接不兼容。

2. 伪元素先放大后缩小

这个方法的可行性会更高,兼容性也更好。唯一的缺点是代码会变多。 思路是先放大、后缩小:在目标元素的后面追加一个 ::after 伪元素,让这个元素布局为 absolute 之后、整个伸展开铺在目标元素上,然后把它的宽和高都设置为目标元素的两倍,border 值设为 1px。接着借助 CSS 动画特效中的放缩能力,把整个伪元素缩小为原来的50%。此时,伪元素的宽高刚好可以和原有的目标元素对齐,而 border也缩小为了 1px 的二分之一,间接地实现了 0.5px 的效果。

    #container[data-device="2"]{
       position: relative;
    }
    #container[data-device="2"]::after{
        position: absolute;
        top: 0;
        left: 0;
        width: 200%;
        height: 200%;
        content: "";
        transform: scale(0.5);
        transform-origin: left top;
        box-sizing: border-box;
        border: 1px solid #000;
    }

如果设置<p>的font-size为10rem,那么当用户重置或拖曳浏览器窗口时,它的文本会不会受到影响?为什么????

不会。下面的解释来源该博客

我们知道PC端缩放页面(浏览器的网页缩放功能)其实是改变了dpr(这是可以看得到的,175%时dpr就为1.75)和设备独立像素(放大页面时window.innerWidth值减小),并且是会触发resize事件的。

至于为什么网页缩放不会影响rem元素的物理尺寸(物理尺寸不变,但是现实的设备独立像素即px值是变化的),这其实和在移动端视口缩放不会影响rem元素的原理相同,这里不再深入解释了,在讨论移动端视口缩放时已经详细的证明过这个问题了。

元素的rem是写死的,放大页面时,设备独立像素的数量减少,而屏幕显示区域的面积是不变的,则一个 点/设备独立像素 所包含的物理像素的数量增多,由Y=P/Z得知基准值也随着设备独立像素数量的减少而减少,那么元素的点数量也随之减少,元素的点数量的减少和一个点所包含的物理像素数量的增多刚好抵消,那么最终用于显示该元素的物理像素数量将保持不变,所以rem元素的物理尺寸不受页面缩放的影响。

所以为了防止用户使用浏览器的缩放功能放大页面时会改变原始的布局(不是布局被打破了,布局还是好的,没乱,只是放大了),布局类元素应尽量使用rem单位。

为什么要初始化 CSS?

因为浏览器的兼容问题,不同浏览器对有些标签的默认值是不同的 ,如果没有 初始化 css,往往会导致页面在不同浏览器之间出现差异。 当然,初始化样式有时会对 SEO 产生一定的影响 , 但鱼和熊掌不可兼得,所以在力 求影响最小的情况下初始化 css。 最简单的初始化方法就是:

*{
    padding: 0; 
    margin: 0;
}

display:none 和 visibility:hidden, opacity=0 的区别是什么?

  • display:none 隐藏对应的元素,在文档流中不再给它分配空间,它各边的元素会合拢,即脱离文档流。
  • visibility:hidden 隐藏对应的元素,但是在文档流中仍保留原来的空间。
  • opacity=0该元素隐藏起来了,但不会改变页面布局,并且,如果该元素已经绑定一些 事件,如 click 事件,那么点击该区域,也能触发点击事件的

rgba() 和 opacity 的透明效果有什么不同?

rgba()和opacity都能实现透明效果,但它们最大的不同是:

  • opacity作用于元素,并且可以设置元素内所有内容的透明度;
  • rgba()只作用于元素的颜色或其背景色(设置rgba透明的元素的子元素不会继承透明效果)。

对行内元素设置margin-top和margin-bottom是否起作用?

不起作用(需要注意行内元素的替换元素img、input,它们是行内元素,但是可以设置它们的宽度和高度,并且margin属性也对它们起作用,margin-top和margin-botton有着类似于inline-block的行为)。

如何让超出宽度的文字显示为省略号?

p{
    width:200px;
    overflow:hidden;
    white-space: nowrap;
    text-overflow:ellipsis;
}

如何居中一个已知宽高的浮动元素?

<style>
    .float-content{
        float: left;
        width: 400px;
        height: 200px;
        position: relative;
        margin-left: -200px;
        left: 50%;
        top: 50%;
        background-color: pink;
    }
</style>
<body>
    <div class="float-content"></div>
</body>

如何用实现3栏布局(左右固定 200p×,中间自适应)?

<style>
    .container div{
        height: 200px;
    }
    .main,.left,.right{
        position: relative;
        float: left;
    }
    .left,.right{
        width: 200px;
    }
    .main{
        width: calc(100% - 400px);
        background-color: yellow;
    }
    .left{
        background-color: pink;
    }
    .right{
        background-color: aquamarine;
    }
</style>
<body>
    <div class="container">
        <div class="left">左边</div>
        <div class="main">
            <h2>中间自适应</h2>
        </div>
 
        <div class="right">右边</div>
    </div>
</body>

已知高度的容器如何在页面中水平垂直居中?

<style>
    #box{
        width: 200px;
        height: 200px;
        background-color: red;
        position: absolute;
        left: 50%;
        top: 50%;
        margin-left: -100px;
        margin-top: -100px;
    }
</style>
<body>
    <div id="box">内容</div>
</body>

解释一下 CSS Sprite ,以及如何在页面或网站中使用它。

CSS Sprite其实就是把网页中一些背景图片整合到一张图片文件中,再利用css的"background-image","background-repeat","background-position"的组合进行背景定位,background-position可以用数字精确地走位出背景图片的位直。

  • 优点:
  1. 利用 CSS Sprites 能很好地减少网页的 http 请求,从而大大提高了页面的性能,这是 CSS Sprites 最大的优点;
  2. CSS Sprites 能减少图片的字节,把 3 张图片合并成 1 张图片的字节总是小于这 3 张图片的字节总和。
  • 缺点:
  1. 在图片合并时,要把多张图片有序的、合理的合并成一张图片,还要留好足够的空间,防止板块内出现不必要的背景。
  2. 在宽屏及高分辨率下的自适应页面,如果背景不够宽,很容易出现背景断裂;

说出几种解决 IE6 Bug 的方法。

问题解决方法
双边距问题,是使用float引起的使用display:inline
3像素问题,是使用float引起的使用_margin-right:-3px
超链接hover伪类样式,单击后失效使用以下正确的书写顺序:L→V→H→A(link,visited,hover,active)
z-index问题给父级添加position:relative
PNG图片半透明问题使用JavaScript代码库,或使用IE滤镜

CSS 预处理器?

为什么要用预处理器?它的出现是为了解决什么问题?

预处理器,其实就是 CSS 世界的“轮子”。预处理器支持我们写一种类似 CSS、但实际并不是 CSS 的语言,然后把它编译成 CSS 代码:

image.png

那为什么写 CSS 代码写得好好的,偏偏要转去写“类CSS”呢?这就和本来用 JS 也可以实现所有功能,但最后却写 React 的 jsx 或者 Vue 的模板语法一样——为了爽!要想知道有了预处理器有多爽,首先要知道的是传统 CSS 有多不爽。随着前端业务复杂度的提高,前端工程中对 CSS 提出了以下的诉求:

  1. 宏观设计上:我们希望能优化 CSS 文件的目录结构,对现有的 CSS文件实现复用;
  2. 编码优化上:我们希望能写出结构清晰、简明易懂的 CSS,需要它具有一目了然的嵌套层级关系,而不是无差别的一铺到底写法;我们希望它具有变量特征、计算能力、循环能力等等更强的可编程性,这样我们可以少写一些无用的代码;
  3. 可维护性上:更强的可编程性意味着更优质的代码结构,实现复用意味着更简单的目录结构和更强的拓展能力,这两点如果能做到,自然会带来更强的可维护性。 这三点是传统 CSS 所做不到的,也正是预处理器所解决掉的问题。

预处理器普遍会具备这样的特性:

  1. 嵌套代码的能力,通过嵌套来反映不同 css 属性之间的层级关系;
  2. 支持定义css变量;
  3. 提供计算函数;
  4. 允许对代码片段进行extend和mixin;
  5. 支持循环语句的使用;
  6. 支持将 CSS 文件模块化,实现复用。

以less为例

  1. 变量
@colorRed:red;
p{
    color: @colorRed;
}
  1. 混合(Mixins) classB 继承 classA的样式
.border-content(@radius: 5px){
    border: 1px solid red;
    border-radius: @radius;
    box-shadow: 2px 2px 2px 2px rgba(0, 0, 0, .3);
}
#one{
    width: 200px;
    height: 100px;
    .border-content;
}
#two{
    width: 200px;
    height: 100px;
    .border-content(50px);
}
  1. 嵌套(Nesting) 以嵌套的方式编写层叠样式
div{
    p{
        span{
            color:red;
        }
    }
}
  1. 运算(Operations) 任何数字、颜色或者变量都可以参与运算
    @baseColor:red; //#ff0000
    @baseWidth:100px;
    @baseHeight:100px;
    div{
        width: @baseWidth / 2; // 50px
        height: @baseHeight / 5; // 20px 
        background-color: @baseColor / 2; // #800000
    }
  1. 作用域(Scope) less 中的范围非常类似于CSS。变量和混合变量首先在本域查找,如果找不到它们,则从“父”范围继承它们
	/*例题1*/
	@var: red;
	#page {
	  @var: white;
	  #header {
	    color: @var; /*white*/ 
	  }
	}
  1. 导入(Importing)
	@import "lib.less";
	@import "lib";
	@import "lib.css";

如何实现元素的垂直居中

  1. 父元素 display:flex,align-items:center;
  2. 元素绝对定位,top:50%,margin-top:-(高度/2)
  3. 高度不确定用 transform:translateY(-50%)
  4. 父元素 table 布局,子元素设置 vertical-align:center;

处置居中方法

1.margin:auto 法

定位为上下左右为 0,margin:0 可以实现脱离文档流的居中

<style>
    div {
        width: 400px;
        height: 400px;
        position: relative;
        border: 1px solid #465468;
    }

    img {
        position: absolute;
        margin: auto;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
    }
</style>
<body>
    <div>
        <img src="mm.jpg"> 
    </div>
</body>

2.margin 负值法

    .container {
        width: 500px;
        height: 400px;
        border: 2px solid #379;
        position: relative;
    }

    .inner {
        width: 480px;
        height: 380px;
        background-color: #746;
        position: absolute;
        top: 50%;
        left: 50%;
        margin-top: -190px;
        /*height 的一半*/
        margin-left: -240px;
        /*width 的一半*/
    }

补充:其实这里也可以将 marin-top 和 margin-left 负值替换成, transform:translateX(-50%)和 transform:translateY(-50%)

3.table-cell(未脱离文档流的)

设置父元素的 display:table-cell,并且 vertical-align:middle,这样子元素可以实现垂直居中。

    div {
        width: 300px;
        height: 300px;
        border: 3px solid #555;
        display: table-cell;
        vertical-align: middle;
        text-align: center;
    }

    img {
        vertical-align: middle;
    }

4.利用 flex

将父元素设置为 display:flex,并且设置 align-items:center;justify-content:center;

    .container {
        width: 300px;
        height: 200px;
        border: 3px solid #546461;
        display: -webkit-flex;
        display: flex;
        -webkit-align-items: center;
        align-items: center;
        -webkit-justify-content: center;
        justify-content: center;
    }

    .inner {
        border: 3px solid #458761;
        padding: 20px;
    }

了解重绘和重排吗,知道怎么去减少重绘和重排吗,让文档脱离文档流有哪些方法?

DOM 的变化影响到了预算内宿的几何属性比如宽高,浏览器重新计算元素的几何属性, 其他元素的几何属性也会受到影响,浏览器需要重新构造渲染书,这个过程称之为重排, 浏览器将受到影响的部分重新绘制在屏幕上 的过程称为重绘,

引起重排重绘的原因有:

  • 添加或者删除可见的 DOM 元素,
  • 元素尺寸位置的改变
  • 浏览器页面初始化,
  • 浏览器窗口大小发生改变,重排一定导致重绘,重绘不一定导致重排,

减少重绘重排的方法有:

  • 不在布局信息改变时做 DOM查询,
  • 使用 csstext,className 一次性改变属性
  • 使用 fragment
  • 对于多次重排的元素,比如说动画。使用绝对定位脱离文档流,使其不影响其他元素

二、css3相关考题

CSS3中有哪些新特性?

1. 圆角 (border-radius);

image.png

<style>
.circle{
    width: 100px;
    height: 100px;
    border-radius: 50%;
    background-color: pink;
}
</style>
<body>
    <div class="circle"></div>
</body>

2. 阴影 (box-shadow);

image.png

<style>
.circle{
    width: 100px;
    height: 100px;
    border-radius: 50%;
    box-shadow: 2px 2px 2px 2px rgba(0, 0, 0, .3);
}
</style>
<body>
    <div class="circle"></div>
</body>

3. 对文字加特效 (text-shadow);

image.png

<style>
.p-text{
    /* 水平阴影位置,垂直阴影位置,模糊距离,阴影颜色 */
    text-shadow: 2px 4px 3px rgba(0,0,0,0.5);
}
</style>
<body>
    <p class="p-text">CSS3新特性</p>
</body>

4. 线性渐变 (linear-gradient);

image.png

<style>
.box{
    width: 200px;
    height: 200px;
    background-image: linear-gradient(to top,orange,green);
}
</style>
<body>
    <div class="box"></div>
</body>

5. 变换 (transform),如下面

  • 旋转:transform: rotate(9deg)
  • 缩放:transform: scale(0.85,0.90)
  • 定位:transform: translate(0px,-30px) x,y轴
  • 倾斜:transform: skew(-9deg,0deg)

image.png

<style>
.box{
    width: 150px;
    height: 150px;
    background-color: yellow;
    color: red;
    font-size: 30px;
    text-align: center;
    line-height: 150px;
    float: left;
}
</style>
<body>
    <div class="box">正常</div>
    <div class="box" style="transform: rotate(45deg);">旋转45deg</div>
    <div class="box" style="transform: scale(0.5);">缩放0.5</div>
    <div class="box" style="transform: translate(0px,100px);">定位偏移</div>
    <div class="box" style="transform: skew(-45deg,0deg);">倾斜</div>
</body>

6. 更多的 css 选择器

(1)属性选择器

例如:

input[value] {
    color: pink;
}

(2)结构伪类选择器

结构伪类选择器主要根据文档结构来选择元素 常用于根据父级选择器选择里面的子元素

选择符简介
E:first-child匹配父元素中的第一个子元素E
E:last-child匹配父元素中最后一个E元素
E:first-of-type指定类型E的第一个
E:last-of-type指定类型E的最后一个
E:nth-of-type(n)指定类型E的第n个
E:nth-child(n)匹配父元素中的第n个子元素E
<style>
    /* 第一个div标签字体变红 */
    .box div:first-child {
        color: red; 
    }
    /* 不生效 因为p标签不是box父容器中第一个元素 */
    .box p:first-child {
        color: red; 
    }
    /* 生效,第一个p标签内容字体变红 */
    .box p:first-of-type {
        color: red;
    }
    /* 常用的 双数 */
    .box p:nth-child(2n){
        color:red;
    }
    /* 常用的 单数 */
    .box p:nth-child(2n+1) {
        color: red;
    }
</style>
<body>
    <div class="box">
        <div>第一个div元素</div>
        <p>第一个p元素</p>
        <p>第二个p元素</p>
        <p>第三个p元素</p>
        <p>第四个p元素</p>
        <p>第五个p元素</p>
        <div>我第二个div元素</div>
    </div>
</body>
first-child 与 first-of-type 的区别是什么?

first-child 匹配的是父元素的第一个子元素 , 可以说是结构上的第一个子元素。 first-of-type 匹配的是该类型的第一个元素,类型就是指冒号前面匹配到的元素。并不限制是第一个子元素,只要是该类型元素的第一个即可。 当然,这些元素的范围都属于同一级,也就是同辈。

(3)伪元素选择器

伪元素选择器可以帮我们利用CSS创建新标签元素,而不需要HTML标签,从而简化HTML结构 ::before:在元素内部的前面插入内容;::after:在元素内部的后面插入内容

新创建的这个元素在文档树中是找不到的,所以我们称为伪元素

7. 多背景设置;

background: url("p1.jpg") 0 0 no-repeat,
            url("p2.jpg") 200px 0 no-repeat,
            url("p3.jpg") 400px 201px no-repeat;

/* 或者 */
background-image:url("1.jpg"),url("2.jpg"),url("3.jpg");
background-position: 0 0, 200px 0, 400px 201px;

8. 色彩模式,如 rgba;

9. 媒体查询; @media

简单来说就是检测用户浏览当前网页所使用的设备。常见的媒体设备包括电脑、智能手机、平板电脑、屏幕阅读器、打印设备等。除了查询用户所使用的设备类型,我们可能还需要知道设备的屏幕尺寸、分辨率、设备方向等信息,以便我们制作出可以在各种设备上查看的网页效果。

使用方法 @media 媒体类型 and (媒体特性){ 样式规则 )

/* 当视口宽度小于等于768像素时应用这些样式 */
@media screen and (max-width: 768px) { ... } 
/* 在打印页面时应用这些样式 */
@media print { ... }
/* 当设备处于水平模式时应用这些样式 */
@media only screen and (orientation: landscape) { ... }
/* 当设备处于垂直模式时应用这些样式 */
@media only screen and (orientation: portrait) { ... }
/* 当设备的分辨率为96 dpi时应用这些样式 */
@media only screen and (resolution: 96dpi) { ... }
/* 当设备没有色彩支持时应用这些样式 */
@media only screen and (color: 0) { ... }
/* 当设备只能通过大型指针进行交互时应用这些样式 */
@media only screen and (pointer: coarse) { ... }
/* 当设备支持光标悬停效果时应用这些样式 */
@media only screen and (hover: hover) { ... } 

10. 图片边框( border-image )

详情可以到w3c这里 语法:

border-image: source slice width outset repeat|initial|inherit;
描述
border-image-source用在边框的图片的路径。
border-image-slice图片边框向内偏移。
border-image-width图片边框的宽度。
border-image-outset边框图像区域超出边框的量。
border-image-repeat图像边框是否应平铺(repeated)、铺满(rounded)或拉伸(stretched)。

image.png

<style> 
div
{
border:15px solid transparent;
width:300px;
padding:10px 20px;
}

#round
{
-moz-border-image:url(/i/border.png) 30 30 round;	/* Old Firefox */
-webkit-border-image:url(/i/border.png) 30 30 round;	/* Safari and Chrome */
-o-border-image:url(/i/border.png) 30 30 round;		/* Opera */
border-image:url(/i/border.png) 30 30 round;
}
</style>
<body>
    <div id="round">在这里,图片铺满整个边框。</div>
</body>

11. 动画( animation )

优点:

  • 在性能上会稍微好一些 , 浏览器会对 CSS3 的动画做一些优化。
  • 代码相对简单。 缺点:
  • 在动画控制上不够灵活 。
  • 兼容性不好。
  • 部分动画功能无法实现。

例如:365度不断旋转

<style>
    .rotate {
            width: 100px;
            height: 100px;
            background-color: red;
            animation: rotateAnimation 2s linear infinite; /* 设置动画属性 */
        }
        
        @keyframes rotateAnimation {
            0%   { transform: rotate(0deg); } /* 初始状态为0度 */
            100% { transform: rotate(360deg); } /* 结束状态为360度 */
        }
</style>
<body>
    <div class="rotate"></div> 
</body>

Animation 与 Transition 的异同是什么?

Animation 与 Transition 的功能相同,都是通过改变元素的属性值来实现动画效果的。 它们的区别在于 , 使用 Transition 的功能时只 能用指定属性的开始值和结束值, 然 后在这两个属性值之间使用平滑过渡的方式实现动画效果 , 因此不能实现比较复杂的动 画效果。 Animation 功能通过定义多个关键帧,以及定义每个关键帧中元素的属性值末 实现更为复杂的动画效果。