您的位置:首页 > Web前端 > CSS

中国第二届CSS开发者大会

2018-03-22 14:17 465 查看
展新:企业CSS应用

支付宝前端发展过程:

很早之前的支付宝的时候只有pa.css, 解决基础样式、重用等功能

=> 后来超过了6000行/100k,全局样式太多,重置困难,烂代码积压

=> 2011年的时候出现了前端解决方案: CSS样式规范,浏览器解决方案: 例如: 解决1px圆角,解决ie6下的浮动 形成了 Alice V3 写样式有道可寻,可维护性强..文件进行拆分,最基础只有20k 但是随着 交互组件缺乏,工程化不足,产品差异化越来越多

=> 出现了AliceUI 模块化命名 和组织方式,强大的工具支持-spm等 CSS3新技术使用 但是视觉规范多变,企业平台业务据增,新技术发展。 所以很多前端技术可能刚开始的使用是放在后台去使用。

(1)在图标设计规范:

在设计iconfont字体的时候,比如在16*16px的设计图中,内部的icon的大小应该是在14*14 或则 15*15,而不是16*16

1. 尽可能地接近普通文字的font-size

2. 视觉上不同的形状做适当的调整,以保证[看起来]都差不多大

3. 图标的线条的粗细保证是像素格的整数倍

(2)iconfont的命名上也是非常讲究的:

一般命名的规范: name - type - direction

比如: caret-circle-left

caret-circle-o-right

caret-o-down

caret-up

(3)色彩中的学问

固定必须要知道的色谱,

基础的色谱: active / link / hover / outline

固定的色谱: 标题颜色, 正文的颜色,辅助的颜色

提示性色谱: 出错的颜色, 成功的颜色, 警告的颜色

郑海波: CSS预处理器

为什么要写css预处理器.?

CSS的"罪":
变量
函数
逻辑/循环
前缀
运算/表达式
CSS缺乏是抽象能力。
抽离细节
减少关注点


CSS中的抽象:CASCADING

<div class='m-layer m-layer-bg m-layer-primary  z-show'>
Cascading 是CSS的灵魂, 也是限制预处理能力的 “关键点”
</div>

.m-layer{...}
.m-layer-bg{...}
.m-layer-primary{...}
.z-show{...}


预处理器:处理特定格式源文件到目标CSS的处理程序。

// 编译前
$color-primary = #de12ec;
.m-layer{
background-color: $color-primary;
&:hover{
background-color: l-adjust($color-primary, -10%);
}
}

// 编译后
.m-layer{
background-color:#de12ec;
}
.m-layer:hover{
background-color:#b10ebd;
}


预处理器青铜时代: LESS-SCSS-Stylus

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

li { display: inline-block; }

a {
display: block;
padding: 6px 12px;
text-decoration: none;
}
}


优点:

对前端更友好

不基于缩进,不简洁但更安全

与自定义DSL同样强大的语言能力

可以直接使用css书写

预处理器钢铁时代(纯CSS语法)

严格遵守CSS语法的提供额外能力的CSS预处理器

postcss: https://github.com/postcss
rework: https://github.com/reworkcss

postcss简介:

npm install postcss --save-dev

postcss其实只是个平台,它提供解析,AST便利操作。
SourceMap和翻译器,具体功能由插件实现。


官方案例:

var postcss = require('postcss');

postcss([
// 允许你使用"阉割版"的未来的CSS特性
require('cssnext')(),
// 一个高级的css压缩器
require('cssnano')()
])
.process(css, { from: 'src/app.css', to: 'app.css' })
.then(function (result) {
// 写入变换后的css文件
fs.writeFileSync('app.css', result.css);
// sourmap文件
if ( result.map ) fs.writeFileSync('app.css.map', result.map);
});


POSTCSS正在渐渐成为预处理器中的jQuery;

// 编译前before compile
.m-nav{
.list{
padding: 10px;
}
.link{
color: red;
&:hover{
color: green;
}
}
}

// 编译后 after compile
.m-nav .list{
padding:10px;
}
.m-nav .link{
color:#f00;
}
.m-nav .link:hover{
color:#008000;
}


Nesting建议嵌套尽量不要超过3层

1. 使用选择器提升

