CSS
关于 CSS 的一些总结, 持续更新中……
常用 CSS(面试常问点)
CSS 选择器及其优先级
选择器 | 格式 | 优先级、权重 |
---|---|---|
id选择器 | #id | 100 |
类选择器 | .className | 10 |
属性选择器 | a[ref='ccc'] | 10 |
伪类选择器 | li:last-child | 10 |
标签选择器 | a | 1 |
伪元素选择器 | div:after | 1 |
相邻兄弟选择器 | h1+p | 0 |
子选择器 | div>a | 0 |
后代选择器 | div a | 0 |
通配符选择器 | * | 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);
清除浮动方法
常用的清除浮动方法:
- 父级 div 设置 height
- 添加空标签
<div></div>
然后设置样式 clear:both - 利用伪类选择器 :after 添加样式
:after { display: block; clear :both; content: '';}
- 父级设置
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 等分辨率差别比较挺大的设备
除此之外,还有 vh vw calc()
- vh 代表视窗高度,1vh = 1%的视窗高度
- vw 代表视窗宽度,1vw = 1%的视窗宽度
- calc() 是 css 中的计算函数,可以使用四则运算,也可以对 百分比、px、em、rem 计算
- 注意的是,在使用运算符时,运算符两侧得有空格留出
link 和 @import 区别
首先两者都是引入外部 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-grow
,flex-shrink
和flex-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-content
,align-items
,align-content
搭配使用
justify-content
属性定义了项目在主轴上的对齐方式。align-items
属性定义项目在交叉轴上如何对齐。align-content
属性定义了多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用。
还有两个 flex-direction
和 flex-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;
}
上面代码表示划分出 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 更易于编写和维护。
以下是它们的区别:
-
语法:Stylus 使用缩进式语法,SCSS 和 Less 使用类似于 CSS 的语法。
-
变量:Stylus、SCSS 和 Less 都支持变量,但是它们的语法略有不同。在 Stylus 中,变量名前面不需要加 $ 符号;在 SCSS 和 Less 中,变量名前面需要加 $ 符号。
-
嵌套规则:Stylus、SCSS 和 Less 都支持嵌套规则,但是它们的语法略有不同。在 Stylus 中,使用缩进来表示嵌套;在 SCSS 和 Less 中,使用大括号来表示嵌套。
-
运算符:Stylus、SCSS 和 Less 都支持运算符,但是它们的语法略有不同。在 Stylus 中,运算符前后不需要加空格;在 SCSS 和 Less 中,运算符前后需要加空格。
-
函数:Stylus、SCSS 和 Less 都支持函数,但是它们的语法略有不同。在 Stylus 中,函数名后面不需要加括号;在 SCSS 和 Less 中,函数名后面需要加括号。
-
兼容性:SCSS 和 Less 都是 css 的升级版,因此它们的语法更接近于 CSS,更易于学习和使用。同时,它们也更加兼容现有的 CSS 代码。
总的来说,Stylus、SCSS 和 Less 都是很好的 CSS 预处理器,选择哪一个取决于个人喜好和项目需求。如果你已经熟悉了 CSS 的语法,那么 SCSS 和 Less 可能更容易上手一些。如果你喜欢简洁的语法和更高的灵活性,那么 Stylus 可能更适合你。