CSS记忆点

1,260 阅读19分钟

一、盒模型

元素的内在盒子是由margin boxborder boxpadding boxcontent box组成的,这四个盒子由外到内构成了盒模型。

  • content-box,默认值,只计算内容的宽度,border和padding不计算入width之内
  • padding-box,padding计算入宽度内
  • border-box,border和padding计算入宽度之内

二、CSS基础

1、 CSS 有哪些样式可以给子元素继承!

  • 可继承的:font-size,font-weight,line-height,color,cursor
  • 不可继承的一般是会改变盒子模型的:display,marginborderpaddingheight

更加全面的可以到引擎找

2、 行内元素有哪些?块级元素有哪些? 空(void)元素有那些?

块级元素是指单独撑满一行的元素,如div、ul、li、table、p、h1等元素。这些元素的display值默认是block、table、list-item等。

内联元素又叫行内元素,指只占据它对应标签的边框所包含的空间的元素,这些元素如果父元素宽度足够则并排在一行显示的,如span、a、em、i、img、td等。这些元素的display值默认是inline、inline-block、inline-table、table-cell等。

实际开发中,我们经常把display计算值为inline inline-block inline-table table-cell的元素叫做内联元素,而把display计算值为block的元素叫做块级元素。

3、width: auto 和 height: auto

widthheight的默认值都是auto

对于块级元素,流体布局之下width: auto自适应撑满父元素宽度。这里的撑满并不同于width: 100%的固定宽度,而是像水一样能够根据margin不同而自适应父元素的宽度。

对于内联元素,width: auto则呈现出包裹性,即由子元素的宽度决定。

无论内联元素还是块级元素,height: auto都是呈现包裹性,即高度由子级元素撑开。

注意父元素height: auto会导致子元素height: 100%百分比失效。

css的属性非常有意思,正常流下,如果块级元素的width是个固定值,marginauto,则margin会撑满剩下的空间;如果margin是固定值,widthauto,则width会撑满剩下的空间。这就是流体布局的根本所在。

4、消除图片底部间隙的方法

  • 图片块状化 - 无基线对齐:img { display: block; }
  • 图片底线对齐:img { vertical-align: bottom; }
  • 行高足够小 - 基线位置上移:.box { line-height: 0; }

5、层叠上下文

层叠上下文好像是一个结界,层叠上下文内的元素如果跟层叠上下文外的元素发生层叠,则比较该层叠上下文和外部元素的层叠上下文的层叠水平高低。

创建一个层叠上下文的方法就是给position值为relative/aboslute/fixed的元素设置z-index不为auto的值。

三、CSS3特性

1、CSS 中transition和animate有何区别? animate 如何停留在最后一帧!

这种问题见仁见智,我的回答大体是这样的..待我捋捋.

transition一般用来做过渡的, 没时间轴的概念, 通过事件触发(一次),没中间状态(只有开始和结束)

animate则是做动效,有时间轴的概念(帧可控),可以重复触发和有中间状态;

过渡的开销比动效小,前者一般用于交互居多,后者用于活动页居多;

至于如何让animate停留在最后一帧也好办,就它自身参数的一个值就可以了

2、word-spacing 空格间隙

不要被表面意思误导,word-spacing指的是字符“空格”的间隙。如果一段文字中没有空格,则该属性无效。下面代码设定空格间隙是20px,也就是说空格现在占据的宽度是原有的空格宽度+20px的宽度:

<p>我有空 格,我该死......</p>
<style>
  p {
    word-spacing: 20px;
  }
</style>
复制代码

3、white-space 空白处理

我们都知道如果在html中输入多个空白符,默认会被当成一个空白符处理,实际上就是这个属性控制的:地址

  1. normal:合并空白符和换行符;
  2. nowrap:合并空白符,但不许换行;
  3. pre:不合并空白符,并且只在有换行符的地方换行;
  4. pre-wrap:不合并空白符,允许换行符换行和文本自动换行;

四、CSS选择器及其优先级

