Skip to main content

CSS

关于 CSS 的一些总结, 持续更新中……

常用 CSS(面试常问点)

CSS 选择器及其优先级

选择器格式优先级、权重
id选择器#id100
类选择器.className10
属性选择器a[ref='ccc']10
伪类选择器li:last-child10
标签选择器a1
伪元素选择器div:after1
相邻兄弟选择器h1+p0
子选择器div>a0
后代选择器div a0
通配符选择器*0

对于选择器的优先级:

  • 标签选择器、伪元素选择器:1
  • 类选择器、伪类选择器、属性选择器:10
  • id 选择器:100
  • 内联样式:1000

注意事项:

  • !important 声明的样式的优先级最高;
  • 如果优先级相同,则最后出现的样式生效;
  • 继承得到的样式的优先级最低;
  • 通用选择器(*)、子选择器(>)和相邻同胞选择器(+)并不在这四个等级中,所以它们的权值都为 0 ;
  • 样式表的来源不同时,优先级顺序为:内联样式 > 内部样式 > 外部样式 > 浏览器用户自定义样式 > 浏览器默认样式。

content 属性

css 中 content 属性,是专门用于伪元素 after/before 伪元素选择器上,用来生成内容插入。最常见的是图标,还有清除浮动。

如何让 chrome 支持 10px 的文字?

font-size: 12px;
-webkit-transform: scale(0.84);
font-size: 20px;
-webkit-transform: scale(0.5);

清除浮动方法

常用的清除浮动方法:

  1. 父级 div 设置 height
  2. 添加空标签 <div></div> 然后设置样式 clear:both
  3. 利用伪类选择器 :after 添加样式 :after { display: block; clear :both; content: '';}
  4. 父级设置 overflow: hidden

px、em、rem、rpx

三者的区别:

  • px 是固定的像素,一旦设置了就无法因为适应页面大小而改变。
  • em 和 rem 相对于 px 更具有灵活性,他们是相对长度单位,其长度不是固定的,更适用于响应式布局。
  • em 是相对于其父元素来设置字体大小,这样就会存在一个问题,进行任何元素设置,都有可能需要知道他父元素的大小。而 rem 是相对于根元素,这样就意味着,只需要在根元素确定一个参考值。
  • rpx 是微信小程序中使用的单位,相当于把屏幕分成了 750 份
  • rem 是基于 根元素 html 设置的 font-size 参考值为基准来进行转换,默认为 16px,即默认 1rem = 16 / 16

使用场景:

  • 对于只需要适配少部分移动设备,且分辨率对页面影响不大的,使用 px 即可 。
  • 对于需要适配各种移动设备,使用 rem,例如需要适配 iPhone 和 iPad 等分辨率差别比较挺大的设备
tip

除此之外,还有 vh vw calc()

  • vh 代表视窗高度,1vh = 1%的视窗高度
  • vw 代表视窗宽度,1vw = 1%的视窗宽度
  • calc() 是 css 中的计算函数,可以使用四则运算,也可以对 百分比、px、em、rem 计算
    • 注意的是,在使用运算符时,运算符两侧得有空格留出

首先两者都是引入外部 css 的方式,主要区别是:

  • link 是 Xhtml 标签,除了可以加载 css 外,还可以定义 RSS 等事务;
  • @import 只属于 css, 用于引用外部 css
  • 兼容性,@import 是 css 2.1 引入的
  • link 支持使用 js 去控制改变样式,@import 是不支持的

CSS3 的新特性

  • 圆角 border-redius
  • 多列布局 multi-column layout
  • 阴影 shadow
  • 文字效果 text-shadow
  • 文字渲染 text-decoration
  • 渐变 gradient
  • 旋转,缩放,倾斜等 transform
  • 动画,多背景等
  • 新增选择器
    • 非选择器 :not
    • first-of-type
    • last-of-type
    • only-of-type
    • only-child
    • nth-child()
    • :before
    • :after
    • :checked
    • :disabled
    • :enableds

BFC

俗称 块级格式化上下文,就是一个独立的布局环境,一个容器盒子,在这个容器内按照一定的规则包房物品,且不会收外部环境物品的影响。

那如何创建一个 BFC?

  • body
  • float 除了 none 以外的设置
  • 定位 position absolute,fixed
  • display inline-block,flex,table-cell 等
  • overflow hidden, auto, scroll

