一、CSS基础

1.对盒模型的理解

CSS3中的盒模型有以下两种:标准盒子模型、IE盒子模型

前端面试题之CSS_前端

前端面试题之CSS_外边距_02

盒模型都是由四个部分组成的,分别是margin、border、padding和content。

标准盒模型和IE盒模型的区别在于设置width和height时,所对应的范围不同:

  • 标准盒模型的width和height属性的范围只包含了content,
  • IE盒模型的width和height属性的范围包含了border、padding和content。

可以通过修改元素的box-sizing属性来改变元素的盒模型:

  • box-sizing: content-box表示标准盒模型(默认值)
  • box-sizing: border-box表示IE盒模型(怪异盒模型)

2. 隐藏元素的方法有哪些

  • display:none:渲染树不会包含该渲染对象,因此该元素不会在页面中占据位置,也不会响应绑定的监听事件。
  • visibility: hidden:元素在页面中仍占据空间,但是不会响应绑定的监听事件。
  • opacity: 0:将元素的透明度设置为 0,以此来实现元素的隐藏。元素在页面中仍然占据空间,并且能够响应元素绑定的监听事件。
  • position: absolute:通过使用绝对定位将元素移除可视区域内,以此来实现元素的隐藏。
  • z-index: 负值:来使其他元素遮盖住该元素,以此来实现隐藏。
  • clip/clip-path :使用元素裁剪的方法来实现元素的隐藏,这种方法下,元素仍在页面中占据位置,但是不会响应绑定的监听事件。
  • transform: scale(0,0):将元素缩放为 0,来实现元素的隐藏。这种方法下,元素仍在页面中占据位置,但是不会响应绑定的监听事件

display:none与visibility:hidden的区别:

(1)在渲染树中

  • display:none会让元素完全从渲染树中消失,渲染时不会占据任何空间;
  • visibility:hidden不会让元素从渲染树中消失,渲染的元素还会占据相应的空间,只是内容不可见。

(2)是否是****继承属性

  • display:none是非继承属性,子孙节点会随着父节点从渲染树消失,通过修改子孙节点的属性也无法显示;
  • visibility:hidden是继承属性,子孙节点消失是由于继承了hidden,通过设置visibility:visible可以让子孙节点显示;

(3)修改常规文档流中元素的 display 通常会造成文档的重排,但是修改visibility属性只会造成本元素的重绘;

(4)如果使用读屏器,设置为display:none的内容不会被读取,设置为visibility:hidden的内容会被读取。

3.display:none与visibility:hidden的区别

这两个属性都是让元素隐藏,不可见。两者****区别如下:

(1)在渲染树中

  • display:none会让元素完全从渲染树中消失,渲染时不会占据任何空间;
  • visibility:hidden不会让元素从渲染树中消失,渲染的元素还会占据相应的空间,只是内容不可见。

(2)是否是****继承属性

  • display:none是非继承属性,子孙节点会随着父节点从渲染树消失,通过修改子孙节点的属性也无法显示;
  • visibility:hidden是继承属性,子孙节点消失是由于继承了hidden,通过设置visibility:visible可以让子孙节点显示;

(3)修改常规文档流中元素的 display 通常会造成文档的重排,但是修改visibility属性只会造成本元素的重绘;

(4)如果使用读屏器,设置为display:none的内容不会被读取,设置为visibility:hidden的内容会被读取。

4. z-index属性在什么情况下会失效

通常 z-index 的使用是在有两个重叠的标签,在一定的情况下控制其中一个在另一个的上方或者下方出现。z-index值越大就越是在上层。z-index元素的position属性需要是relative,absolute或是fixed。

z-index属性失效:

元素没有设置position属性为非static属性。解决:设置该元素的position属性为relative,absolute或是fixed中的一种

5. CSS3的新特性
  • 新增各种CSS选择器 (: not(.input):所有 class 不是“input”的节点)
  • 圆角 (border-radius:8px)
  • 多列布局 (multi-column layout)
  • 阴影和反射 (Shadoweflect)
  • 文字特效 (text-shadow)
  • 文字渲染 (Text-decoration)
  • 线性渐变 (gradient)
  • 旋转 (transform)
  • 增加了旋转,缩放,定位,倾斜,动画,多背景