1、CSS选择器

  • !important
  • 内联样式style=""
  • ID选择器#id
  • 类选择器/属性选择器/伪类选择器.class.active[href=""]
  • 元素选择器/关系选择器/伪元素选择器html+div>span::after
  • 通配符选择器*

2、权重值和选择器 

  1.  1,0,0,0 内联样式:style="" 
  2.  0,1,0,0 ID选择器:#idName{...} 
  3.  0,0,1,0 类、伪类、属性选择器:.className{...} / :hover{...} / [type="text"] ={...} 
  4.  0,0,0,1 标签、伪元素选择器:div{...} / :after{...} 
  5.  0,0,0,0 通用选择器(*)、子选择器(>)、相邻选择器(+)、同胞选择器(~)

当两个权值进行比较的时候,是从高到低逐级将等级位上的权重值来进行比较的,而不是 1000个数 + 100个数 + 10个数 + 1个数 的总和来进行比较的,换句话说,低等级的选择器个数再多也不会超过高等级的选择器的优先级的。

3、!important的权重最高

如果出现了!important,则不管权重如何都取有!important的属性值。但是宽高有例外情况,由于宽高会被max-width/min-width覆盖,所以!important会失效。

4、 !important问题

超越!important:max-width会覆盖width,而且这种覆盖是超级覆盖,比!important的权重还要高

超越最大:min-width覆盖max-width,此规则发生在min-width和max-width冲突的时候,如下:

.container{
    min-width:1400px;
    max-width:1200px;
}

5、面试题举例

// 假设下面样式都作用于同一个节点元素`span`,判断下面哪个样式会生效
body#god div.dad span.son {width: 200px;}
body#god span#test {width: 250px;}