特点:

  • 垂直方向为 从上到下 文档流的排列
  • BFC 中上下两个块之间的 margin 会重叠
  • 计算高度时会将 浮动元素的高度计算在内
  • BFC 区域不会和浮动元素发生重叠
  • 独立容器

动画

  • 依靠 css3 中的 translation, transform, animation
  • translation 主要是定义变化的过程
    • *-property 动画过渡属性的名称
    • *-duration 动画时长
    • *-time-function 时间函数 ease-in-out、 ease-out 等
    • *-delay 结束时间
  • transform 主要定义元素的变化结果
    • rotate 旋转
    • scale 缩放
    • skew 拉伸
    • translate 移动
    • matrix matrix(a, b, c, d, tx, ty) 其中 a, b, c, d 分别代表函数 scaleX(), skewY(), skewX(), scaleY(),它们共同代表一个线性变换。tx 和 ty 表示位移,分别代表 translateX(), translateY()
  • animation 主要定义动画的效果
    • *-name 动画名称
    • *-duration 时长
    • *-time-function 时间函数
    • *-delay 结束时间
    • *-iteration-count 动画次数
    • *-direction 播放 - 正向,反向,交替
    • *-play-state 动画播放状态 运行还是暂停
    • *-fill-mode 设置 CSS 动画在执行之前和之后如何将样式应用于其目标。

上面的 animation 中 的动画名称 可以使用 @keyframes 来声明,然后通过 from,to 或者百分比来定义动画元素的状态,最常见的就是 轮播图,直接上例子:

