1. CSS3 中新增了哪些新特性?

答:一些选择器、边框(border-radius, border-image)、box-shadow、背景(background-origin``、``background-size 等)、文字(word-wrap, text-overflow, text-shadow)、颜色(rgba, hsla)、transition 过渡、transform 转换(scale 缩放,translate 平移,rotate 旋转,skew 切斜)、animation 动画、渐变(linear-gradient线性渐变和 radial-gradient 径向渐变)、Flex 布局、Grid 栅格布局、多列布局、媒体查询等等

2. CSS3 画一个三角形,其原理是什么?

我们有时候会需要用到一个三角形的形状,比如地址选择或者播放器里面播放按钮,通常情况下,我们会使用图片或者 svg 去完成三角形效果图

  • 实心三角形

    .border: {
      width: 0;
      height: 0;
      border-style: solid;
      border-width: 0 50px 50px;
      border-color: transparent transparent red;
    }
    

    这时候就已经能够看到 4 个不同颜色的三角形,如果需要下方三角形,只需要将上、左、右边框设置为透明就可以得到下方的红色三角形. 但这种方式,虽然视觉上是实现了三角形,但实际上,隐藏的部分任然占据部分高度,需要将上方的宽度去掉

  • 空心三角形(利用伪类)

    伪类元素定位参照对象的内容区域宽高都为 0,则内容区域即可以理解成中心一点,所以伪元素相对中心这点定位

    .border {
      width: 0;
      height: 0;
      border-style: solid;
      border-width: 0 50px 50px;
      border-color: transparent transparent #d9534f;
      position: relative;
    }
    .border:after {
      content: '';
      border-style: solid;
      border-width: 0 40px 40px;
      border-color: transparent transparent #96ceb4;
      position: absolute;
      top: 6px;
      left: -40px;
    }
    

  • 原理分析 采用的是均分原理:非常有意思的是盒子都是一个矩形或正方形,从形状的中心,向 4 个角上下左右划分 4 个部分

    .square {
      width: 0;
      height: 0;
      margin: 0 auto;
      border-width: 6px;
      border-color: red transparent transparent transparent;
      border-style: solid dashed dashed dashed; // 为了兼容IE6,把没有的边框都设置为虚线
    }
    

    边框是实现三角形的部分,边框实际上并不是一个直线,如果我们将四条边设置不同的颜色,将边框逐渐放大,可以得到每条边框都是一个梯形.当分别取消边框的时候,发现下面几种情况:

    1. 取消一条边的时候,与这条边相邻的两条边的接触部分会变成直的
    2. 当仅有邻边时, 两个边会变成对分的三角
    3. 当保留边没有其他接触时,极限情况所有东西都会消失
  • 通过上图的变化规则,利用旋转、隐藏,以及设置内容宽高等属性,就能够实现其他类型的三角形

/* 如设置直角三角形  */
.box {
  /* 内部大小 */
  width: 0px;
  height: 0px;
  /* 边框大小 只设置两条边*/
  border-top: #4285f4 solid;
  border-right: transparent solid;
  border-width: 85px;
  /* 其他设置 */
  margin: 50px;
}

3. 获取元素的宽高的方式有哪些?

  1. dom.style.width/height

    原理:这种方式只能取到 dom 元素内联样式所设置的宽高;(也就是说如果该节点的样式是在 style 标签中或外联的 CSS 文件中设置的话,通过这种方法是获取不到 dom 的宽高的)

  2. dom.currentStyle.width/height

    原理:获取渲染后的宽高。(但仅 IE 支持)

  3. dom.getComputedStyle(dom).width/height

    原理:与 2 原理类似。但是兼容性,通用性更好一些

  4. dom.getBoundingClientRect().width/height

    原理:计算元素的绝对位置,获取到四个属性,left, top, right, bottom

4. 说说你对 盒子模型 的理解?

CSS3 中的盒模型有以下两种:标准盒模型、IE(怪异替代)盒模型。

两种盒子模型都是由 content + padding + border + margin 构成,其大小都是由 content + padding + border 决定的,但是盒子内容宽/高度(即 width/height)的计算范围根据盒模型的不同会有所不同:

  • 标准盒模型:只包含 content
  • IE(替代)盒模型:content + padding + border

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

  • box-sizing: content-box :标准盒模型(默认值)
  • box-sizing: border-box :IE(替代)盒模型

5. CSS 中选择器有哪些?优先级?哪些属性可以继承?

样式的优先级一般为 !important > style > id > class > 标签选择器

  • 优先级:

    1. !important
    2. 内联样式(1000)
    3. ID 选择器(0100)
    4. 类选择器/属性选择器/伪类选择器(0010)
    5. 元素选择器/伪元素选择器(0001)
    6. 关系选择器/通配符选择器(0000)

    总结:带!important 标记的样式属性优先级最高; 样式表的来源相同时:!important > 行内样式>ID 选择器 > 类选择器 > 标签 > 通配符 > 继承 > 浏览器默认属性

  • css 属性选择器常用的有:

    1. id 选择器(#box),选择 id 为 box 的元素
    2. 类选择器(.one),选择类名为 one 的所有元素
    3. 标签选择器(div),选择标签为 div 的所有元素
    4. 后代选择器(#box div),选择 id 为 box 元素内部所有的 div 元素
    5. 子选择器(.one>one_1),选择父元素为.one 的所有.one_1 的元素
    6. 相邻同胞选择器(.one+.two),选择紧接在.one 之后的所有.two 元素
    7. 群组选择器(div,p),选择 div、p 的所有元素
    8. 通配符选择器(*)
  • 一些使用频率相对不是很多的选择器:

    1. 伪类选择器(:link, :visited, :active, :hover)
    2. 伪元素选择器(:after, :before)
    3. 属性选择器([attribute], [attribute=value])
  • CSS3 中新增的选择器:

    1. 伪类选择器(:nth-child(n), :not, :last-child)
    2. 属性选择器([attribute^=value])
  • 优先级是由 A 、B、C、D 的值来决定的,其中它们的值计算规则如下:

    1. 如果存在内联样式,那么 A = 1,否则 A = 0
    2. B 的值等于 ID 选择器(#id) 出现的次数
    3. C 的值等于 类选择器(.class) 和 属性选择器(a[href="https://example.org"]) 和 伪类(:first-child) 出现的总次数
    4. D 的值等于 标签选择器(h1,a,div) 和 伪元素(::before,::after) 出现的总次数

知道了优先级是如何计算之后,就来看看比较规则:

  1. 从左往右依次进行比较 ,较大者优先级更高
  2. 如果相等,则继续往右移动一位进行比较
  3. 如果 4 位全部相等,则后面的会覆盖前面的
  • CSS 属性继承 在 css 中,继承是指的是给父元素设置一些属性,后代元素会自动拥有这些属性

    • 关于继承属性,可以分成:
    1. 字体系列属性

    2. 文本系列属性

    3. 元素可见性

    4. 表格布局属性

      注意:继承中比较特殊的几点:

      1. a 标签的字体颜色不能被继承
      2. h1-h6 标签字体的大小也是不能被继承的
    • 无继承的属性:
      1. display
      2. 文本属性:vertical-align、text-decoration
      3. 盒子模型的属性:宽度、高度、内外边距、边框等
      4. 背景属性:背景图片、颜色、位置等
      5. 定位属性:浮动、清除浮动、定位 position 等
      6. 生成内容属性:content、counter-reset、counter-increment
      7. 页面样式属性:size、page-break-before、page-break-after

扩展:CSS 伪类用于向某些选择器添加特殊的效果。CSS 伪元素用于向某些选择器设置特殊效果。

6. display 和 position 有哪些值?

  • display 的值:none、inline、inline-block、block、table、flex
  • position 的值:static、relative、absolute、fixed、inherit、sticky
    1. static(没有定位)是 position 的默认值,元素处于正常的文档流中,会忽略 left、top、right、bottom 和 z-index 属性。
    2. relative(相对定位)是指给元素设置相对于原本位置的定位,元素并不脱离文档流,因此元素原本的位置会被保留,其他的元素位置不会受到影响。
    3. absolute(绝对定位)是指给元素设置绝对的定位,相对定位的对象可以分为两种情况:
      1. 设置了 absolute 的元素如果存在有祖先元素设置了 position 属性为 relative 或者 absolute,则这时元素的定位对象为此已设置 position 属性的祖先元素。
      2. 如果并没有设置了 position 属性的祖先元素,则此时相对于 body 进行定位。
    4. fixed 可以简单说 fixed 是特殊版的 absolute,fixed 元素总是相对于 body 定位的。
    5. inherit 继承父元素的 position 属性,但需要注意的是 IE8 以及往前的版本都不支持 inherit 属性。

扩展补充display: nonevisibility: hiddenopacity: 0 之间的区别?

  • 相同点:都是隐藏
  • 不同点
    1. 是否占据空间
      • display: none, 隐藏之后 不占 据空间
      • visibility: hiddenopacity: 0 隐藏后任然 占据 空间
    2. 子元素是否继承
      • display: none, 不会被子元素继承,父元素都不存在了,子元素也不会显示
      • visibility: hidden, 会被子元素继承,通过设置子元素,visibility: visible 来显示子元素
      • opacity: 0, 会被子元素继承,但是不能设置子元素 opacity 来重新显示
    3. 事件绑定
      • display: none, 元素都不在了,所以无法触发它绑定的事件
      • visibility: hidden, 不会触发它上面绑定的事件
      • opacity: 0, 元素上面绑定的事件是可以触发的
    4. 过渡动画
      • transition: 对于 display无效的
      • transition: 对于 visibility无效的
      • transition: 对于 opacity 是 有效的

7. 清除浮动的方式有哪些?

  • 方式一、添加额外标签,使用 clear:both;清除浮动
    <div class="parent">
      <!-- 添加额外标签并且添加clear属性 -->
      <div style="clear:both"></div>
      <!-- 也可以加一个br标签 -->
    </div>
    
  • 方式二、利用伪元素:after 来清除浮动
    // 在css中添加:after伪元素
    .parent:after {
      /* 设置添加子元素的内容是空 */
      content: '';
      /* 设置添加子元素为块级元素 */
      display: block;
      /* 设置添加的子元素的高度0 */
      height: 0;
      /* 设置添加子元素看不见 */
      visibility: hidden;
      /* 设置clear:both */
      clear: both;
    }
    
  • 方式三、使用 CSS 的 overflow 属性(BFC)

8. 说说重绘 & 重排?

简单地总结下两者的概念:

  • 重排:无论通过什么方式影响了元素的几何信息(元素在视口内的位置和尺寸大小),浏览器需要重新计算元素在视口内的几何属性,这个过程叫做重排
  • 重绘:通过构造渲染树和重排(回流)阶段,我们知道了哪些节点是可见的,以及可见节点的样式和具体的几何信息(元素在视口内的位置和尺寸大小),接下来就可以将渲染树的每个节点都转换为屏幕上的实际像素,这个阶段就叫做重绘

如何减少重排和重绘?

  1. 最小化重绘和重排,比如样式集中改变,使用添加新样式类名 .class 或 cssText
  2. 批量操作 DOM,比如读取某元素 offsetWidth 属性存到一个临时变量,再去使用,而不是频繁使用这个计算属性;又比如利用 document.createDocumentFragment() 来添加要被添加的节点,处理完之后再插入到实际 DOM 中
  3. 使用 absolutefixed 使元素脱离文档流,这在制作复杂的动画时对性能的影响比较明显
  4. 开启 GPU 加速,利用 css 属性 transform 、will-change 等,比如改变元素位置,我们使用 translate 会比使用绝对定位改变其 left 、top 等来的高效,因为它不会触发重排或重绘,transform 使浏览器为元素创建⼀个 GPU 图层,这使得动画元素在一个独立的层中进行渲染。当元素的内容没有发生改变,就没有必要进行重绘

扩展transform 会造成回流吗? 渲染流水线是这样的顺序:重排 -> 重绘 -> 合成transform: translate 是直接合成,跳过了前面的重排重绘。但是 限制高宽也会出现问题,譬如图片被拉伸了。

-> 给 <img/> 标签写上宽高,可以在图片未加载之前提前占住位置,避免图片从未加载状态到渲染完成状态高宽变化引起的 重排 问题。object-fit: cover,它能够指定可替换元素的内容(也就是图片)该如何适应它的父容器的高宽。object-fit 还有一个配套属性 object-position,它可以控制图片在其内容框中的位置。(类似于 background-position),m 默认是 object-position: 50% 50%,如果你不希望图片居中展示,可以使用它去改变图片实际展示的 position 。

img {
  width: 100px;
  height: 100px;
  object-fit: cover;
  object-position: 50% 50%;
}

9. defer、async 的区别?

  • script :会阻碍 HTML 解析,只有下载好并执行完脚本才会继续解析 HTML。
  • async script :解析 HTML 过程中进行脚本的异步下载,下载成功立马执行,有可能会阻断 HTML 的解析。
  • defer script:完全不会阻碍 HTML 的解析,解析完成之后再按照顺序执行脚本。

10. 说说 html、css、js 的加载顺序?

html 解析 -> htmlParser2 css 解析 -> css

  • DOM 解析:把所写的各种 html 标签,生成一个 DOM TREE,相当于是生成了一个最原始的页面,一点样式都没有,毫无 CSS 修饰。边解析边渲染
  • DOM 渲染:浏览器会把本身默认的样式 + 用户自己写得样式整合到一起,形成一个CSS TREE,而DOM渲染就是指DOM TREECSS TREE 结合到一起,生成一个Render TREE,呈现出一个带有样式的页面
  • DOMCSS
  1. css 的加载不会阻塞 DOM解析
  2. css 的加载会阻塞 DOM渲染
  • DOMJS
  1. JS(加载和执行) 都会阻塞 DOM解析
  2. JS(加载和执行) 都会阻塞 DOM渲染

html 中每遇到 script 标签,页面就会重新渲染一次,因为要保证标签中的 JS 代码拿到的都是最新的样式

  • CSSJS
  1. CSS 的加载阻塞 JS运行,不阻塞 JS加载CSSJS 同时加载

CSS 的渲染 GUI 线程JS 运行线程互斥

总结

  1. script 最好放底部,link 最好放头部。注意link 放到底部,可能会发生 重绘,因为渲染 DOM,要等待样式加载完毕

  2. 如果头部同时有scriptlink的情况下,最好将script放在link上面

  3. HTML 在加载的时候,会预先加载 CSSJS,且并行加载。JS 阻塞 DOM 解析 和 渲染。JS 要等上面的的 css 加载完毕,保证页面可以操作样式 扩展:为了避免让用户看到长时间的白屏时间,我们应该尽可能的提高 css 加载速度,比如可以使用以下几种方法:

  4. 使用 CDN(因为 CDN 会根据你的网络状况,替你挑选最近的一个具有缓存内容的节点为你提供资源,因此可以减少加载时间)

  5. css 进行压缩(可以用很多打包工具,比如 webpack, gulp 等,也可以通过开启 gzip 压缩)

  6. 合理的使用缓存(设置 cache-control,expires,以及 E-tag 都是不错的,不过要注意一个问题,就是文件更新后,你要避免缓存而带来的影响。其中一个解决防范是在文件名字后面加一个版本号)

  7. 减少 http 请求数,将多个 css 文件合并,或者是干脆直接写成内联样式(内联样式的一个缺点就是不能缓存)

  8. 不要在嵌入的 JS 中调用运行时间较长的函数,如果一定要用,可以用setTimeout来调用

  • 扩展DOM 如何生成的?
    1. 在解析前会执行 预解析 操作,会预先加载 JSCSS 等文件
    2. 字节流 -> 分词器 -> 根据 token 生成节点 -> 插入到 DOM 树
    3. 遇到 JS:在解析过程中遇到 script 标签,HTMLParser 会停止解析,(下载)执行对应的脚本
    4. JS 执行前,需要等待当前脚本之上的所有 CSS 加载解析完毕(JS 是依赖 CSS 的加载)

11. 你知道哪几种方式可以隐藏一个元素?

答:opacity/filter: opacity()clip-pathpositionz-indexvisibility覆盖一个元素(伪类:after)displaytransform: scale(0)/translate(-999px, 0px)color alpha缩小尺寸

12. 了解 H5 的 draggable 拖拽吗?

为了使元素可拖动,把 draggable 属性设置为 truedraggable 属性可用于任何元素节点,但是图片(img)和链接(a)不加这个属性,就可以拖拉

注意:一旦某个元素节点的 draggable 属性设为 true,就无法再用鼠标选中该节点内部的文字或子节点了

  • 当元素节点或选中的文本被拖拉时,包括以下一些事件:
    1. drag:拖拉过程中
    2. dragstart:用户开始拖拉时
    3. dragend:拖拉结束时
    4. dragenter:拖拉进入当前节点时
    5. dragover:拖拉到当前节点上方时
    6. dragleave:拖拉操作离开当前节点范围时
    7. drop:被拖拉的节点或选中的文本,释放到目标节点时

13. 优化长列表滚动效果?

  • transition 优化动画效果,分层渲染

    1. 第一种、用 transform 进行强制分层
    2. 第二种、可以用 content-visibility 将看不见的元素不渲染,设置值为 auto 即可
    3. 第三种、是对于某些动画效果,可以用 will-change 作用在父元素上进行 gpu 加速,使用后删掉
    4. 第四种、懒加载:即监听 scroll 事件或使用 IntersectionObserver 监听
    5. 第五种、可视区域渲染: 仅在可视区域展示数据,为保证滚动条的完整性,非可视区域使用占位元素的高度后者容器的位移来撑开。
  • 扩展:css 怎么开启硬件加速(GPU 加速)

  1. transform(当 3D 变换的样式出现时会使用 GPU 加速)
  2. opacity
  3. filter
  4. will-change

浏览器在处理上面的 css 的时候,会使用 GPU 渲染

14. 移动端 1px 像素如何解决?

在 CSS 规范中,长度单位可以分为两类,绝对(absolute)单位以及相对(relative)单位。px 是一个相对单位,相对的是设备像素(device pixel)。

  • PX(CSS pixels)虚拟像素,可以理解为“直觉”像素,CSS 和 JS 使用的抽象单位,浏览器内的一切长度都是以 CSS 像素为单位的,CSS 像素的单位是 px。
  • DP(device pixels)设备像素(物理像素),顾名思义,显示屏是由一个个物理像素点组成的,通过控制每个像素点的颜色,使屏幕显示出不同的图像,屏幕从工厂出来那天起,它上面的物理像素点就固定不变了,单位 pt。 pt 在 css 单位中属于真正的绝对单位,1pt = 1/72(inch),inch 及英寸,而 1 英寸等于 2.54 厘米。
  • DPR(device pixels ratio)DPR = 设备像素/CSS 像素
  • DIP(Device independent Pixel)设备独立像素/逻辑像素.可以理解为: 设备独立像素 = css 像素

根本原因:因为不同设备可能有不同的 dpr,导致了 1px 展示的宽度有所不同。

问题

  • 问:1px 的设置是没有问题的,那么是什么导致了不同设备的表现不一致呢? 答: 不同的 dpr 导致了不同设备的 1px 包含了不同数量的 pt
  • 问:我和设计小伙伴嘴里说的 1px 是一个东西吗? 答:并不是,设计小伙伴真正想要的是 1pt 的效果

解决方案

注意:我在两倍屏把宽度定义成 0.5px 不就行了吗?0.5px 也只在 ios8+上支持(小于 ios8 被转为 0px),安卓上是不行的。

  • 方式一、background-image && border-image

    .background-image-1px {
      background: url(...) no-repeat left bottom;
      -webkit-background-size: 100% 1px;
      background-size: 100% 1px;
    }
    
    .border-bottom-1px {
      border-width: 0 0 1px 0;
      -webkit-border-image: url(...) 0 0 2 0 stretch;
      border-image: url(...) 0 0 2 0 stretch;
    }
    

    优势: 至少解决了问题

    劣势: 我想换个颜色还得换图,而且图片处理圆角会出现模糊的问题

  • 方式二、border-shadow

    通过 css 对 border-shadow 的处理来模拟 0.5px

    .box-shadow-1px {
      box-shadow: inset 0px -1px 1px -1px #c8c7cc;
    }
    

    优势: 代码少,还能换颜色

    劣势: 阴影导致的颜色变浅,而且仔细看谁都看得出这是阴影而不是边框

  • 方式三、伪元素 + scale 缩放

    构建 1 个伪元素, border 为 1px, 再以 transform 缩放到 50%。ant-design-mobile 同样使用这种处理

    原理: 是把原先元素的 border 去掉,然后利用 :before 或者 :after 重做 border ,并将 transform 的 scale 缩小一半,原先的元素相对定位,新做的 border 绝对定位。

    .scale-1px {
      position: relative;
      border: none;
    }
    .scale-1px:after {
      content: '';
      position: absolute;
      bottom: 0;
      background: #000;
      width: 100%;
      height: 1px;
      -webkit-transform: scaleY(0.5);
      transform: scaleY(0.5);
      -webkit-transform-origin: 0 0;
      transform-origin: 0 0;
    }
    

    四条 border 样式设置:

    .scale-1px {
      position: relative;
      margin-bottom: 20px;
      border: none;
    }
    .scale-1px:after {
      content: '';
      position: absolute;
      top: 0;
      left: 0;
      border: 1px solid #000;
      -webkit-box-sizing: border-box;
      box-sizing: border-box;
      width: 200%;
      height: 200%;
      -webkit-transform: scale(0.5);
      transform: scale(0.5);
      -webkit-transform-origin: left top;
      transform-origin: left top;
    }
    

    最好在使用前也判断一下,结合 JS 代码,判断是否 Retina 屏:

    if (window.devicePixelRatio && devicePixelRatio >= 2) {
      document.querySelector('ul').className = 'scale-1px'
    }
    

    优点:可以满足所有场景,且修改灵活。缺点:对于已使用伪类的元素(例如 clearfix)要多层嵌套。

  • 方式四、viewport + rem 实现

    同时通过设置对应 viewport 的 rem 基准值,这种方式就可以像以前一样轻松愉快的写 1px 了。 在 devicePixelRatio = 2 时,输出 viewport:

    <meta
      name="viewport"
      content="initial-scale=0.5, maximum-scale=0.5, minimum-scale=0, user-scalable=no"
    />
    

    在 devicePixelRatio = 3 时,输出 viewport:

    <meta
      name="viewport"
      content="initial-scale=0.3333333333333333, maximum-scale=0.3333333333333333, minimum-scale=0.3333333333333333, user-scalable=no"
    />
    

    优点:所有场景都能满足。一套代码,可以兼容基本所有布局 缺点:老项目修改代价过大,只适用于新项目

15. css 如何实现一个正方形盒子(随父元素)自适应?

  • 方式一、CSS3 vw 单位,vw 是相对于视口的宽度。视口被均分为 100 单位的 vw。1vw = 1% viewport width
    .box {
      width: 20%; // 20vw也可以
      height: 20vw;
      background: red;
    }
    
  • 方式二、设置盒子的 padding-bottom 样式,让盒子的 padding-bottom 和盒子的宽度一样,同时设置 heigh = 0px;
    .box {
      width: 20%;
      /* 设置height为0,避免当盒子里面有内容的时候,盒子会被内容撑大 */
      height: 0px;
      /* 把盒子的高撑开,和width设置同样的固定的宽度或者百分比。百分比相对的是父元素盒子的宽度 */
      padding-bottom: 20%;
      background: red;
    }
    
    盒子设置了 heigh:0px;导致该元素里面再有子元素的时候,就无法正常设置高度。所以我们需要用到 position: absolute;使当前内容脱离文档流,那么内容的高度百分比参照的就是父级的宽度

经典 Flex 布局

如今Flex布局不管是移动端还是 PC 端的应用已经非常广泛了,下面我列举几个平时项目中非常常见的几个需求。以下例子我们都以 Vue 项目为例~

flex 布局均匀分布后换行问题

需求一:ul下有多个li,每三个li排一列,多余的换行显示。

很显然,绝大部分的小伙伴都会使用Flex布局,很显然会出现一个问题就是如果 li 是 3 的倍数的话就能正常显示,若不是的话,布局就不是产品经理满意的结果。

display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;

解决方案

我们在ul的底部新增li,个数为数组总长度%3的余数即可。

<li class="item" style="border: none;" v-for="(ite, idx) in list.length%3" :key="idx"></li>

扩展:flex:1 是哪些属性组成的

flex 实际上是 flex-growflex-shrinkflex-basis 三个属性的缩写

  • flex-grow:定义项目的的放大比例

    默认为 0,即 即使存在剩余空间,也不会放大;所有项目的 flex-grow 为 1:等分剩余空间(自动放大占位);flex-grow 为 n 的项目,占据的空间(放大的比例)是 flex-grow 为 1 的 n 倍。

  • flex-shrink:定义项目的缩小比例

    默认为 1,即 如果空间不足,该项目将缩小;所有项目的 flex-shrink 为 1:当空间不足时,缩小的比例相同;flex-shrink 为 0:空间不足时,该项目不会缩小;flex-shrink 为 n 的项目,空间不足时缩小的比例是 flex-shrink 为 1 的 n 倍。

  • flex-basis: 定义在分配多余空间之前,项目占据的主轴空间(main size),浏览器根据此属性计算主轴是否有多余空间

    默认值为 auto,即 项目原本大小;设置后项目将占据固定空间。

两栏布局

两栏布局:左右两栏,左边固定,右边自适应

效果图

  1. 第一种方式 --- 浮动

    HTML 部分:

    <div class="outer outer1">
        <div class="left">1-left</div>
        <div class="right">1-right</div>
    </div>
    

    CSS 部分:

    .outer1 .left {
        width: 200px;
        float: left;
    }
    .outer1 .right {
        width: auto;
        margin-left: 200px;
    }
    
  2. 第二种方式 --- flex

    HTML 部分:

    <div class="outer outer2">
        <div class="left">2-left</div>
        <div class="right">2-right</div>
    </div>
    

    CSS 部分:

    .outer2 {
       display: flex;
    }
    .outer2 .left {
       flex: 0 0 200px;
       /* flex-grow: 0;
       flex-shrink:0;
       flex-basis:200px; */
    }
    .outer2 .right {
       flex: auto;
    }
    
    注意:flex: 0 0 200px是flex: flex-grow flex-shrink flex-basis的简写
    
  3. 第三种方式 --- position

    HTML 部分:

    <div class="outer outer3">
       <div class="left">3-left</div>
       <div class="right">3-right</div>
    </div>
    

    CSS 部分:

    .outer3 {
       position: relative;
    }
    .outer3 .left {
       position: absolute;
       width: 200px;
    }
    .outer3 .right {
       margin-left: 200px;
    }
    
  4. 第四种方式 --- position again

    HTML 部分:

    <div class="outer outer4">
        <div class="left">4-left</div>
        <div class="right">4-right</div>
    </div>
    

    CSS 部分:

    .outer4 {
        position: relative;
    }
    .outer4 .left {
        width: 200px;
    }
    .outer4 .right {
        position: absolute;
        top: 0;
        left: 200px;
        right: 0;
    }
    

三栏布局

三栏布局: 中间列自适应宽度,旁边两侧固定宽度

效果图

  1. 第一种方式 --- 定位

    HTML 部分:

    <div class="outer outer1">
       <div class="left">1-left</div>
       <div class="middle">1-middle</div>
       <div class="right">1-right</div>
    </div>
    

    CSS 部分:

    .outer1 {
       position: relative;
    }
    .outer1 .left {
       position: absolute;
       width: 100px;
    }
    .outer1 .middle {
       margin: 0 200px 0 100px;
    }
    .outer1 .right {
       position: absolute;
       width: 200px;
       top: 0;
       right: 0;
    }
    注意:左右分别使用绝对定位,中间设置外边距
    
  2. 第二种方式 --- flex布局

    HTML 部分:

    <div class="outer outer2">
       <div class="left">2-left</div>
       <div class="middle">2-middle</div>
       <div class="right">2-right</div>
    </div>
    

    CSS 部分:

    .outer2 {
       display: flex;
    }
    .outer2 .left {
       flex: 0 0 100px;
    }
    .outer2 .middle {
       flex: auto;
    }
    .outer2 .right {
       flex: 0 0 200px;
    }
    
  3. 第三种方式 --- 浮动原理

    HTML 部分:

    <div class="outer outer3">
       <div class="left">3-left</div>
       <div class="right">3-right</div>
       <div class="middle">3-middle</div>
    </div>
    

    CSS 部分:

    .outer3 .left{
       float: left;
       width: 100px;
    }
    .outer3 .right {
       float: right;
       width: 200px;
    }
    .outer3 .middle {
       margin: 0 200px 0 100px;
    }
    

圣杯布局

圣杯布局: 中间的优先渲染,独立的左中右结构

具体实现圣杯布局的步骤:

  1. 让左右浮动在一行显示,相对定位
  2. 让中间模块的 middle 宽度为 100%
  3. 让左边的色块移动到 middle 前面,margin-left:-100%
  4. 让右边的色块移动到 middle 的后面,margin-left:-宽度
  5. 给三个小块的父元素加一个内填充的属性 padding,为的是填充挤到中间
  6. 给左边的块移动到左边 left:-200px, 给右边的块移动到右边 right:-200px

效果图

HTML 部分:

<header>header</header>
   <div class="container">
      <div class="middle">midlle</div>
      <div class="left">left</div>
      <div class="right">right</div>
   </div>
<footer>footer</footer>

CSS 部分:

header, footer {
   height: 100px;
   width: 100%;
   background-color: antiquewhite;
}
.container {
   height: 200px;
   padding-left: 200px;
   padding-right: 300px;
}
.container > div {
   float: left;
   position: relative;
   height: 100%;
}
.left {
   width: 200px;
   height: 200px;
   background-color: burlywood;
   margin-left: -100%;
   left: -200px;
}
.right {
   width: 300px;
   height: 200px;
   background-color: burlywood;
   margin-left: -300px;
   right: -300px;
}
.middle {
   width: 100%;
   height: 200px;
   background-color: #b0f9c2;
}

双飞翼布局

双飞翼布局

具体实现双飞翼布局的步骤:

  1. 给左,中,右 加浮动,在一行显示
  2. 给 middle 宽度为 100%
  3. 让左边的模块移动 middle 的左边 margin-left:-100%
  4. 让右边的模块移动 middle 的右边 margin-left:-自己宽度
  5. 给 middle 里面的容器添加外间距 margin: 左右

效果:

html 部分

<div class="main">
    <div class="middle">
			<div class="middle-inner">中间</div>
    </div>
    <div class="left">左边</div>
    <div class="right">右边</div>
</div>

css 部分

.main>div {
    float:left;
    position: relative;
    height: 300px;
}
.middle {
    width: 100%;
    background-color: lightgreen
}
.left {
   width:200px;
   margin-left:-100%;
   background-color:#b0f9c2
}
.right {
   width: 200px;
   margin-left:-200px;
   background-color:pink
}
.middle-inner{
   margin:0 200px;
   background-color: burlywood;
   height:300px;
}

水平垂直居中

html 部分

<div class="box" id="box">
   石小明
</div>

css 部分

公共部分

body {
    width: 100vw;
    height: 100vh;
    overflow: hidden;
}
.box {
    box-sizing: border-box;
    width: 100px;
    height: 50px;
    line-height: 50px;
    text-align: center;
    font-size: 16px;
    border: 1px solid lightblue;
    background: lightcyan;
}

第一种:定位

.box {
    position: absolute;
    top: 50%;
    left: 50%;
    margin-left: -50px;
    margin-top: -25px;
}

注意:上面的方式是一定要知道具体的宽高。但下面的方式是知道宽高,但是没有用到宽高。

第二种:flex

body {
    display: flex;
    justify-content: center;
    align-items: center;
}

注意:这种方式也是兼容性不是很好

第三种:JavaScript

let html = document.documentElement,
            winW = html.clientWidth,
            winH = html.clientHeight,
            boxW = box.offsetWidth, // offsetWidth带边框
            boxH = box.offsetHeight;

            box.style.position = 'absolute';
            box.style.left = (winW - boxW) / 2 + 'px';
            box.style.top = (winH - boxH) / 2 + 'px';

第四种:table-cell

body {
    display: table-cell;
    vertical-align: middle;
    text-align: center;
}