因此上面那道的面试题比较应该是在第二等级id选择器的比较就结束了:(#god + #test = 0,2,0,0) > (#god = 0,1,0,0);而上图种例子中两个权重分别是:(#test = 0,1,0,0) > (.test....test10 = 0,0,11,0),也是在第二等级id选择器的比较时就结束了。所以以后比较权重,就先比较id选择器个数,如果id一样多,再比较class选择器个数。

五、BFC

BFC(Block Formatting Context)格式化上下文,是Web页面中盒模型布局的CSS渲染模式,指一个独立的渲染区域或者说是一个隔离的独立容器。 

BFC应用

  • 防止margin重叠
  • 清除内部浮动
  • 自适应两(多)栏布局
  • 防止字体环绕

触发BFC条件

  • 根元素
  • float的值不为none
  • overflow的值不为visible
  • display的值为inline-block、table-cell、table-caption
  • position的值为absolute、fixed

BFC的特性

  • 内部的Box会在垂直方向上一个接一个的放置。

  • 垂直方向上的距离由margin决定

  • bfc的区域不会与float的元素区域重叠。

  • 计算bfc的高度时,浮动元素也参与计算

  • bfc就是页面上的一个独立容器,容器里面的子元素不会影响外面元素。

六、水平居中

1、行内元素

.parent {
    text-align: center;
}

2、块级元素

.son {
    margin: 0 auto;
}

3、flex布局

.parent {
    display: flex;
    justify-content: center;
}

4、绝对定位定宽

.son {
    position: absolute;
    width: 宽度;
    left: 50%;
    margin-left: -0.5*宽度
}

5、绝对定位不定宽

.son {
    position: absolute;
    left: 50%;
    transform: translate(-50%, 0);
}

6、left/right: 0

.son {
    position: absolute;
    width: 宽度;
    left: 0;
    right: 0;
    margin: 0 auto;
}

七、垂直居中

1、行内元素

.parent {
    height: 高度;
}
.son {
    line-height: 高度;
}

2、table

.parent {
  display: table;
}
.son {
  display: table-cell;
  vertical-align: middle;
}

3、flex

.parent {
    display: flex;
    align-items: center;
}

4、绝对定位定高

.son {
    position: absolute;
    top: 50%;
    height: 高度;
    margin-top: -0.5高度;
}

5、绝对定位不定高

.son {
    position: absolute;
    top: 50%;
    transform: translate( 0, -50%);
}

6、top/bottom: 0;

.son {
    position: absolute;
    height: 高度;
    top: 0;
    bottom: 0;
    margin: auto 0;
}

八、CSS 引入的方式有哪些? link 和@import 的区别是?

有四种:内联(元素上的style属性)、内嵌(style标签)、外链(link)、导入(@import) link和@import的区别:

  • link是XHTML标签,除了加载CSS外,还可以定义RSS等其他事务;@import属于CSS范畴,只能加载CSS

  • link引用CSS时,在页面载入时同时加载@import需要页面网页完全载入以后加载

  • link是XHTML标签,无兼容问题@import是在CSS2.1提出的,低版本的浏览器不支持

  • link支持使用Javascript控制DOM去改变样式;而@import不支持。

九、flex布局

父项常用属性

  • flex-direction:设置主轴的方向
  • justify-content:设置主轴上的子元素排列方式
  • flex-wrap:设置子元素是否换行
  • align-content:设置侧轴上的子元素的排列方式(多行)
  • align-items:设置侧轴上的子元素排列方式(单行)
  • flex-flow:复合属性,相当于同时设置了 flex-direction 和 flex-wrap

flex-direction

在 flex 布局中,是分为主轴和侧轴两个方向,同样的叫法有 : 行和列、x 轴和y 轴

  • 默认主轴方向就是 x 轴方向,水平向右
  • 默认侧轴方向就是 y 轴方向,水平向下

<img src="./imgs/13.JPG">

: 主轴和侧轴是会变化的,就看 flex-direction 设置谁为主轴,剩下的就是侧轴。而我们的子元素是跟着主轴来排列的

flex-wrap设置是否换行

  • 默认情况下,项目都排在一条线(又称”轴线”)上。flex-wrap属性定义,flex布局中默认是不换行的。
  • nowrap 不换行
  • wrap 换行

justify-content 设置主轴上的子元素排列方式

<img src="./imgs/14.jpg">

效果图

: 这里讲下space-aroundspace-evenly

  • space-around:项目之间的间距为左右两侧项目到容器间距的2倍。

  • space-evenly:项目两侧之间的间距与项目与容器两侧的间距相等,相当于除去项目宽度和容器和项目的两侧间距,剩下的平均分配了剩余宽度作为项目左右margin。

**设置侧轴上的子元素排列方式:align-items(单行)/align-content(多行) **

上图写能设置多行只能用于子项出现 换行 的情况(多行),在单行下是没有效果的。

效果跟上面是一样的只不过是方向换了,上面是元素在主轴上排列,这个是在侧抽上,至于侧轴是不是Y轴就看你的flex-direciton怎么设置的了

子项常见属性

  • flex(复合属性): 默认: flex: 0 1 auto;
    • flex-grow
    • flex-shrink
    • flex-basis
  • align-self:控制子项自己在侧轴的排列方式
  • order:定义子项的排列顺序(前后顺序), 0是第一个

flex-grow

默认0,用于决定项目在有剩余空间的情况下是否放大,默认不放大;注意,即便设置了固定宽度,也会放大。

假设第一个项目默认为0,第二个项目为flex-grow:2,最后一个项目为1,则第二个项目在放大时所占空间是最后项目的两倍。

可以这么理解:

  • flex: 1 => 在剩余的空间里我就占一份

  • flex: 2 => 在剩余的空间里我就占两份

  • flex: 3 => 在剩余的空间里我就占三份

    假设三个盒子分别都设置了上面的属性: 那就将剩余空间分成6份, 各占自己的份数

    假设前两个没有设置, 就最后一个设置了flex: 3 === flex: 1, 那就将剩余空间都给它 复制代码

flex-shrink

默认1,用于决定项目在空间不足时是否缩小,默认项目都是1,即空间不足时大家一起等比缩小;注意,即便设置了固定宽度,也会缩小。但如果某个项目flex-shrink设置为0,则即便空间不够,自身也不缩小。

上图中第二个项目flex-shrink为0,所以自身不会缩小。

flex-basis

默认auto,用于设置项目宽度,默认auto时,项目会保持默认宽度,或者以width为自身的宽度,但如果设置了flex-basis,权重会width属性高,因此会覆盖widtn属性。

上图中先设置了flex-basis属性,后设置了width属性,但宽度依旧以flex-basis属性为准。

注意⚠: 如果当容器中有多个盒子并且还宽度100%, flex-basis会被影响, 如下图

解决办法就是在我们设置flex-basis宽度时, 最好给他设置flex-shrink为0不缩放

十、grid布局

最强大的 CSS 布局 —— Grid 布局 (juejin.cn)

十一、让元素消失

visibility:hidden、display:none、z-index=-1、opacity:0

  1. opacity:0,该元素隐藏起来了,但不会改变页面布局,并且,如果该元素已经绑定了一些事件,如click事件也能触发

  2. visibility:hidden,该元素隐藏起来了,但不会改变页面布局,但是不会触发该元素已经绑定的事件

  3. display:none, 把元素隐藏起来,并且会改变页面布局,可以理解成在页面中把该元素删掉

  4. z-index=-1置于其他元素下面

十二、清除浮动

  • 在浮动元素后面添加 clear:both 的空 div 元素,

    <div class="container">
        <div class="left"></div>
        <div class="right"></div>
        <div style="clear:both"></div>
    </div>
    
  • 给父元素添加 overflow:hidden 或者 auto 样式,触发BFC。

    <div class="container">
        <div class="left"></div>
        <div class="right"></div>
    </div>
    
    .container{
        width: 300px;
        background-color: #aaa;
        overflow:hidden;
        zoom:1;   /*IE6*/
    }
    
  • 使用伪元素,也是在元素末尾添加一个点并带有 clear: both 属性的元素实现的。

    <div class="container clearfix">
        <div class="left"></div>
        <div class="right"></div>
    </div>
    
    .clearfix{
        zoom: 1; /*IE6*/
    }
    .clearfix:after{
        content: ".";
        height: 0;
        clear: both;
        display: block;
        visibility: hidden;
    }
    

推荐使用第三种方法,不会在页面新增div,文档结构更加清晰。

十三、calc函数

calc函数是css3新增的功能,可以使用calc()计算border、margin、pading、font-size和width等属性设置动态值。

#div1 {
    position: absolute;
    left: 50px;
    width: calc( 100% / (100px * 2) );
    //兼容写法
    width: -moz-calc( 100% / (100px * 2) );
    width: -webkit-calc( 100% / (100px * 2) );
    border: 1px solid black;
}