/**css**/
.ani {
width: 480px;
height: 320px;
margin: 50px auto;
overflow: hidden;
box-shadow: 0 0 5px rgba(0, 0, 0, 1);
background-size: cover;
background-position: center;
-webkit-animation-name: "loops";
-webkit-animation-duration: 20s;
-webkit-animation-iteration-count: infinite;
}
@-webkit-keyframes "loops" {
0% {
background:url(http://d.hiphotos.baidu.com/image/w%3D400/sign=c01e6
}
25% {
background:url(http://b.hiphotos.baidu.com/image/w%3D400/sign=edee1
}
50% {
background:url(http://b.hiphotos.baidu.com/image/w%3D400/sign=937da
}
75% {
background:url(http://g.hiphotos.baidu.com/image/w%3D400/sign=7d375
}
100% {
background:url(http://c.hiphotos.baidu.com/image/w%3D400/sign=cfb23
}
}

Flex

flex 布局,是一种弹性盒布局模型,给子元素提供了空间分布和对齐能力,由container(容器)及item(项目)组成。该布局模型提供了一种更加高效的方式来对容器中的项目进行布局、对齐和分配空间。适用于在不同尺寸的屏幕中创建可自动扩展和收缩布局,通常可用于水平/垂直居中,两栏、三栏布局等的场景里。

其中flex属性是flex-growflex-shrinkflex-basis的简写,默认值为0 1 auto。该属性有两个快捷值:auto (1 1 auto)none (0 0 auto)

  • flex-grow: 定义项目的放大比例,默认值为 0,即如果存在剩余空间,也不放大。如果所有项目的 flex-grow 属性都为 1,则它们将等分剩余空间(如果有的话)。如果一个项目的 flex-grow 属性为 2,其他项目都为 1,则前者占据的剩余空间将比其他项多一倍。

  • flex-shrink: 项目的缩小比例,默认为 1,即如果空间不足,项目将缩小。如果所有项目的 flex-shrink 属性都为 1,当空间不足时,都将等比例缩小。如果一个项目的 flex-shrink 属性为 0,其他项目都为 1,则空间不足时,前者不缩小。

  • flex-basis: 定义了在分配多余空间之前,项目占据的主轴空间。浏览器会根据该属性,计算主轴是否有多余空间。它的默认值为 auto,即项目的本来大小。当设置为 0 的是,会根据内容撑开。也可以设为跟 width 或 height 属性一样的值(比如 350px),则项目将占据固定空间。

flex 常用属性值:

  • flex: 1 --> flex: 1 1 0%
  • flex: 2 --> flex: 2 1 0%
  • flex: auto --> flex: 1 1 auto
  • flex: none --> flex: 0 0 auto【常用于固定尺寸不伸缩】

除此之外,flex 经常和 justify-contentalign-itemsalign-content 搭配使用

  • justify-content 属性定义了项目在主轴上的对齐方式。
  • align-items 属性定义项目在交叉轴上如何对齐。
  • align-content 属性定义了多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用。

还有两个 flex-directionflex-warp

  • flex-direction 是控制 flex 的主轴方向,正向还是反向
    • row flex 容器的主轴被定义为与文本方向相同。主轴起点和主轴终点与内容方向相同
    • row-reverse row 反向
    • column flex 容器的主轴和块轴相同。主轴起点与主轴终点和书写模式的前后点相同
    • column-reverse column 反向
  • flex-warp 指定 flex 元素单行显示还是多行显示
    • warp 单行
    • no-warp 多行

以上两个可以使用 flex-flow 来缩写

gird

Grid 布局是将容器划分成了“行”和“列”,产生了一个个的网格,我们可以将网格元素放在与这些行和列相关的位置上,从而达到我们布局的目的。

我们通过在元素上声明 display:grid 或 display:inline-grid 来创建一个网格容器。声明 display:grid 则该容器是一个块级元素,设置成 display: inline-grid 则容器元素为行内元素

grid-template-columns 属性和 grid-template-rows 属性

  • grid-template-columns 属性设置列宽

  • grid-template-rows 属性设置行高 这两个属性在 Grid 布局中尤为重要,它们的值是有多种多样的,而且它们的设置是比较相似的

    .wrapper {
    display: grid;
    /* 声明了三列,宽度分别为 200px 100px 200px */
    grid-template-columns: 200px 100px 200px;
    grid-gap: 5px;
    /* 声明了两行,行高分别为 50px 50px */
    grid-template-rows: 50px 50px;
    /* 这里相同行高的 可以使用 repeat(2, 50px)来设置 */
    }
  • repeat() 函数:可以简化重复的值。该函数接受两个参数,第一个参数是重复的次数,第二个参数是所要重复的值。

  • auto-fill 关键字:表示自动填充, 让一行(或者一列)中尽可能的容纳更多的单元格。

  • fr 关键字:Grid 布局还引入了一个另外的长度单位来帮助我们创建灵活的网格轨道。

    .wrapper-3 {
    display: grid;
    /* 分为三列 200px 一列,剩下两列 一列占1/3, 最后一列占 2/3 */
    grid-template-columns: 200px 1fr 2fr;
    grid-gap: 5px;
    grid-auto-rows: 50px;
    }
  • minmax() 函数:我们有时候想给网格元素一个最小和最大的尺寸,minmax() 函数产生一个长度范围,表示长度就在这个范围之中都可以应用到网格项目中。

    .wrapper-4 {
    display: grid;
    grid-template-columns: 1fr 1fr minmax(300px, 2fr);
    grid-gap: 5px;
    grid-auto-rows: 50px;
    }
  • auto 关键字:由浏览器决定长度。通过 auto 关键字,我们可以轻易实现三列或者两列布局。grid-template-columns: 100px auto 100px 表示第一第三列为 100px,中间由浏览器决定长度

    .wrapper-5 {
    display: grid;
    grid-template-columns: 100px auto 100px;
    grid-gap: 5px;
    grid-auto-rows: 50px;
    }

grid-row-gap 属性、grid-column-gap 属性以及 grid-gap 属性

  • grid-row-gap 表示行间距
  • grid-column-gap 表示列间距
  • grid-gap 相当于前两者的缩写

grid-template-areas 属性

grid-template-areas 属性用于定义区域,一个区域由一个或者多个单元格组成

.wrapper {
display: grid;
grid-gap: 10px;
grid-template-columns: 120px 120px 120px;
grid-template-areas:
". header header"
"sidebar content content";
background-color: #fff;
color: #444;
}
.sidebar {
grid-area: sidebar;
}

.content {
grid-area: content;
}

.header {
grid-area: header;
}
info

上面代码表示划分出 6 个单元格,其中值得注意的是 . 符号代表空的单元格,也就是没有用到该单元格。

grid-auto-flow 属性

grid-auto-flow 属性控制着自动布局算法怎样运作,精确指定在网格中被自动布局的元素怎样排列。默认的放置顺序是"先行后列",即先填满第一行,再开始放入第二行,即下图英文数字的顺序 one,two,three...。这个顺序由 grid-auto-flow 属性决定,默认值是 row。

.wrapper {
display: grid;
grid-template-columns: 100px 200px 100px;
grid-auto-flow: row;
grid-gap: 5px;
grid-auto-rows: 50px;
}
  • grid-auto-flow: row dense 表示尽可能填满表格,
  • grid-auto-flow: column 表示先列后行,结果就是
    • 1,3,5
    • 2,4,6

grid-auto-columns 属性和 grid-auto-rows 属性

在讲 grid-auto-columns 属性和 grid-auto-rows 属性之前,先来看看隐式和显式网格的概念

隐式和显式网格:显式网格包含了你在 grid-template-columns 和 grid-template-rows 属性中定义的行和列。如果你在网格定义之外又放了一些东西,或者因为内容的数量而需要的更多网格轨道的时候,网格将会在隐式网格中创建行和列

假如有多余的网格(也就是上面提到的隐式网格),那么它的行高和列宽可以根据 grid-auto-columns 属性和 grid-auto-rows 属性设置。它们的写法和 grid-template-columns 和 grid-template-rows 完全相同。如果不指定这两个属性,浏览器完全根据单元格内容的大小,决定新增网格的列宽和行高

两栏布局

  • 浮动实现

    • 使用 float 使左边容器浮动
    • 右边容器使用 margin-left 撑出宽度做内容显示
    • 父容器添加 BFC,让子容器撑起其高度 代码如下
        <style>
      .box {
      overflow: hidden; /*添加BFC*/
      }
      .left {
      float: left;
      width: 200px;
      background-color: goldenrod;
      height: 200px;
      }
      .right {
      margin-left: 200px;
      background-color: lightgray;
      height: 200px;
      }
      </style>
      <div class="box">
      <div class="left">left</div>
      <div class="right">right</div>
      </div>
  • flex 弹性布局实现

    • 给父容器添加 display:flex
    • 左边容器设置宽度
    • 右边容器 flex:1 占据剩余宽度 代码如下
      <style>
    .box {
    display: flex;
    }
    .left {
    background-color: greenyellow;
    width: 200px;
    height: 200px;
    }
    .right {
    background-color: fuchsia;
    height: 200px;
    flex: 1;
    }
    </style>
    <div class="box">
    <div class="left">left</div>
    <div class="right">right</div>
    </div>

三栏布局

  • 两边使用 absolute,中间使用 margin
  • 圣杯布局(两边使用 float 和负 margin)
  • 双飞翼布局(两边使用 absolute,中间使用 margin)
  • display: grid; 网格布局
    • 将父容器设置成网格布局
    • grid-template-columns: 200px auto 200px; 设置三列网格其中左右分别 200px,中间自适应
  • display:flex; 弹性布局
    • 将父容器设置为 display:flex;。
    • 盒内元素两端对齐,将中间容器设置 flex:1,填充空白区域。

选择器

逻辑选择器

在 CSS 选择器家族中,新增这样一类比较新的选择器 -- 逻辑选择器,目前共有 4 名成员:

:is, :where, :not, :has

1、:is 伪类选择器

:is() CSS 伪类函数将选择器列表作为参数,并选择该列表中任意一个选择器可以选择的元素。

在之前,对于多个不同父容器的同个子元素的一些共性样式设置,可能会出现如下 CSS 代码:

header p:hover,
main p:hover,
footer p:hover {
color: red;
cursor: pointer;
}

// k可以改写为:
:is(header, main, footer) p:hover {
color: red;
cursor: pointer;
}

下面的动图更形象的展示

同时也是支持多层级 层叠连用

<div>
<i>div i</i>
</div>
<p>
<i>p i</i>
</p>
<div>
<span>div span</span>
</div>
<p>
<span>p span</span>
</p>
<h1>
<span>h1 span</span>
</h1>
<h1>
<i>h1 i</i>
</h1>
div span,
div i,
p span,
p i {
color: red;
}

/* 使用 `:is` 之后: */
:is(div, p) :is(span, i) {
color: red;
}

然而,他并不是万能的,:is 是不支持【伪元素】,例如:

注意,仅仅是不支持伪元素,伪类,譬如 :focus:hover 是支持的。

div p::before,
div p::after {
content: "";
//...
}

/* 上面的就不支持写为下面 */
div p:is(::before, ::after) {
content: "";
//...
}

:is 选择器的优先级

<div>
<p class="test-class" id="test-id">where & is test</p>
</div>
<div>
<p class="test-class">where & is test</p>
</div>
/* 
此时,由于 div :is(p) 可以看成 div p,优先级是没有 div .test-class 高的,
因此,被选中的文本的颜色是不会发生变化的。
*/
div :is(p) {
color: blue;
}

/* 如果想加上#text-id */
div :is(p, #text-id) {
color: blue;
}

对于 div :is(p, #text-id)is:() 内部有一个 id 选择器,因此,被该条规则匹配中的元素,全部都会应用 div #id 这一级别的选择器优先级。这里非常重要,再强调一下,对于 :is() 选择器的优先级,我们不能把它们割裂开来看,它们是一个整体,优先级取决于选择器列表中优先级最高的选择器

:is 的别名 :matches():any()

:is() 是最新的规范命名,在之前,有过有同样功能的选择,分别是:

:is(div, p) span {
}
// 等同于
:-webkit-any(div, p) span {
}
:-moz-any(div, p) span {
}
:matches(div, p) span {
}

2、:where 伪类选择器

了解了 :is 后,我们可以再来看看 :where,它们两个有着非常强的关联性。:where 同样是将选择器列表作为其参数,并选择可以由该列表中的选择器之一选择的任何元素。

还是这个例子:

:where(header, main, footer) p:hover {
color: red;
cursor: pointer;
}

/* 上面的css,等同于: */
header p:hover,
main p:hover,
footer p:hover {
color: red;
cursor: pointer;
}

上面的样式看上去和 :is 貌似一样啊,下面来说下两者的区别:

伪类和伪元素的区别

  • 伪类是表示状态
    • :hover
    • :focus
    • ...
  • 伪元素是真的元素
    • ::after
    • ::before
    • ...
  • 伪类是单个 :, 伪元素是 :: 两个冒号

CSS 优化 工程化

优化方式

  • 加载优化
    • css 压缩
    • css 单一样式
    • 减少使用 @import
  • 选择器
    • 避免使用通配
    • 减少标签选择的使用,使用 class
    • 尽量少的使用后代选择器,降低权重,减少开销
    • 属性值为 0 不加单位
    • 去除空规则
    • 浮点数 0.22 可以直接使用 .22
    • 减少嵌套层级
    • 慎用字体
    • 相同样式抽离公用

工程化

目前最流行的预处理器 Sass,Less 等;还有 PostCss 工程化插件

使用预处理器,主要是为了解决:

  • 可以自定义 css 变量, less 的 @声明变量 sass 的 $声明变量
  • 提供计算函数
  • 嵌套代码能力,展示利于阅读的层级关系
  • 支持代码片段 extend mixin
  • 支持循环语句的使用 sass 的 @for less 的 each
  • css 文件模块化,实现复用

PostCSS

PostCss 是一个对 css 解析处理的工具,和预处理器不同的是, 预处理器是类 css,Postcss 处理的就是 css 本身, 类似于 babel 将高版本的 js 转换为低版本的 js, PostCss 做的就是类似的事情, 高级的 css 很可能存在的兼容性问题, PostCss 就可以解决这类问题。

除此之外,PostCss 还有更强大的插件机制,支持拓展, 比如:autoPrefixer。

css 预处理器

最常见的三种预处理器:Less, Scss, Stylus, 它们的主要作用是让 CSS 更易于编写和维护。

以下是它们的区别:

  1. 语法:Stylus 使用缩进式语法,SCSS 和 Less 使用类似于 CSS 的语法。

  2. 变量:Stylus、SCSS 和 Less 都支持变量,但是它们的语法略有不同。在 Stylus 中,变量名前面不需要加 $ 符号;在 SCSS 和 Less 中,变量名前面需要加 $ 符号。

  3. 嵌套规则:Stylus、SCSS 和 Less 都支持嵌套规则,但是它们的语法略有不同。在 Stylus 中,使用缩进来表示嵌套;在 SCSS 和 Less 中,使用大括号来表示嵌套。

  4. 运算符:Stylus、SCSS 和 Less 都支持运算符,但是它们的语法略有不同。在 Stylus 中,运算符前后不需要加空格;在 SCSS 和 Less 中,运算符前后需要加空格。

  5. 函数:Stylus、SCSS 和 Less 都支持函数,但是它们的语法略有不同。在 Stylus 中,函数名后面不需要加括号;在 SCSS 和 Less 中,函数名后面需要加括号。

  6. 兼容性:SCSS 和 Less 都是 css 的升级版,因此它们的语法更接近于 CSS,更易于学习和使用。同时,它们也更加兼容现有的 CSS 代码。

总的来说,Stylus、SCSS 和 Less 都是很好的 CSS 预处理器,选择哪一个取决于个人喜好和项目需求。如果你已经熟悉了 CSS 的语法,那么 SCSS 和 Less 可能更容易上手一些。如果你喜欢简洁的语法和更高的灵活性,那么 Stylus 可能更适合你。