CSS技巧 | 青训营

169 阅读7分钟

部署相关开发环境。其实对于CSS开发环境的部署还是很简单的,一个浏览器一个编辑器即可。当然这样的部署也只能应付一些简单的Demo,应用级别的部署还需结合webpack实现。 开发工具选择:

浏览器的渲染过程

  • 处理 HTML 标记并构建 DOM 树。
  • 处理 CSS 标记并构建 CSSOM(Style Rules) 树。
  • 将 DOM 与 CSSOM 合并成一个渲染树(Render Tree)。
  • 根据渲染树(Layout)来布局,以计算每个节点的几何信息。
  • 将各个节点绘制(Painting)到屏幕上

46f3a2d81b65e8b57aef988fe898a0a7.jpeg

回流和重绘(基础)

回流

回流又名重排,指的是 布局几何属性需改变的渲染。 渲染树的节点发生改变,影响了该节点的集合属性,导致该节点位置发生变化,此时就会触发浏览器回流并重新生成渲染树。 回流意味着节点的几何属性发生了改变,需重新计算并生成渲染树,导致渲染树的全部或部分发生变化。 reflow(回流)是导致DOM脚本执行效率低的关键因素之一,页面上任何一个节点触发了reflow,会导致它的子节点及祖先节点重新渲染。

重绘

重绘指的是当节点需要更改外观而不影响布局的,比如改变color就称为重绘。 渲染树的节点发生改变,但不影响该节点的几何属性。 由此可见,回流对浏览器性能的消耗是高于重绘的,而且回流一定会伴随重绘,重绘却不一定伴随回流。

性能优化

回流重绘在操作节点样式时频繁出现,同时也存在很大程度上的性能问题。
回流必定引发重绘,重绘不一定引发回流,可利用该法则解决一些因为回流重绘而引发的性能问题。

使用visibility:hidden 替换 display:none:

  • VH占据空间,DN不占据空间
  • DN触发回流重绘,VH触发重绘
  • DN影响过渡不影响动画,VH不影响过渡不影响动画
  • DN后自身及其子节点都不可见,- VH后自身及其子节点全都不可见但可声明子节点visibility:visible单独显示

使用transform代替top

top是几何属性,操作top会改变节点位置从而引发回流,使用transform:translate3d(x, 0, 0)代替top,只会引发图层重绘。

避免使用table布局

一个很小的改动就可能造成整个<table>回流,通常可以用<ul><li><span>等标签取代<table>系列标签生成表格。

避免规则层级过多

浏览器的css解析器解析css文件时,对CSS规则是从右到左匹配查找,样式层级过多会影响回流重绘效率,保持3层左右比较合适。

动态改变类而不改变样式(最小化重绘和重排)

不要尝试每次操作DOM去改变节点样式,这样会频繁触发回流。
更好的方式是使用新的类名预定义节点样式,在执行逻辑操作时收集并确认最终更换的类名集合,在适合时机一次性动态替换原来的类名集合。

  • 使用cssText

    const el = document.getElementById('test');el.style.cssText += 'border-left: 1px; border-right: 2px; padding: 5px;';
    
  • 修改CSS的class

    const el = document.getElementById('test');el.className += ' active';
    

布局技巧

  • 普通布局:display:block/inline
  • 浮动布局:float:left/right
  • 定位布局:position:relative/absolute/fixedleft/right/top/bottom/z-index
  • 表格布局:table系列属性
  • 弹性布局:display:flex/inline-flexflex系列属性
  • 格栅布局:display:grid/inline-gridgrid系列属性
  • 响应式布局:em/rem/vw/vh/vmin/vmax媒体查询

浮动布局

清除浮动

  1. 利用 clear 样式,在父元素标签结束之前插入 块级元素 clear 属性指定一个元素是否必须移动(清除浮动之后)到在它之前的浮动元素下面。
.clearfix::after {
    display: blockl
    visibility: hidden;
    clear: both;
    height: 0;
    font-size: 0;
    content: "";
}
  1. 为父元素添加overflow属性(其他方式形成BFC也可清除浮动)
  2. 当为父元素添加 overflow 属性时,该元素会构建一个 BFC BFC在计算高度的时候,内部浮动元素的高度也要计算在内。