注意点:

  • 需要注意的是,运算符前后都需要保留一个空格,例如:width: calc(100% - 10px);

  • calc()函数支持 "+", "-", "*", "/" 运算;

  • 对于不支持 calc() 的浏览器,整个属性值表达式将被忽略。不过我们可以对那些不支持 calc()的浏览器,使用一个固定值作为回退。

十四、两边宽度固定中间自适应的三栏布局

圣杯布局和双飞翼布局是前端工程师需要日常掌握的重要布局方式。两者的功能相同,都是为了实现一个两侧宽度固定,中间宽度自适应的三栏布局。

圣杯布局

<style>
body{
    min-width: 550px;
}
#container{
    padding-left: 200px;
    padding-right: 150px;
}
#container .column{
    float: left;
}
#center{
    width: 100%;
}
#left{
    width: 200px;
    margin-left: -100%;
    position: relative;
    right: 200px;
}
#right{
    width: 150px;
    margin-right: -150px;
}
</style>
<div id="container">
    <div id="center" class="column">center</div>
    <div id="left" class="column">left</div>
    <div id="right" class="column">right</div>
</div>

Layout.gif

双飞翼布局

<style>
body {
    min-width: 500px;
}
#container {
    width: 100%;
}
.column {
    float: left;
}
#center {
    margin-left: 200px;
    margin-right: 150px;
}
#left {
    width: 200px;
    margin-left: -100%;
}
#right {
    width: 150px;
    margin-left: -150px;
}
</style>
<div id="container" class="column">
    <div id="center">center</div>