.m-layer{   // 一般这个表示的是一个组件对应的样式,但是嵌套多层不好
.cnt{
.nav{
.bar{
padding: 10px;
}
}
}
}

=>

.m-layer{      // 这样的选择依然是唯一的,但是不用嵌套多层
.layer_bar{
padding: 10px;
}
}


2 避免深层选择器序列

// 不好的实践
div, p, span, ul{
div, p, span, ul{
div, p, span, ul{
left: 10px;
}
}
}


变量的最佳实践:

变量名要达意

// BAD
$fs1 = 14px;
$fs2 = 16px;
$fs3 = 18px;
$fc0 = #253443; // 主色1
$fc1 = #153c3d; // 主色2
$fc2 = #777 ;   // 灰色

// GOOD
$fsize-base  = 14px;
$fsize-small = 12px;
$fsize-big      = 16px;
$color-primary = #253443;
$color-inverse = #153c3d;
$color-gray      = #777;


2 全局变量集中管理

Rule更易于迁移

变量更易于查找管理

3 私有变量声明在模块内

.m-module{
$gap = 32px;
.side{
margin-right: $gap;
}
}


4 必须统一管理z-index

// z-index config:
$modal-index = 1000;
$dropdown-index = 100;
$mask-index = $modal-index - 10;


施峰峰:移动下的布局

vw: viewport 宽度的1%

vh: viewport 高度的1%

vmin: viewport Math.min(高度, 宽度)的1%

vmax: viewport Math.max(高度, 宽度)的1%

案例如下:

<div>按钮内容</div>

div{
height: 10vw;
width: 50vw;
line-height: 10vw;
font-size: 5vw;
text-align: center;
color: #fff;
background: red;
margin: auto;
}


css: 神奇的padding/margin-top;子元素的padding-top百分比基准是父元素的宽度。

.papa {
width:100px;
height: 300px;
background-color: #ddd;
overflow: hidden;
}

.child {
width: 50px;
height: 50px;
background-color: red;
margin-top: 100%;               // 这里的值是父元素的宽度
}


结合使用rem和@media

html {
font-size:62.5%;
}
body {
font-size: 1.6rem;
}
h1 {
text-align: center;
font-size: 3rem;
}
p {
text-align: center;
font-size: 1.8rem;
}

@media all and (max-width: 700px) {
html {
font-size: 60%;
}
}
@media all and (max-width: 608px) {
html {
font-size: 52%;
}
}
@media all and (max-width: 533px) {
html {
font-size: 45%;
}
}


黄薇(瓜瓜):高性能CSS动画

讲讲web浏览器渲染过程:

1 通过一个get请求,获取一个html页面

2 分析html结构生成DOM树

3 Recalculate Style:分析CSS,浏览器让DOM+CSS生成了叫渲染树(render tree)

4 layout 将渲染树中每个节点,根据宽度高度模型相关的属性来计算它的位置和大小

5 Paint 开始涂鸦,把每个区域涂鸦完毕生成一个位图

6 Composite Layers 浏览器将位图从CPU 传送到 GPU 然后渲染到屏幕上,完成一次渲染工作



从图中可以看出,在width,height,margin等是处于Layout阶段。以及box-shadow处于paint阶段,transform处在Composite Layers阶段。

所以在改变CSS样式属性的时候会触发浏览器中的哪个阶段呢,当触发了某个阶段的执行,同时也会触发该阶段后面的执行。举例触发了Layout阶段,那么Paint和Composite Layers阶段也一样要触发。所以 绘制的阶段,触发的时间越早,消耗的代价越大。

渲染小结

渲染主要三阶段: Layout计算范围,Paint计算展现,Composite合成Bitmap

修改不同CSS属性会触发不同阶段

触发的阶段越前,渲染的代价越高

硬件加速

硬件加速也称为GPU加速。

术语: texture。 可看做一个放在GPU上的位图

GPU擅长队texture进行偏移,放大缩小,旋转,更改透明度(意思是处理的特别快,时间短)

浏览器是如何使用GPU的呢?

浏览器中有个Layer模型

浏览器会根据CSS属性为元素生成Layers

将Layers作为texture上传到GPU

当改变Layer的transform,opacity属性时,渲染会跳过Layout,paint;直接通知GPU对Layer做变换。

