前情提要

  • CSS:老板,你看ES9,ES10都出来了,您看我的事情什么时候...

  • W3C: 这不是正在走着流程嘛!小C你不要心急!

  • W3C:(语重心长)你看啊,我们先(1)提个开发提案章程, 然后再批准成立工作组(2)紧接着工作组建立标准和指南,然后再修改修改。(3)再然后啊,给顾问委员会技术报告审核一下(4)最后浏览器厂商再实现一下 这不就完事了吗?大概不到10年咱们就全部搞定了吧

  • CSS: 。。。。。。 (难过)

  • W3C:(顿了顿):但是这些年啊,你的刻苦努力我们都是看在眼里的!

  • CSS:所以!!??(兴奋加期待)

  • W3C:所以啊,我们要感谢你为前端社区,所作出的贡献!

  • CSS:。。。。。。(沮丧)

  • W3C:但是呢!考虑到你设备老旧,是该更新一下啦。

  • CSS:请问是!?(兴奋加期待,还有微微的迟疑)

  • W3C:没错,这是老板我送给你的步入成年的礼物—— Houdini

什么是Houdini

Houdini包含6组API

S1. Paint API

简单地讲,Paint API就是允许你通过JavaScript注册一个背景函数,类似于linear-gradient()那种,在定义时候可以提供Canvas的2Dcontext给你自行绘制,你通过JS注册这个背景函数后呢,就可以自由地在CSS中通过以下方式使用该背景
background: paint(背景函数名);
如果想了解Paint API的MDN入门指导请点击这里 ,因为这个MDN上是有入门文档的,所以就不放草案了
 

S2.Layout API

可以允许你自行定义布局,并通过以下方式使用:
display:layout(自定义布局名)
这意味着什么呢?我们常用的flex布局, 栅格布局都可以重新通过display进行定义和使用,非常方便。甚至,如果/假如Layout API早出来10年的话,我们甚至可以为这些类似于flex等的新兴属性定义polyfill!, 就像我们为ES6中的proxy对象,promise对象分别添加proxy-polyfill,promise-polyfill一样,实现对低级浏览器的兼容,这无疑让人感到高兴。
 
Layout的定义虽然是为布局使用的,但实际上,根据W3C草案,它还有控制定位和overflow等的能力,总之,除了动画意外的疑难杂症,Layout几乎都能够涉足。如果你想仔细了解:layout的W3C草案
 

S3. AnimationWorklet

这么关键的场合怎么能少得了动画呢?它可以控制动画的效果。该 API 使用户可以在专有的线程中去运行动画,从而大大降低了主线程的压力。如果想了解AnimationWorklet的W3C草案内容请点击这里,这个草案在今年的6月底刚刚发布

S4. Properties & Values

用于自定义CSS属性并为其约定类型,行为和默认值。可以看作less的@式定义和Sass的$式定义的2.0加强版。顺便一提,它经常和前3个API搭配使用。

S5. Parser API

允许开发者自由扩展 CSS 词法分析器,比如新的媒体规则、新的伪类、嵌套等等。时至今日,它还没有形成一个完整的草案,只是初具模型,大家可以阅读 Parser API草案(W3C)

S6.Typed OM

用人话解释就是,原本我们不是可以通过element.style.cssText去修改CSS样式嘛,大佬们觉得这样的字符串操作麻烦而且速度很慢,所以定义了一组CSS专有的接口对象去进行操作,Typed OM提供了与底层值交互的接口,通过使用专门的JS对象来表示它们。除此外还增加了一些其他的API 点击这里查看MDN的Typed OM的入门指导

为什么说Houdini是CSS的成人礼?

这个问题等同于:
问题:结合CSS的产生背景和历史渊源,请问如何客观评价Houdini的历史地位?(本小题10分,请考生答题时不要超出装订线) ( 难道我们在考历史题吗?逃Σ( ° △ °|||)︴)
 

A. 为CSS新特性提供polyfill

它的主要作用在于给予开发者更多开发CSS的自由度,推动CSS新特性发布的进程,同时为未来的那些像flexbox这样优秀的特性提供polyfill,让我们可以不再需要顾忌兼容性,而能够尽快地使用新发布的CSS特性,当然,CSS的生态也会因此更为繁荣。
 
举个例子,我们在使用ES6的Promise的时候,怎么考虑让它在低版本浏览器不报“Promise is undefined”的错误呢?很简单,只要加个promise-polyfill就可以了,如果你想一本万利,那么导入个babel-polyfill,所有(严格的说是大部分)ES6的新对象都可以放心用了。
 
试着想一下,假如Houdini比flex早出来10年,这个时候还需要担心flex兼容性吗?不需要了,我们可以从NPM社区上下一个包,这个前人写好的npm包注册了一个layout方法,你只要下载这个包,在index引用运行一下,然后可以肆无忌怛的通过使用flex了,想怎么浪就怎么浪

B. Houdini的作用是为CSS提供进一步的完善

Houdini出来是16年的事情了,当时的话大家都觉得个这个新东西挺有发展潜力的,但是我觉得嘛,要客观看待,Houdini做的事情,其实很多时候,原本我们就可以做了,举个例子:
  1. Paint API: 在JS领域里直接使用Canvas标签和包装起来的相关函数也是可以做的

  2. Layout API:提供的是大幅度的自定义布局的功能,但问题是。。。flexbox和grid已经把大多数场景给肝了。Layout要是早出来还好,这比flex完了这么多年,就感觉有点尴尬

  3. Typed OM:提供了直接操作CSS属性的对象接口,但问题是CSSOM的标准出来也不少时间了呀,相比之下Typed OM的功能好像就失了一些新意。。。(某个表情包老头估计会说:别笔笔,一梭子ele.style.cssText不就完事了吗!)

  4. 其他,想到再更

我们可以理解为,Houdini在为一开始CSS没有设计想要,并设计进去的一些东西做一些补充(XX可能会迟到!但永远不会缺席。但问题是没打到卡是要扣工资的呀~)
 
  • CSS:大师!我感觉我在传承了Houdini的灵力加持后功力大增!

  • 大师:那尼玛是因为你一开始的内力。。。emmm

啊~下面又到了我最喜欢的互怼环节了呀

  1. 告别CSS

  2. 为什么CSS一开始这么难学

  3. 前端工程师讨厌写CSS是什么心态?

为什么说Houdini是CSS漫长的成人礼?

至今为止,刚刚在can i use上查到的结果显示,目前houdini的七大特性,除了Paint API和TypedOM外,其余几个API在浏览器上可以说都是全军覆没的状态(或者说刚刚萌芽更合适一些?),就算是Paint API也好,它也仅仅只在Edge76,Chrome66和Opera52以上实现了技术扎根, 其余浏览器,哪怕是IE,Firefox,Safari的最新版本,也都尚未实现
 
下面这张是谷歌上搜到的,2018年底制作,现在可以认为绝大部分仍然适用
 
可能有同学会问了,上面写的Chrome-Canary是什么意思呢?额。。。canary直译为“金丝雀”,属于和dev,beta相类似的版本的概念范畴,(你就理解为内测版吧,逃~)根据相关资料提示,Layout API在Chrome-Canary上实现部分支持,但是我试用了一下发现还是用不了(心塞),控制台CSS.layoutWorklet打出来是undefined,所以评论区有高人还请指教下啦~

Chrome-Canary中国区下载链接

实战Houdini之Paint API

那咱们就写一个咱们可以在Chrome上跑的demo好了
 
首先,我们需要编写一个JavaScript文件,我们命名为paint.js,然后通过registerPaint方法注册一个paint方法,paint方法可以绘制div的背景,例如下面我们把这个paint方法命名为circle,这意味着它可以通过background: paint(circle)去使用绘制的画布。我们上面也说过,我们注册paint方法时系统会提供ctx作为参数,这个ctx是HTML5/Canvas的2Dcontext的子集,实现了除了文字操作外的大多数方法和属性。(文字操作指的是ctx.fillText或者ctx.strokeText这一类方法)。
 
下面我们来通过JS注册一个paint方法,来为div添加一个background,这个paint方法命名为circle,它的功能是为div提供一个半径为Math.min(长,宽)的实心圆,圆的背景色可在CSS的上下文代码块中通过--color这个属性名指定。
paint.js的全部代码如下
// paint.js
registerPaint('circle', class {
// 决定了paint方法中props中能获取的CSS属性值
static get inputProperties() { return ['--color']; } // 绘制一个半径为长或宽的最小值的圆形作为背景
// ctx是Canvas的ctx的子集,实现了除文字操作外的大多数方法和属性
paint(ctx, size, props) {
// size表示使用该paint方法的div的长和宽
const width = size.width / 2;
const height = size.height / 2;
const radius = Math.min(width, height);
// props.get表示将根据inputProperties返回的键值从CSS代码块中获取相应属性
const color = props.get('--color');
// 给画笔着色
ctx.fillStyle = color;
// 开始动笔绘制
ctx.beginPath();
// 以width,height为圆心,radius为半径画圆圈,从0度画到360度
ctx.arc(width, height, radius, 0, 2 * Math.PI);
// 用fillstyle把圆圈轨迹内部进行颜色填充
ctx.fill();
// 搞定!
}
});

(代码中的具体API我们过会再仔细解释,我们先把代码跑通再说)

然后,仅仅这样做是不够的,我们还需要在主线程里,例如main.html的脚本里。通过下面这个API去加载我们刚刚定义的paint.js
CSS.paintWorklet.addModule('paint.js');

注意,paint.js内部会形成一个封闭而独立的,叫worklet的作用域,它和全局Window是不一样的!不要在这里尝试使用fetch等方法。

上面两步做完了,我们就可以使用CSS去使用我们刚刚定义的paint函数了
<!-- HTML -->
<div class="foo"></div>
<!-- CSS -->
<style>
.foo {
border: 1px solid blue;
width: 200px;
height: 200px;
/*指定背景色为红色*/
--color: red;
/*使用刚刚注册的paint方法*/
background-image: paint(circle);
}
</style>

我们看下效果

github项目代码如下

https://github.com/penghuwan/houdini-module

好,我们回过头来解释下paint方法里面的逻辑
(1)size 它是一个对象,保存了使用这个定义paint方法的div的长和宽,可以分别通过size.width和size.height去访问
registerPaint('circle', class {
// ctx是Canvas的ctx的子集,实现了除文字操作外的大多数方法和属性
paint(ctx, size, props) {
// size表示使用该paint方法的div的长和宽
const width = size.width / 2;
const height = size.height / 2;
// ...
}
});
(2)props:我们可以通过props参数获取CSS上下文代码块(指的是paint(circle)在的那个代码块)的其他CSS属性,但是这个属性需要在inputProperties函数中进行声明,声明的方法是在函数中返回一个数组,数组项为属性名称
// paint.js
registerPaint('circle', class {
// 决定了paint方法中props中能获取的CSS属性值
static get inputProperties() { return ['--color']; }
// ctx是Canvas的ctx的子集,实现了除文字操作外的大多数方法和属性
paint(ctx, size, props) {
const color = props.get('--color');
}
});
// style
.foo {
/*指定背景色为红色*/
--color: red;
/*使用刚刚注册的paint方法*/
background-image: paint(circle);
}
(3)ctx:这个参数上文已经多次介绍,这里不再赘述
 

警告,下面讲的都是当前没有任何stable浏览器可以运行的代码,我是根据W3C的草案和示范代码要求来的,正所谓——姜太公写代码,愿者Debug

Layout

<抱歉写的太累了,休息下,本部分待会再更>

Animation

<抱歉写的太累了,休息下,本部分待会再更>

Propertis和values

<抱歉写的太累了,休息下,本部分待会再更>

Typed OM

<抱歉写的太累了,休息下,本部分待会再更>

CSS!你的Houdini来啦

但是你用不了,哈哈哈哈!

 
本文完

参考资料

  1. Houdini:CSS 领域最令人振奋的革新

  2. Chrome提供的Houdini Demo

  3. 1中Demo的在线运行地址(注意很多是暂时跑不了的)

  4. layout的API草案(W3C)

  5. Painting API的入门指导

  6. Parser API草案(W3C)

  7. AnimationWorklet工作草案(W3C)

给大家一点点建议,谷歌英文资料吧。。。很多干货

【CSS】Houdini, CSS的成人礼的更多相关文章

  1. CSS Houdini:用浏览器引擎实现高级CSS效果

    vivo 互联网前端团队-Wei Xing Houdini被称之为Magic of styling and layout on the web,看起来十分神秘,但实际上,Houdini并非什么神秘组织 ...

  2. CSS Vocabulary – CSS 词汇表,你都掌握了吗?

    CSS 是前端开发必备技能,入门容易,深入难.比如像 Pseudo-class.Pseudo-element.Media query.Media type 以及 Vendor prefix 的概念,很 ...

  3. css样式 --- CSS hack

    前端样式,虽然不是经常需要hack,但是我们经常会遇到各浏览器表现不一致的情况.基于此,某些情况我们会极不情愿的使用这个不太友好的方式来达到大家要求的页面表现.我个人是不太推荐使用hack的,要知道一 ...

  4. CSS Sprites (CSS图像拼合技术)教程工具

    什么是CSS Sprites? “Sprite”(精灵)这个词在计算机图形学中有它独特的定义,由于游戏.视频等画质越来越高,必须有一种技术可以智能的处理材质和贴图,并且要 同时保持画面流畅.“Spri ...

  5. CSS:CSS定位和浮动

    CSS2.1规定了3种定位方案 1.Normal flow:普通流(相对定位 position relative.静态定位 position static) 普通流(normal flow,国内有人翻 ...

  6. CSS之CSS hack

    由于不同的浏览器对CSS的支持及解析结果不一样,还由于CSS中的优先级的关系.我们就可以根据这个来针对不同的浏览器来写不同的CSS. CSS Hack大致有3种表现形式,CSS类内部Hack.选择器H ...

  7. HTML+CSS笔记 CSS笔记集合

    HTML+CSS笔记 表格,超链接,图片,表单 涉及内容:表格,超链接,图片,表单 HTML+CSS笔记 CSS入门 涉及内容:简介,优势,语法说明,代码注释,CSS样式位置,不同样式优先级,选择器, ...

  8. CSS:CSS学习总结

    CSS:CSS学习总结 背景 CSS是一种声明式的语言,学好CSS的难度甚至大于学好一门服务器语言(我个人的感觉),这周在学习CSS,就记录一下学习经验. 1.规则声明顺序 因为CSS的样式具备层叠性 ...

  9. CSS Sprites (css精灵)

    CSS Sprites CSS Sprites在国内很多人叫css精灵,是一种网页图片应用处理方式.它允许你将一个页面涉及到的所有零星图片都包含到一张大图中去,这样一来,当访问该页面时,载入的图片就不 ...

随机推荐

  1. RabbitMQ延迟消息的延迟极限是多少?

    之前在写Spring Cloud Stream专题内容的时候,特地介绍了一下如何使用RabbitMQ的延迟消息来实现定时任务.最近正好因为开发碰到了使用过程中发现,延迟消息没有效果,消息直接就被消费了 ...

  2. windows下挂载linux的nfs网络硬盘

    挂载命令,速度快 mount \\10.8.200.167\goworkspace z: -o nolock,rsize=1024,wsize=1024,timeo=15 安装步骤 yum insta ...

  3. python课堂整理1

      1.变量 变量只能由字母.数字.下划线组成 特例:1.变量不能用数字开头    2.不能是python的关键字 3.最好不要和python内置的东西重复 让变量名有意义 些 python3的关键字 ...

  4. sort+结构体+简单数学+暴力-例题

    A-前m大的数 还记得Gardon给小希布置的那个作业么?(上次比赛的1005)其实小希已经找回了原来的那张数表,现在她想确认一下她的答案是否正确,但是整个的答案是很庞大的表,小希只想让你把答案中最大 ...

  5. python post接口测试第一个用例日记

    如下是我自己公司的一个请求,学习过程顺便记录下,都是白话语言,不那么专业,不喜勿喷! 首先看下图,post请求一般需要填写参数url, data(一般是表格类型的参数,如我们智联驾驶APP登录的参数) ...

  6. 【MySQL】ON DUPLICATE KEY UPDATE

    之前没用过这个操作,甚至没见过--最近接触到,而且还挺有用. 作用:若 KEY 不重复,则插入记录:否则更新记录. 单条操作: INSERT INTO table(a, b, c) VALUES (1 ...

  7. superset安装文档

    1 安装python3.6 yum install epel-release -y yum install https://centos7.iuscommunity.org/ius-release.r ...

  8. Android Studio项目/Flutter 案例中Gradle报错通用解决方案(包括Unable to tunnel through proxy问题)

    目录 Step 1:修改Gradle版本为本地版本 Step 2:修改classpath为Android Studio版本 Step 3:关闭代理 Step 1:修改Gradle版本为本地版本     ...

  9. Spring中FactoryBean的作用和实现原理

    BeanFactory与FactoryBean,相信很多刚翻看Spring源码的同学跟我一样很好奇这俩货怎么长得这么像,分别都是干啥用的.BeanFactory是Spring中Bean工厂的顶层接口, ...

  10. css3系列之transform 详解rotate

    rotate rotateX rotateY rotateZ rotate3d rotate: 旋转该元素,配合着transform-origin属性,transform-origin 是设置旋转点的 ...