</div>
<div id="left" class="column">left</div>
<div id="right" class="column">right</div>

十五、伪类和伪元素

1、伪类

伪类存在的意义是为了通过选择器找到那些不存在DOM树中的信息以及不能被常规CSS选择器获取到的信息。

  1. 获取不存在与DOM树中的信息。比如a标签的:link、visited等,这些信息不存在与DOM树结构中,只能通过CSS选择器来获取;
  2. 获取不能被常规CSS选择器获取的信息。比如:要获取第一个子元素,我们无法用常规的CSS选择器获取,但可以通过 :first-child 来获取到。

weilei.png

2、伪元素

伪元素用于创建一些不在文档树中的元素,并为其添加样式。比如说,我们可以通过:before来在一个元素前增加一些文本,并为这些文本添加样式。虽然用户可以看到这些文本,但是这些文本实际上不在文档树中。常见的伪元素有:::before::after::first-line::first-letter::selection::placeholder

因此,伪类与伪元素的区别在于:有没有创建一个文档树之外的元素。

3、::after和:after的区别

在实际的开发工作中,我们会看到有人把伪元素写成:after,这实际是 CSS2 与 CSS3新旧标准的规定不同而导致的。

CSS2 中的伪元素使用1个冒号,在 CSS3 中,为了区分伪类和伪元素,规定伪元素使用2个冒号。所以,对于 CSS2 标准的老伪元素,比如:first-line:first-letter:before:after,写一个冒号浏览器也能识别,但对于 CSS3 标准的新伪元素,比如::selection,就必须写2个冒号了。

4、基于伪元素的图片内容生成技术

需求:图片还没加载时就把 alt 信息呈现出来。

实现:图片没有 src ,因此,::before::after 可以生效,我们可以通过 content 属性呈现 alt 属性值。

img::after{
    /* 生成 alt 信息 */
    content: attr(alt);
    /* 尺寸和定位 */
    postion:absolute; bottom: 0;
    width:100%;
    background-color:rgba(0,0,0,.5);
    transform: translateY(100%);
    transition: transform .2s;
}
img:hover::after{
    transform: translateY(0);
}    

当我们给图片添加src 属性时图片从普通元素变成替换元素,原本还支持的::before::after 此时全部无效,此时再hover图片,是不会有任何信息出现的。

5、 轻松实现hover图片变成另外一张图片

img:hover{
    content: url(laugh-tear.png);
}
复制代码

content 改变的仅仅是视觉呈现,当我们鼠标右键或其他形式保存这张图片时,所保存的还是原来 src 对应的图片。这种方法还可以用在官网标志上。

由于使用 conetnt 生成图片无法设置图片的尺寸,要想在移动端使用该技术,建议使用SVG图片

十六、流式布局与响应式布局的区别

流式布局 使用非固定像素来定义网页内容,也就是百分比布局,通过盒子的宽度设置成百分比来根据屏幕的宽度来进 行伸缩,不受固定像素的限制,内容向两侧填充。

响应式开发 利用CSS3 中的 Media Query(媒介查询),通过查询 screen 的宽度来指定某个宽度区间的网页布局。

  • 超小屏幕(移动设备) 768px 以下
  • 小屏设备 768px-992px
  • 中等屏幕 992px-1200px
  • 宽屏设备 1200px 以上

由于响应式开发显得繁琐些,一般使用第三方响应式框架来完成,比如 bootstrap 来完成一部分工作,当然也 可以自己写响应式

十七、回流和重绘

回流 比如我们增删DOM节点,修改一个元素的宽高,页面布局发生变化,DOM树结构发生变化,那么肯定要重新构建DOM树,而DOM树与渲染树是紧密相连的。DOM树构建完,渲染树也随之对页面再次渲染,这个过程就叫回流。(结构会变)

导致回流的操作:

  • 页面首次渲染
  • 浏览器窗口大小发生变化
  • 元素尺寸发生改变(包括外边距、内边距、边框大小、高度和宽度)
  • 元素的位置发生变化
  • 元素内容变化(文字数量或图片大小等等)
  • 元素字体大小变化