为什么使用硬件加速实现动画快?

(1)首先,当使用jquery实现div向下移动的动画时。浏览器是做了那些事情?



这里每一次top新增1px之后都会触发浏览器重排和重绘制。

(2)使用硬件加速,就可以使用CSS3中的Animate transform



然而这里是直接触发了Composite Layers阶段,减少了重排和重绘的过程。

节省了CPU进行Layout,Paint的时间,CPU向GPU传输位图的时间。

fps

对人类的眼睛来说,30FPS+是感觉流畅的,60FPS(1s显示60张图片)会更加舒服。

所以为了使得舒服顺滑的动画,就必须在1/60FPS,约等于16.7ms内,把这一帧准备好。

渲染时机的选择:

(1)setTimeout(callback, 1/60)来实现动画

缺点:

依靠浏览器内置时钟更新频率,然后ie等浏览器更新的间隔时间不一样

main thread队列,如果上个帧的动画展示出错那么会影响下一帧的动画。

(2)HTML5的出现:requestAnimationFrame(更好的选择)

定义绘制每一帧前的工作。 requestAnimationFrame(callback)

自动调节频率。callback工作太多无法在一帧内完成,会自动降低为30FPS, 虽然频率降低但比丢帧好。

渲染一帧的时间:

目标:16ms

触发Layout:

改变width, height, margin等和大小、位置相关的属性

读取size, position相关得属性(因为一个页面中有多个脚本,有时候很多脚本就是改变了width和height,为了页面的正确性,所以当读取这些属性的时候会触发Layout阶段)

相关属性有:

clientHeight, clientLeft, clientTop, clientWidth, focus(), getBoundingClientRect(), getClientRects(), innerText, offsetHeight, offsetLeft, offsetParent, offsetTop, offsetWidth, outerText, scrollByLines(), scrollByPages(), scrollHeight, scrollIntoView(), scrollIntoViewIfNeeded(), scrollLeft, scrollTop, scrollWidth .....


尽量不要去触发Layout: 使用transform代替top, left的动画

// 频繁Layout
var h1 = element1.clientHeight;
element1.style.height = (h1 * 2) + 'px';

var h2 = element2.clientHeight;
element2.style.height = (h2 * 2) + 'px';

var h3 = element3.clientHeight;
element3.style.height = (h3 * 2) + 'px';


读取clientHeight属性的时候,就会出发Layout,比如上图,读取h2的时候无法确认h1的位置有没有变化,所以会发生Layout。

// 分离读取操作
// Read
var h1 = element1.clientHeight;
var h2 = element2.clientHeight;
var h3 = element3.clientHeight;

// Write
element1.style.height = (h1 * 2) + 'px';
element2.style.height = (h2 * 2) + 'px';
element3.style.height = (h3 * 2) + 'px';


这样浏览器会先将数据取出来,然后再下面才会进行改变,触发一次Layout。

事实上,两段代码的实际写法如下:

document.body.addEventListener('click', function() {
var h1 = element1.clientHeight;
element1.style.height = (h1 * 2) + 'px';
});

document.body.addEventListener('click', function() {
var h2 = element2.clientHeight;
element2.style.height = (h2 * 2) + 'px';
});   // 在这里无法将两次的操作读写放在一起


所以使用requestAnimationRequest推迟执行

document.body.addEventListener('click', function() {
// Read
var h1 = element1.clientHeight;
// Write
requestAnimationFrame(function() {
element1.style.height = (h1 * 2) + 'px';
});
});
document.body.addEventListener('click', function() {
// Read
var h2 = element2.clientHeight;
// Write
requestAnimationFrame(function() {
element2.style.height = (h2 * 2) + 'px';
});
});
// 使用了requestAnimationFrame使得在第一帧的时候只会去读取h1和h2这两个数据的值,
// 而在下一帧的时候才回去去触发Layout


触发Paint

当修改border-radius,box-shadow,color等展示相关属性时,会触发paint

减少不必的绘制: gif图即使被其他Layer盖住不可见,也可能导致paint,不需要时应将gif图的display属性设为none。

减少绘制区域:为引起大范围Paint的元素生成独立的Layer以减小Paint的范围

附上中国第二届CSS开发者大会地址

https://www.w3ctech.com/topic/1463
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: