- 做者:陈大鱼头
- github: KRISACHAN
最近据说TypeScript3.7添加了对Optional Chaining的支持,而后就想着给鱼头的脚手架ying-template的TS版本升级,而后在命令行发现这样的一句信息:javascript
'postcss-cssnext' 已经被 'postcss-preset-env'代替了。详情请查看 moox.io/blog/deprec…css
其实鱼头的脚手架里早就把postcss-cssnext
换成了postcss-preset-env
,不过一直没删,可是看到这句话以后,处于好奇,就去翻了翻PostCSS的官网,而后又思考了下这些年CSS的发展历程,遂有这篇文章的出炉。html
从1997年 CSS1.0
发布到现在,从最开始只支持简单的文字排版到现在已经能够作出酷炫的3D动画,CSS已经走过了22个年头,其发展如图所示:前端
[图片来自MDN]java
随着互联网的发展,人们对网页的要求已是从只要展现图文就好变成了各类交互跟视觉效果都须要有着更多的体验要求。CSS为此也是不断的更新着。webpack
随着web业务日益复杂化和多元化,前端开发也从单纯的web page转变成web app,在此也诞生了“前端工程化”的概念,一个完备的web app每每会很大很复杂,甚至会有不少人共同维护,以往的拼页面,写jQuery已是不足以支撑现代的需求。一样的,CSS也是如此,再也不是内联写几个margin
,padding
或者HTML一股脑引入几个CSS就足够的,并且因为人员配置的增多,不一样的开发,命名习惯,样式是否会冲突也是必需要考虑的。git
除了工程问题,还有就是CSS与浏览器之间的关系也是咱们不得不考虑的,虽然CSS发展的很快,可是浏览器对CSS新特性支持的进度确实很是缓慢的。因此虽然某些属性已经推出了不少年,可是也每每由于浏览器的缘由而没法进行大规模的使用。github
虽然在实际开发过程当中,CSS有着这样那样让人没法忽略的问题,可是“方法总比困难多”,在前端界也有许多热心的大牛们在尝试着解决这些问题。此次让鱼头与你们一块儿分享下这些与CSS相关的技巧与方法。web
命名一直是开发者比较头疼的问题,在前端里,除了JS各类变量的命名,还有元素class的命名,虽然咱们能够随意起名,愿意的话甚至可使用
.a .b .c
等无心义的规则来命名,可是若是是一个长期的,大型的或多人协做的项目里这么命名,恐怕容易被人胖揍。此次咱们来分享下业界经常使用的用来防挨揍的命名规则。typescript
OOCSS有两个编写原则:
咱们来看看官网的一个例子:
<div class="mod grab">
<b class="top">
<b class="tl"></b>
<b class="tr"></b>
</b>
<div class="inner">
<div class="hd">
<h3>grab</h3>
</div>
<div class="bd">
<p>Body</p>
</div>
</div>
<b class="bottom">
<b class="bl"></b>
<b class="br"></b>
</b>
</div>
复制代码
在这里.mod
是父类,全部的类都是继承自它,.grab
即是子类。
至于.top
、.inner
与bottom
,顾名思义就是不一样位置的子盒子。
这里是以“容器”为命名法则。
BEM 是块(Block)、 元素(Element)、修饰符( Modifier)的单词集合。
在选择器中,咱们用如下三种符号来表示以上内容
-
中划线 :仅做为连字符使用,表示某个块或者某个子元素的多单词之间的链接记号。__
双下划线:双下划线用来链接块和块的子元素_
单下划线:单下划线用来描述一个块或者块的子元素的一种状态就像这样:type-block__element_modifier
官网的例子以下:
<style> .button { display: inline-block; border-radius: 3px; padding: 7px 12px; border: 1px solid #D5D5D5; background-image: linear-gradient(#EEE, #DDD); font: 700 13px/18px Helvetica, arial; } .button--state-success { color: #FFF; background: #569E3D linear-gradient(#79D858, #569E3D) repeat-x; border-color: #4A993E; } .button--state-danger { color: #900; } </style>
<button class="button">
Normal button
</button>
<button class="button button--state-success">
Success button
</button>
<button class="button button--state-danger">
Danger button
</button>
复制代码
SMACSS,一个长得很像OOCSS的规则。
核心只有如下6个:
修饰符是--
,子模块是__
官网的例子以下:
<style> #header { … } #primarynav { … } #maincontent { … } </style>
<div id="header"></div>
<div id="primarynav"></div>
<div id="maincontent"></div>
复制代码
CSS 预处理器是一个能让你经过预处理器本身独有的语法来生成CSS的程序。市面上有不少CSS预处理器可供选择,且绝大多数CSS预处理器会增长一些原生CSS不具有的特性,例如代码混合,嵌套选择器,继承选择器等。这些特性让CSS的结构更加具备可读性且易于维护。
sass是诞生最先,也是世界上最成熟、最稳定、最强大的专业级CSS扩展语言!(官网说的(O_o)?? )
sass可用使用变量,嵌套规则,混合器,继承等编程语言才有的概念,代码例子以下:
$nav-color: #F90;
nav {
$width: 100px;
width: $width;
color: $nav-color;
}
//编译后
nav {
width: 100px;
color: #F90;
}
复制代码
Less 是一门 CSS 预处理语言,它扩展了 CSS 语言,增长了变量、Mixin、函数等特性,使 CSS 更易维护和扩展。
代码例子以下:
@base: #f938ab;
.box-shadow(@style, @c) when (iscolor(@c)) {
-webkit-box-shadow: @style @c;
box-shadow: @style @c;
}
.box-shadow(@style, @alpha: 50%) when (isnumber(@alpha)) {
.box-shadow(@style, rgba(0, 0, 0, @alpha));
}
.box {
color: saturate(@base, 5%);
border-color: lighten(@base, 30%);
div { .box-shadow(0 0 5px, 30%) }
}
// 编译后
.box {
color: #fe33ac;
border-color: #fdcdea;
}
.box div {
-webkit-box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
}
复制代码
Stylus,富于表现力、动态的、健壮的 CSS
代码例子以下:
body
font 12px Helvetica, Arial, sans-serif
a.button
border-radius 5px
复制代码
彻底不须要{} : ;
的预处理器,我的是特别不喜欢这种写法,可是对于不少喜欢简洁的开发者来讲,这确实很是好的编写方式
有点时候眼看CSS出来新的属性,可是由于浏览器兼容的问题,因此每每是只能看而不能用,即使有的属性能够用,但也由于各浏览器的现实状况而存在乎想不到的BUG,那么这就意味着一个属性出来以后咱们要等到5年甚至更久以后才能使用吗?都9012年了耶?
固然不是,接下来咱们能够了解一下这个如魔法师通常的存在 —— CSS Houdini
CSS Houdini是一组底层API,它们公开了CSS引擎的各个部分,从而使开发者能够经过这组API来扩展CSS。它让开发者拥有了直接访问CSSOM的能力,开发者能够经过这组API来编写浏览器可解析的CSS代码,这让开发者能够在不须要等待浏览器的实现的前提下实现本身想要的CSS功能。
[图片来自:www.qed42.com/blog/buildi…]
如上所示,不一样的API所对应的就是浏览器不一样的渲染环节,用时下流行的概念来解释就是浏览器加载时不一样生命周期的钩子函数。
简单来讲,CSS Houdini就是JS IN CSS,niubility ..
咱们可访问的7个API以下:
Mmmm,虽然是有7个API(Houdini drafts上还有一些),但浏览器实际的支持状况实际上是这样的:
[图片来自:ishoudinireadyyet.com/]
CSS Houdini的工做流程以下:
[图片来自:www.qed42.com/blog/buildi…]
本篇不打算细讲CSS Houdini,因此不会画出全部的DEMO,有兴趣的能够查看底部的“资料来源”,从而获取更加详细的信息。
Typed OM
<style> * { margin: 0; padding: 0; } .box { background: linear-gradient(to right, #2c3e50, #4ca1af); } </style>
<div class="box" id="box"></div>
<script> 'use strict' box.attributeStyleMap.set('width', CSS.px(200)) box.attributeStyleMap.set('height', CSS.px(200)) const [x, y] = 'width,height' .split(',') .map(val => Number.parseInt(box.computedStyleMap().get(val))) box.attributeStyleMap.set('transform', new CSSTranslate(CSS.px(x), CSS.px(y))) console.log(box.computedStyleMap().get('transform')) console.log(window.getComputedStyle(box, null)['transform']) </script>
复制代码
上面就是Typed OM的示例,这里值得一提的就是,若是咱们用getComputedStyle
去获取transform
的值,最终结果是个矩阵,这其实不太方便咱们作二次操做,可是用Typed OM的JS API computedStyleMap
,去取的结果就是一个具体属性的集合,这是很是有利于咱们进行二次操做的。
Paint API
Paint API就是容许你例如Canvas的属性来编写CSS样式,使用方法也很简单,咱们能够看看slides.iamvdo.me/waq19/#/35上的示例
首先咱们新建个文件叫registerPaint.js
,在里面写下如下代码:
registerPaint('circle-ripple', class {
static get inputProperties() { return [ '--circle-color',
'--circle-radius', '--circle-x', '--circle-y'
]}
paint(ctx, geom, props, args) {
const x = props.get('--circle-x').value;
const y = props.get('--circle-y').value;
const radius = props.get('--circle-radius').value;
}
}
复制代码
而后再新建一个index.html
,而且在JS代码里注册上面写好的registerPaint.js
,方式以下:CSS.paintWorklet.addModule('registerPaint.js');
具体代码以下:
<style> .el { --circle-radius: 0; --circle-color: deepskyblue; background-image: paint(circle-ripple); } .el.animating { transition: --circle-radius 1s, --circle-color 1s; --circle-radius: 300; --circle-color: transparent; } </style>
<div class="el" id="el"></div>
<script> 'use strict' CSS.paintWorklet.addModule('registerPaint.js'); el.addEventListener('click', e => { el.classList.add('animating'); el.attributeStyleMap.set('--circle-x', e.offsetX); el.attributeStyleMap.set('--circle-y', e.offsetY); }); </script>
复制代码
因此咱们有如下的效果:
说到底CSS Houdini其实也只是JS IN CSS,并非纯正的CSS,那么对于一些新的CSS属性,咱们相用的话,真的还得等5年后吗?还有即使是有各类工具,可是像一些兼容性写法,厂商前缀,循环,原生CSS也没有,咱们不是还得须要依赖CSS预处理器吗?
其实也不是,这时候咱们能够利用CSS届的Babel —— PostCSS
简单来讲PostCSS就是可让开发者使用JS来处理CSS的处理器,它分了如下5大类功能:
利用从 Can I Use 网站获取的数据为 CSS 规则添加特定厂商的前缀。Autoprefixer 自动获取浏览器的流行度和可以支持的属性,并根据这些数据帮你自动为 CSS 规则添加前缀。
例如咱们输入如下代码:
:fullscreen {
}
复制代码
那么就会输出:
:-webkit-:full-screen {
}
:-moz-:full-screen {
}
:full-screen {
}
复制代码
PostCSS Preset Env 帮你将现代 CSS 语法转换成大多数浏览器都能理解的东西,根据你的目标浏览器或运行时环境来肯定你须要的 polyfills,基于 cssdb 实现。
例如咱们输入如下代码:
@custom-media --med (width <= 50rem);
@media (--med) {
a {
&:hover {
color: color-mod(black alpha(54%));
}
}
}
复制代码
就会输出:
@media (max-width: 50rem) {
a:hover {
color: rgba(0, 0, 0, 0.54);
}
}
复制代码
CSS 模块 就是说你永远不用担忧命名太大众化而形成冲突太普通,只要用最有意义的名字就好了。
例如咱们输入如下代码:
.name {
color: gray;
}
复制代码
就会输出:
.Logo__name__SVK0g {
color: gray;
}
复制代码
经过使用 stylelint 强化一致性约定并避免样式表中的错误,stylelint 是一个现代化 CSS 代码检查工具。它支持最新的 CSS 语法,包括相似 CSS 的语法,例如 SCSS 。
例如咱们输入如下代码:
a {
color: #d3;
}
复制代码
那么控制台会抛出错误:
app.css
2:10 Invalid hex color
复制代码
LostGrid 利用 calc() 和你所定义的分割方式来建立网格系统,无需传递大量参数。
例如咱们输入如下代码:
div {
lost-column: 1/3
}
复制代码
就会输出:
div {
width: calc(99.9% * 1/3 -
(30px - 30px * 1/3));
}
div:nth-child(1n) {
float: left;
margin-right: 30px;
clear: none;
}
div:last-child {
margin-right: 0;
}
div:nth-child(3n) {
margin-right: 0;
float: right;
}
div:nth-child(3n + 1) {
clear: both;
}
复制代码
cssdb是postcss-preset-env的实现基准,主要就是CSS的新功能功能及这些功能从提出到成为标准时所在的进程。
cssdb跟ecma同样,对新属性分了不一样的进程,具体的进程以下:
这就是postcss-preset-env依赖的实现基准,那么若是咱们想要在咱们的代码里使用这些Stage,该怎么作呢?
以个人脚手架ying-template
为例,咱们来查看在webpack中的实际配置:
首先咱们先安装postcss以及其相应的插件:
npm install postcss postcss-loader postcss-preset-env postcss-nesting --save-dev
复制代码
而后咱们在webpack的config配置module中输入如下配置:
module: {
rules: [
{
test: /\.css$/,
include,
exclude,
use: [/* 你其它的loader */ 'postcss-loader']
}
]
}
复制代码
而后在根目录新建一个postcss.config.js
const postcssConfig = {
plugins: {
precss: {},
'postcss-preset-env': {
browsers: 'last 2 versions', // 浏览器兼容的版本
stage: 3 // 你用的属性所在的阶段
},
'postcss-nesting': {} // 这里就是你所使用的插件
}
};
module.exports = postcssConfig
复制代码
这样就完成了,若是想看完整的配置,能够clone个人脚手架:github.com/KRISACHAN/y…
(这是个多页面的webpack4脚手架,集成了babel 7,precss 4,typescript3.7,karma以及eslint等现代前端开发所需经常使用的东西,有兴趣的能够去看看。)
咱们能够经过preset-env.cssdb.org/playground这个网站来查看具体的编译结果。
编译结果图以下:
是否是很是神奇呢?
随着前端工程的普及,某E浏览器的没落,CSS的发展可谓是一日千里,近日也有一些数学属性的提案在发起,之后会发展成什么样,没人能够知道。只是总的来讲,CSS的将来是一片光明的。本文简单分享了一些现代化的CSS知识,经过这些知识,咱们很容易就能写出完备且现代化的CSS代码,可以给创造出更多的效益,但愿你们能够积极地用起这些知识,并对CSS能够有更多的思考以及想象。
CSS,将来可期
若是你、喜欢探讨技术,或者对本文有任何的意见或建议,你能够扫描下方二维码,关注微信公众号“ 鱼头的Web海洋 ”,随时与鱼头互动。欢迎!衷心但愿能够碰见你。