二、页面布局

1.三列布局

三栏布局一般指的是页面中一共有三栏,左右两栏宽度固定,中间自适应的布局,三栏布局的具体实现:

  • 利用绝对定位,左右两栏设置为绝对定位,中间设置对应方向大小的margin的值。
.container {
    position: relative;
    height: 100px;
}
.left {
    position: absolute;
    width: 100px;
    height: 100px;
    background: #f00;
}
.right {
    position: absolute;
    top: 0;
    right: 0;
    width: 200px;
    height: 100px;
    background: #0f0;
}
.center {
    margin-left: 100px;
    margin-right: 200px;
    height: 100px;
    background: #ff0;
}
  • 利用flex布局,左右两栏设置固定大小,中间一栏设置为flex:1
.container {
    display: flex;
    height: 100px;
}

.left {
    width: 100px;
    background: #f00;
}

.right {
    width: 200px;
    background: #0f0;
}

.center {
    flex: 1;
    background: #ff0;
}
  • 利用浮动,左右两栏设置固定大小,并设置对应方向的浮动。中间一栏设置左右两个方向的margin值,注意这种方式**,中间一栏必须放到最后:**
.container {
    height: 100px;
}

.left {
    float: left;
    width: 100px;
    height: 100px;
    background: #f00;
}

.right {
    float: right;
    width: 200px;
    height: 100px;
    background: #0f0;
}

.center {
    height: 100px;
    margin-left: 100px;
    margin-right: 200px;
    background: #ff0;
}
  • 圣杯布局,利用浮动和负边距来实现。父级元素设置左右的 padding,三列均设置向左浮动,中间一列放在最前面,宽度设置为父级元素的宽度,因此后面两列都被挤到了下一行,通过设置 margin 负值将其移动到上一行,再利用相对定位,定位到两边。
<style>
        .container {
            height: 100px;
            padding-left: 100px;
            padding-right: 200px;
        }

        .left {
            position: relative;
            left: -100px;
            float: left;
            margin-left: -100%;
            width: 100px;
            height: 100px;
            background: #f00;
        }

        .right {
            position: relative;
            left: 200px;

            float: right;
            margin-left: -200px;

            width: 200px;
            height: 100px;
            background: #0f0;
        }

        .center {
            float: left;
            width: 100%;
            height: 100px;
            background: #ff0;
        }
    </style>
    <div class="container">
        <div class="center"></div>
        <div class="left"></div>
        <div class="right"></div>
    </div>
  • 双飞翼布局,双飞翼布局相对于圣杯布局来说,左右位置的保留是通过中间列的 margin 值来实现的,而不是通过父元素的 padding 来实现的。本质上来说,也是通过浮动和外边距负值来实现的
<style>
        .left,
        .right {
            width: 200px;
            height: 200px;
            background: pink;
            float: left;
        }

        .content {
            height: 200px;
            background: rgb(45, 173, 75);
            float: left;
            width: 100%;
        }

        .ineer {
            margin: 0 200px;
            height: 200px;
        }

        .left {
            margin-left: -100%;
        }

        .right {
            margin-left: -200px;
        }
    </style>

    <div class="wrap">
        <div class="content">
            <div class="ineer">content</div>
        </div>
        <div class="left"></div>
        <div class="right"></div>
    </div>

2.flex:1表示什么

flex属性是flex-grow,flex-shrink和flex-basis的简写,默认值为0 1 auto。flex:1 表示 flex: 1 1 0%****:

  • 第一个参数表示: flex-grow 定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大;
  • 第二个参数表示: flex-shrink 定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小;
  • 第三个参数表示: flex-basis给上面两个属性分配多余空间之前, 计算项目是否有多余空间, 默认值为 auto, 即项目本身的大小。

三、定位与浮动

1.什么是margin重叠问题?如何解决?

两个块级元素的上外边距和下外边距可能会合并(折叠)为一个外边距,其大小会取其中外边距值大的那个,这种行为就是外边距折叠。需要注意的是,浮动的元素和绝对定位这种脱离文档流的元素的外边距不会折叠。重叠只会出现在垂直方向

计算原则:

折叠合并后外边距的计算原则如下:

  • 如果两者都是正数,那么就取最大者
  • 如果是一正一负,就会正值减去负值的绝对值
  • 两个都是负值时,用0减去两个中绝对值大的那个

解决方法:

对于折叠的情况,主要有两种:兄弟之间重叠和父子之间重叠

(1)兄弟之间重叠

  • 底部元素变为行内盒子:display: inline-block
  • 底部元素设置浮动:float
  • 底部元素的position的值为absolute/fixed

(2)父子之间重叠

  • 父元素加入:overflow: hidden
  • 父元素添加透明边框:border:1px solid transparent
  • 子元素变为行内盒子:display: inline-block
  • 子元素加入浮动属性或定位

四、场景应用

1.怎么画一条0.5px的线

  • 采用transform: scale()的方式,该方法用来定义元素的2D 缩放转换:
transform: scale(0.5,0.5);
  • 采用meta viewport的方式
<meta name="viewport" content="width=device-width, initial-scale=0.5, minimum-scale=0.5, maximum-scale=0.5"/>

2.如何解决1px问题

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

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

解决方案:

1.对iOS统给出的方案
border:0.5px solid #E5E5E5

总结:

  • 优点:简单,没有副作用
  • 缺点:支持iOS 8+,不支持安卓
2.使用边框图片
border: 1px solid transparent;
  border-image: url('./../../image/96.jpg') 2 repeat;

总结:

  • 优点:没有副作用
  • 缺点:order颜色变了就得重新制作图片;圆角会比较模糊
3.使用box-shadow实现
box-shadow: 0  -1px 1px -1px #e5e5e5,   //上边线
            1px  0  1px -1px #e5e5e5,   //右边线
            0  1px  1px -1px #e5e5e5,   //下边线
            -1px 0  1px -1px #e5e5e5;   //左边线
4.使用伪元素先放大后缩小

1条border

.setOnePx{
  position: relative;
  &::after{
    position: absolute;
    content: '';
    background-color: #e5e5e5;
    display: block;
    width: 100%;
    height: 1px; /*no*/
    transform: scale(1, 0.5);
    top: 0;
    left: 0;
  }
}

4条border

.setBorderAll{
    position: relative;
    &:after{
        content:" ";
        position:absolute;
        top: 0;
        left: 0;
        width: 200%;
        height: 200%;
        transform: scale(0.5);
        transform-origin: left top;
        box-sizing: border-box;
        border: 1px solid #E5E5E5;
        border-radius: 4px;
      }
}
  • 优点:全机型兼容,实现了真正的1px,而且可以圆角
  • 缺点:暂用了after 伪元素,可能影响清除浮动
5.设置viewport的scale值
<html>

<head>
    <title>1px question</title>
    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
    <meta name="viewport" id="WebViewport"
        content="initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
    <style>
        html {
            font-size: 1px;
        }

        * {
            padding: 0;
            margin: 0;
        }

        .top_b {
            border-bottom: 1px solid #E5E5E5;
        }

        .a,
        .b {
            box-sizing: border-box;
            margin-top: 1rem;
            padding: 1rem;
            font-size: 1.4rem;
        }

        .a {
            width: 100%;
        }

        .b {
            background: #f5f5f5;
            width: 100%;
        }
    </style>
    <script>
        var viewport = document.querySelector("meta[name=viewport]");
        //下面是根据设备像素设置viewport
        if (window.devicePixelRatio == 1) {
            viewport.setAttribute('content',
                'width=device-width,initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no');
        }
        if (window.devicePixelRatio == 2) {
            viewport.setAttribute('content',
                'width=device-width,initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no');
        }
        if (window.devicePixelRatio == 3) {
            viewport.setAttribute('content',
                'width=device-width,initial-scale=0.3333333333333333, maximum-scale=0.3333333333333333, minimum-scale=0.3333333333333333, user-scalable=no'
                );
        }
        var docEl = document.documentElement;
        var fontsize = 32 * (docEl.clientWidth / 750) + 'px';
        docEl.style.fontSize = fontsize;
    </script>
</head>

<body>
    <div class="top_b a">下面的底边宽度是虚拟1像素的</div>
    <div class="b">上面的边框宽度是虚拟1像素的</div>
</body>

</html>