全屏布局

经典的全屏布局由顶部、底部、主体三部分组成,其特点为三部分左右满屏拉伸顶部底部高度固定主体高度自适应,主要应用在主体布局。 该布局非常常见~ 通常使用<header><footer><main>三个标签语义化排版,<main>内还可插入<aside>作为侧边栏。

<div class="fullscreen-layout">
    <header></header>
    <main></main>
    <footer></footer>
</div>

顶部、底部和主体声明left:0right: 0将其左右部分满屏拉伸;顶部和底部声明top: 0bottom: 0分别将其吸顶和吸底,并声明俩高度为固定值;将主体的topbottom分别声明为顶部高度和底部高度。

使用flex实现会更简洁。display:flex默认会令子节点横向排列,需声明flex-direction: colunm改变子节点排列方向为纵向排列;顶部和底部高度固定,所以主体声明flex: 1,让高度自适应即可。

多列布局

两列布局

经典的两列布局由左右两列组成,其特点为一列宽度固定另一列宽度自适应、和两列高度固定且相等。 左列宽度固定和右列宽度自适应:

左列声明float: left和固定宽度,由于float让节点脱离文档流,右列需声明margin-left为左列宽度,以保证两列不重叠。 左列声明同上,右列声明overflow:hidden使其形成BFC区域与外界隔离。 左列声明固定宽度,右列声明flex:1自适应宽度。

圣杯布局

  • header和footer各自占领屏幕所有宽度,高度固定。
  • 中间的container是一个三栏布局。
  • 三栏布局两侧宽度固定不变,中间部分自动填充整个区域。
  • 中间部分的高度是三栏中最高的区域的高度。
<div class="header"></div>
<div class="container">
  <div class="left"></div>
  <div class="right"></div>
  <div class="center"></div>
</div>
<div class="footer"></div>

float + margin-left/right + padding-left/right,由于浮动节点在位置上不能高于前面或平级的非浮动节点,否则会导致浮动节点下沉。因此在编写HTML结构时,将中间列节点挪到右列节点后面。

float + margin-left/right

.container {
    width: 400px;
    height: 400px;
    .left {
        float: left;
        width: 100px;
        height: 100%;
        background-color: #f66;
    }
    .right {
        float: right;
        width: 100px;
        height: 100%;
        background-color: #66f;
    }
    .center {
        margin: 0 100px;
        height: 100%;
        background-color: #3c9;
    }
}

flex

居中布局

  • 块级元素 + padding-top/bottom块级元素

    • 父节点高度未声明或自适应
    • 若节点不是块级元素需声明display:block
  • 行内元素 + line-height行内元素

    • 父节点上声明line-height
    • 若节点不是行内元素需声明display:inline/inline-block
  • display:table + display:table-cell + vertical-align:middle全部元素

    • 父节点上声明display:table
  • display:table-cell + vertical-align:middle全部元素

    • 父节点上声明displayvertical-align
  • position + top/bottom + margin-top/bottom + height全部元素

  • position + top/bottom + transform:translateY(-50%)全部元素

  • display:flex + align-items:center全部元素

    • 父节点上声明displayalign-items
  • display:flex + margin:auto 0全部元素

    • 父节点上声明display

display:inline-block

display: inline-block;
vertical-align: middle;

display:table-cell

display: table-cell;
vertical-align: middle;
div {
    margin: 0 auto;
}

position最传统最稳定的水平垂直居中布局,要点是使用margin负值将节点拉回最中间,所以必须已知宽高才能计算margin负值,通常是margin-leftmargin-top,可连写成margin:-(height/2) 0 0 -(width/2)

position: absolute;
left: 50%;
top: 50%;
margin: -50px 0 0 -50px;

不可知高宽时

position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);

flex

display: flex;
justify-content: center;
align-items: center;

// or 

display: flex;
div{
    margin: auto;
}