重绘 当页面中元素样式的改变并不影响它在文档流中的位置时(例如:color、background-color、visibility等),浏览器会将新样式赋予给元素并重新绘制它,这个过程称为重绘。(结构不变,样式改变)

十八、Sass常用的用法

(1)变量

SASS允许使用变量,所有变量以$开头。

/* 变量声明 */
$fontStack:    Helvetica, sans-serif;
$primaryColor: #333;

body {
  font-family: $fontStack;
  color: $primaryColor;
}

等同于css的写法

body {
  font-family: Helvetica, sans-serif;
  color: #333;
}

如果变量需要镶嵌在字符串之中,就必须需要写在#{}之中。

$side : left;
#div1 {
    margin-#{left}:10px;
}

(2)计算功能

SASS允许在代码中使用算式:

.div2 {
    margin: 10px * 2;
    padding:(14px / 2);
}

等同于css的写法

.div2 {
    margin: 20px;
    padding: 7px;
}

(3)嵌套

SASS允许选择器嵌套。比如:

  • 选择器嵌套

    nav {
      ul {
        margin: 0;
        padding: 0;
        list-style: none;
      }
    
      li { display: inline-block; }
    }
    

等同于css的写法

nav ul {
  margin: 0;
  padding: 0;
  list-style: none;
}

nav li {
  display: inline-block;
}
复制代码
  • &的嵌套

在嵌套的代码块内,可以使用&引用父元素。比如a:hover伪类,可以写成:

a {
    margin: 10px;
    &:hover {
        color: #000;
    }
}

等同于css的写法

a {
    margin: 10px;
}
a:hover {
    color: #000;
}
  • 属性嵌套(很少用,或者说不用,因为这样写更麻烦)

属性也可以嵌套,比如border-color属性,可以写成:

p{
    border: {  //注意,border后面必须加上冒号。
        color: #000;
    }
}

//转化css后
p{
    border-color: #000;
}
复制代码

(4)继承

SASS允许一个选择器,继承另一个选择器。比如,现有div3:

.div3 {
    margin: 2px;
}

/* .div4继承.div3 */
.div4 {  
    @extend .div3;
    font-size: 10px;
}

等同于css的写法

.div3, .div4 {
  margin: 2px;
}
.div4 {
  font-size: 10px;
}

(5)Mixin

Mixin有点像C语言的宏(macro),是可以重用的代码块。

  • 1、使用@mixin命令,定义一个代码块

  • 2、后续可以通过@include复用

    @mixin p1 {
        float: left;
    }
    
    div {
    /*使用@include命令,调用这个mixin。*/
        @include p1; 
        top: 10px;
    }
    

等同于css的写法

div {
  float: left;
  top: 10px;
}

mixin的强大之处,在于可以指定参数和缺省值。这样我们就可以复用一些样式,只需要传递一个参数,就像调用一个函数一样!

  • 例子1: 没有默认值

    @mixin box-sizing ($sizing) {
        -webkit-box-sizing:$sizing;     
           -moz-box-sizing:$sizing;
                box-sizing:$sizing;
    }
    .box-border{
        border:1px solid #ccc;
        @include box-sizing(border-box);/*引用*/
    }
    

等同于css的写法

.box-border {
  border: 1px solid #ccc;
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}
  • 例子2:有默认值;没有默认值的参数要放在参数列表的前面。

    @mixin p2($val1, $val2:20px) {
    /* 如果不加入参数,就用默认参数 */
        float: $val1;
        top: $val2;
    }
    //使用的时候,根据需要加入参数:
    div {
        @include p2(left);
    }
    

等同于css的写法

div {
  float: left;
  top: 20px;
}

(6)导入文件

  • @import命令,用来插入外部文件。

  • 如果插入的是.css文件,则等同于css的import命令。

    @import "path/filename.scss";
    
    @import "foo.css";
    

(7)注释

SASS共有两种注释风格。

  • 标准的CSS注释 /* comment */ ,会保留到编译后的文件。
  • 单行注释 // comment,只保留在SASS源文件中,编译后被省略。