前端面试总结-CSS

722 阅读12分钟

CSS

BFC

  • 定义:块级格式化上下文,它是指一个独立的块级渲染区域,只有Block-level BOX参与,该区域拥有一套渲染规则来约束块级盒子的布局,且与区域外部无关

    从一个现象说起

    一个盒子father没有设置height,其内容子元素son都为浮动的时候,无法撑起自身,即father的height一直为0,这个盒子没有形成BFC

  • 如何创建BFC

    • float的值不为none
    • position的值不是static或者relative
    • display的值是inline-block、flex或者inline-flex
    • overflow:hidden(比较好的方式,不会影响到外部的布局)
  • BFC的其他作用

    • 可以取消margin塌陷的问题
    • 可以阻止元素被浮动元素覆盖

    CSS盒模型

CSS盒模型本质上是一个盒子,封装周围的HTML元素,它包括:边距,边框,填充,和实际内容。

标准盒模型:一个块的总宽度=width+margin(左右)+padding(左右)+border(左右)

怪异盒模型:一个块的总宽度=width+margin(左右)(既width已经包含了padding和border值)

设置盒模型:box-sizing:border-box

CSS选择器优先级

样式的引用方式对css优先级的影响:

行内样式(写在标签的style属性中) > 内部样式表(写在头部的style标签中) > 外部样式表(通过link标签引用css文件)

但是有!important的样式除外

选择器对css样式优先级的影响:

!important > id选择器 > 类选择器 = 属性选择器 = 伪类选择器 > 标签选择器 > 通配选择符 = 关系选择符

垂直居中的写法

1 flex

.parent{
    width:400px;
    height:400px;
    display:flex;
    align-items:center
}
.son{
    width:200px;
    height:200px;
}

2 margin自适应

.parent{
    width:400px;
    height:400px;
    position:relative
}
.son{
    width:200px;
    height:200px;
    position:absolute;
    top:0;
    bottom:0;
    margin:auto
}

3 margin负值

.parent{
    width:400px;
    height:400px;
    position:relative
}
.son{
    width:200px;
    height:200px;
    position:absolute;
    top:50%;
    margin-top:-100px      /*自身高度一半*/
}

4 父元素设置display:table-cell

.parent{
    width:400px;
    height:400px;
    display:table-cell;
    vertical-align:middle
}
.son{
    width:200px;
    height:200px;
}

5 absolute+transform

.parent{
            width: 400px;
            height: 400px;
            background-color: cornflowerblue;
            position: relative;
            margin: 100px auto;
        }
        .child{
            width: 100px;
            height: 100px;
            background-color: darkgreen;
            position: absolute;
            top: 50%;
            transform: translateY(-50%);
        }

清除浮动

首先来看看浮动会产生哪些问题,当父容器未设置高度,且子元素设置为了浮动,那么子元素的高度可能会超过父元素,进而影响其他布局,来看个例子:左边是未清除浮动,子元素已经跑到父元素的兄弟元素上去了,后面是清除了浮动,父元素能够实现自适应高度,让子元素一直保持在父元素内部

image.png

清除浮动的方法

1.我们可以在浮动元素尾部加上一个标签,标签加上clear类,clear类设置为clear:both

.clear{
    clear:both
}

2.可以在父元素上加上overflow:hidden/auto

.container{
    overflow:hidden
}

当元素设置了overflow样式且值部位visible时,该元素就构建了一个BFC,BFC在计算高度时,内部浮动元素的高度也要计算在内,也就是说技术BFC区域内只有一个浮动元素,BFC的高度也不会发生塌缩,所以达到了清除浮动的目的,

3.兼容性最好的,after伪元素

为父元素添加一个clearfix类

 .clearfix::after{
            content:'';
            display: block;
            height: 0;
            clear: both;
            visibility: hidden;
            
        }

4.可以给容器parent添加浮动属性(不推荐,容易改变整体布局)

flex布局

flex-direction:决定主轴的方向(即子item的排列方法) .box { flex-direction: row | row-reverse | column | column-reverse; }

flex-wrap:决定换行规则 .box{ flex-wrap: nowrap | wrap | wrap-reverse; }

flex-flow: .box { flex-flow: || ; }

justify-content:对其方式,水平主轴对齐方式

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

三栏布局

两侧定宽,中间自适应

1.采用浮动加margin的方式,注意:这里html标签顺序有影响,必须先放left和right最后放middle

<div class="left"></div>
<div class="right"></div>
<div class="middle"></div>
*{
            padding: 0;
            margin: 0;
            box-sizing: border-box;
        }
        .left{
            width: 200px;
            float: left;
            height: 100vh;
            background-color: lightblue;
        }
        .right{
            width: 200px;
            float: right;
            height: 100vh;
            background-color: lightblue;
​
        }
        .middle{
            margin: 0 200px ;
            height: 100vh;
            background-color: lightgreen;
        }

2.position

<div class="left"></div>
<div class="middle"></div>
<div class="right"></div>
 *{
            padding: 0;
            margin: 0;
            box-sizing: border-box;
        }
        .left,.middle,.right{
            position: absolute;
            height: 100vh;
        }
        .left,.right{
            width: 200px;
            
            background-color: lightskyblue;
        }
        .left{
            left: 0;
        }
        .right{
            right: 0;
        }
        .middle{
            left: 200px;
            right: 200px;
            background-color: lightgreen;
        }

3.flex

<div class="container">
        <div class="left"></div>
        <div class="middle"></div>
        <div class="right"></div>
    </div>
 *{
            padding: 0;
            margin: 0;
            box-sizing: border-box;
        }
        .container{
            width: 100%;
            height: 100vh;
            display: flex;
            /* justify-content: space-between; */
        }
        .left,.right{
            width: 200px;
            background-color: lightblue;
        }
        .middle{
            flex:1;
            background-color: lightgreen;
        }

vm和vh

1vh等于viewport高度1/100,100vh即当前视口大小高度,1vw表示视口宽度的1/100,100vw即等于当前视口宽度100%

em布局和rem布局

em是根据自身fontsize进行计算

rem是根据html根节点的fontsize来进行计算

冒泡与捕获

 div1.addEventListener('click',function(){console.log('div1')})//true为捕获,false为冒泡,默认为冒泡
 div2.addEventListener('click',function(){console.log('div2')})
 div3.addEventListener('click',function(){console.log('div3')})

image.png

当我们点击div3的时候,会依次输出div3,div2,div1,默认为冒泡

我们将addEventListener的第三个参数换成true,改为捕获,会依次输出div1,div2,div3

如何阻止冒泡喃

div1.addEventListener('click',function(e){
     e.stopPropagation()
     console.log('div1')
})
div2.addEventListener('click',function(e){
     e.stopPropagation()
     console.log('div2')
})
div3.addEventListener('click',function(e){
     e.stopPropagation()
     console.log('div3')
})

这样就能阻止冒泡了,但是如果此时我们将参数设置为true,那么我们点击什么都是打印的div1

事件委托

所谓事件委托,就是不把事件绑定在元素本身,而是绑定在其父元素上,通过冒泡获取元素,比如一个ul里面有很多li,我们想实现点击一个li,打印一下这个 li的内容,传统做法是给每一个li绑定一个事件,这样太过于繁琐,而且会有很多函数驻留在内存中,占用内存,事件委托方法。同时也适合动态添加元素,比如我们在ul中又动态添加了li,我们就不需要再给其添加和之前一样类似的函数了,通过事件委托,被创建之后就具有点击事件了

var ul = document.querySelector('ul')
       ul.addEventListener('click',function(e){
           console.log(e.target.innerHTML)
       })

e.target就是通过冒泡返回的点击源,点击li则e.target为li

js如何获取盒模型的宽和高

假设已经获取了DOM

//只能获取使用内联样式的元素的宽和高
dom.style.width/height
//这种方法获取的是浏览器渲染以后的元素的宽和高,这种写法兼容性更好一些。
window.getComputedStyle(dom).width/height
//这种方法获取的是浏览器渲染以后的元素的宽和高,无论是用何种方式引入的css样式都可以,但只有IE浏览器支持这种写法。
dom.currentStyle.width/height
//这种方式获得到的宽度是内容content+padding+border
//此 api 的作用是:获取一个元素的绝对位置。绝对位置是视窗 viewport 左上角的绝对位置。
//此 api 可以拿到六个属性:left、top、right、bottom、width、height。
dom.getBoundingClientRect().width/height

画一条0.5px的线

  • 采用meta viewport的方式(viewport只针对移动端,只在移动端上才能看到效果)

    <meta name="viewport" content="width=device-width, initial-scale=0.5, minimum-scale=0.5, maximum-scale=0.5"/>

  • 采用transform: scale()的方式

      .line1{
                width: 300px;
                height: 1px;
                margin-top: 100px;
                background-color: cornflowerblue;
                transform:scaleY(0.5);
            }
    

link标签和import标签的区别

link标签属于HTML标签,而@import是css提供的

页面被加载的时候,link会同时被加载,而@import引用的css会等到页面加载结束之后才会加载

link是html标签,因此没有兼容性,而@import只有IE5以上才会识别

link方式样式的权重高于@import的

@import url('路径')

原生JS实现拖拽功能

html

<div>点击拖拽</div>

css,注意:一定要将定位设置为absolute

div{
            width: 50px;
            height: 50px;
            background-color: lightseagreen;
            position: absolute;
        }

js

var div = document.querySelector('div')
      var isDrag=false
      div.addEventListener('mousedown',function(){
          isDrag=true
      })
      div.addEventListener('mouseup',function(){
          isDrag=false
      })
      window.addEventListener('mousemove',function(e){
          if(isDrag){
              console.log(e.clientX)
              div.style.left=(e.clientX-div.clientWidth/2)+'px'
              div.style.top=(e.clientY-div.clientHeight/2)+'px'
          }
      })

CSS3新增内容

  • CSS3边框:border-radius、box-shadow、border-image
  • CSS3背景:background-size、background-origin(规定背景图片定位区域)
  • CSS3文字效果:text-shadow、word-wrap(对长单词进行拆分并换行)
  • CSS3 2D转换:transform: translate()、rotate()、scale()
  • CSS3 3D转换:transform: rotateX()、rotateY()
  • CSS3 过渡:transition
  • CSS3 动画:animation
  • CSS3用户界面:resize(是否可由用户调整元素尺寸)、box-sizing(定义盒模型)

calc属性

calc用户动态计算长度值,任何长度值都可以使用calc()函数计算,需要注意的是,运算符前后都需要保留一个空格,例如:width: calc(100% - 10px);

css动画如何实现

创建动画序列,需要使用animation属性或其子属性,该属性允许配置动画时间、时长以及其他动画细节,但该属性不能配置动画的实际表现,动画的实际表现是由 @keyframes规则实现。

transition也可实现动画。transition强调过渡,元素的一个或多个属性发生变化时产生的过渡效果。

transition和animation的区别

1、transition 是过渡,是样式值的变化的过程,只有开始和结束;animation 其实也叫关键帧,通过和 keyframe 结合可以设置中间帧的一个状态;

 2、animation 配合 @keyframe 可以不触发时间就触发这个过程,而 transition 需要通过 hover 或者 js 事件来配合触发;

 3、animation 可以设置很多的属性,比如循环次数,动画结束的状态等等,transition 只能触发一次;

 4、animation 可以结合 keyframe 设置每一帧,但是 transition 只有两帧;

 5、在性能方面:浏览器有一个主线程和排版线程;主线程一般是对 js 运行的、页面布局、生成位图等等,然后把生成好的位图传递给排版线程,而排版线程会通过 GPU 将位图绘制到页面上,也会向主线程请求位图等等;我们在用使用 aniamtion 的时候这样就可以改变很多属性,像我们改变了 width、height、postion 等等这些改变文档流的属性的时候就会引起,页面的回流和重绘,对性能影响就比较大,但是我们用 transition 的时候一般会结合 tansfrom 来进行旋转和缩放等不会生成新的位图,当然也就不会引起页面的重排了;

关于js动画和css3动画的差异性

功能涵盖面,js比css大,复杂;js在主线程中运行,容易丢帧;js灵活,兼容性好;

实现/重构难度不一,CSS3比js更加简单, 性能跳优方向固定

对帧速表现不好的低版本浏览器,css3可以做到自然降级

css动画有天然事件支持;浏览器可以对css动画进行优化

css有兼容性问题,笨重,代码冗长;强制gpu加速

css比js动画流畅的原理是因为在复合线程中进行动画处理,所以节省了昂贵的主线程资源

隐藏页面中某个元素的方法

opacity=0;visibility=hidden;display:none;position移到外部;z-index图层遮盖

visibility=hidden,opacity=0,display:none区别

  • opacity=0,元素透明度为0,被隐藏,但是不改变页面布局,点击这个元素相应部分,绑定在这个元素上面的事件仍然能够触发
  • visibility=hideen,隐藏元素,不会改变布局,仍然存在于原来非透明的时候那个位置,但是绑定的事件不会触发
  • display=none,元素不显示,且会改变布局,可以理解为暂时将元素从页面中删除了

子元素继承

display:none不会被子元素继承,但是父元素都不在了,子元素自然也就不会显示了,皮之不存,毛之安附~~

visibility:hidden 会被子元素继承,可以通过设置子元素visibility:visible 使子元素显示出来(显示出来之后子元素dom事件可用)

opacity: 0 也会被子元素继承,但是不能通过设置子元素opacity: 1使其重新显示

inline-block、inline和block的区别

  • block:块级元素,前后都有换行符,可设置width和height,padding margin垂直水平方向均有效
  • inline:内联元素,前后无换行符,无法设置宽高,垂直方向的padding和margin无效
  • inline-block:内联块级元素(行内块元素),前后无换行符,可以设置宽高,水平垂直方向的padding和margin均有效

为什么img是inline还可以设置宽高

img属于替换元素,替换元素一般有内在尺寸和宽高比,所以具有width和height,所以可以设置宽高

HTML中替换元素:input img textarea select

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

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

折叠的结果为:

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

css画三角形

.triangle-up {
    width: 0;
    height: 0;
    border-left: 50px solid transparent;
    border-right: 50px solid transparent;
    border-bottom: 100px solid red;
}

CSS+JS写时钟

核心是transform:rotate()和定时器

旋转中心设置:transform-origin:left

表盘刻度可以通过背景图来实现

    <style>
        *{
            padding: 0;
            margin: 0;
            box-sizing: border-box;
        }
     .container{
         width: 400px;
         height: 400px;
         margin: 100px auto;
         background-color: lightskyblue;
         border-radius: 200px;
         position: relative;
     }
     .hour{
         height: 2px;
         width: 100px;
         background-color: red;
         position: absolute;
         top: 50%;
         margin-top: -1px;
         left: 50%;
         transform-origin: left;
     }
     .minute{
        height: 2px;
         width: 120px;
         background-color: green;
         position: absolute;
         top: 50%;
         margin-top: -1px;
         left: 50%;
         transform-origin: left;
     }
     .second{
        height: 2px;
         width: 160px;
         background-color: beige;
         position: absolute;
         top: 50%;
         margin-top: -1px;
         left: 50%;
         transform-origin: left;
     }
       
    </style>
    
</head>
<body><div class="container">
    <div class="hour"></div>
    <div class="minute"></div>
    <div class="second"></div>
</div>
   
<script>
var hour = document.querySelector('.hour')
var minute = document.querySelector('.minute')
var second = document.querySelector('.second')
let h=0
let m=0
let s=0
setInterval(() => {
    s=s+6
    second.style.transform=`rotate(${s}deg)`
    if(s%360==0){
        m=m+6
        minute.style.transform=`rotate(${m}deg)`
    }
    if(m%360==0&&m!=0){
        h=h+6
        hour.style.transform=`rotate(${h}deg)`
    }
}, 1000);

CSS+animation实现硬币动画

  <style>
        *{
            padding: 0;
            margin: 0;
            box-sizing: border-box;
        }
        .coin{
            width: 100px;
            height: 100px;
            border-radius: 50%;
            background-color: cornflowerblue;
            margin: 100px auto;
            animation: rotate 5s linear infinite;
        }
        .coin:hover{
            animation-play-state: paused;
        }
        @keyframes rotate {
           0%{
               transform:rotateY(0deg)
           }
           100%{
               transform:rotateY(360deg)
           }
        }
       
    </style>
<div class="coin"></div>

CSS预处理

scss

定义变量

//定义颜色
$colors:(
    "primary":#db9e3f,
    "info":#4b67af,
    'blue-2':#00ADFF,
    "white":#fff,//当命名与内置属性冲突的时候用引号将其包裹
    "light":#f9f9f9,   
);
//字体大小
$base-font-size:1rem;
$font-sizes:(
    xxs:0.6154,//8px
    xs:0.7692,//10px
    sm:0.9231,//12px
    md:1,//13px
    lg:1.0769,//14px
    xl:1.2308,//16px
);
//布局
$flex-jc:(
    start:flex-start,
    end:flex-end,
    center:center,
    between:space-between,
    around:space-around,
    
);
$flex-ai:(
    start:flex-start,
    end:flex-end,
    center:center,
    // between:space-between,
    // around:space-around,
    stretch:stretch,
);

生成工具类

@each $colorKey,$color in $colors{
    .text-#{$colorKey}{
        color:$color
    }
    .bg-#{$colorKey}{
        background-color:$color;
    }
}
//text
@each $var in (left,center,right){
    .text-#{$var}{
        text-align: $var !important;
    }
}
@each $key,$value in $flex-jc{
    .jc-#{$key}{
        justify-content: $value;
    }
}