【CSS】来自新时代的CSS
•作者:陈大鱼头•github: KRISACHAN[1]
前言
最近听说TypeScript3.7添加了对Optional Chaining[2]的支持,然后就想着给鱼头的脚手架ying-template[3]的TS版本升级,然后在命令行发现这样的一句信息:
'postcss-cssnext' 已经被 'postcss-preset-env'代替了。详情请查看 https://moox.io/blog/deprecating-cssnext/
其实鱼头的脚手架里早就把postcss-cssnext
换成了postcss-preset-env
,不过一直没删,但是看到这句话之后,处于好奇,就去翻了翻PostCSS的官网,然后又思考了下这些年CSS的发展历程,遂有这篇文章的出炉。
浅谈现代化的CSS
从1997年 CSS1.0
发布到如今,从最开始只支持简单的文字排版到如今已经可以做出酷炫的3D动画,CSS已经走过了22个年头,其发展如图所示:
[图片来自MDN[4]]
随着互联网的发展,人们对网页的要求已经是从只要展示图文就好变成了各种交互跟视觉效果都需要有着更多的体验要求。CSS为此也是不断的更新着。
随着web业务日益复杂化和多元化,前端开发也从单纯的web page转变成web app,在此也诞生了“前端工程化”的概念,一个完备的web app往往会很大很复杂,甚至会有很多人共同维护,以往的拼页面,写jQuery已经是不足以支撑现代的需求。同样的,CSS也是如此,不再是内联写几个margin
,padding
或者HTML一股脑引入几个CSS就足够的,而且由于人员配置的增多,不同的开发,命名习惯,样式是否会冲突也是必须要考虑的。
除了工程问题,还有就是CSS与浏览器之间的关系也是我们不得不考虑的,虽然CSS发展的很快,但是浏览器对CSS新特性支持的进度确实非常缓慢的。所以虽然某些属性已经推出了很多年,但是也往往因为浏览器的原因而无法进行大规模的使用。
虽然在实际开发过程中,CSS有着这样那样让人无法忽略的问题,但是“方法总比困难多”,在前端界也有许多热心的大牛们在尝试着解决这些问题。这次让鱼头与大家一起分享下这些与CSS相关的技巧与方法。
最初的CSS模块化 —— CSS命名规则
命名一直是开发者比较头疼的问题,在前端里,除了JS各种变量的命名,还有元素class的命名,虽然我们可以随意起名,愿意的话甚至可以使用
.a .b .c
等无意义的规则来命名,但是如果是一个长期的,大型的或多人协作的项目里这么命名,恐怕容易被人胖揍。这次我们来分享下业界常用的用来防挨揍的命名规则。
OOCSS(Object-Oriented CSS)
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
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
SMACSS,一个长得很像OOCSS的规则。
核心只有以下6个:
•Base:页面的基本样式命名规则•Layout:布局命名规则•Module:模块规命名规则•State:状态命名规则•Theme:主题命名规则•Changing State:可变状态的命名规则
修饰符是--
,子模块是__
官网的例子如下:
<style>#header { … }#primarynav { … }#maincontent { … }
</style>
<div id="header"></div>
<div id="primarynav"></div>
<div id="maincontent"></div>
为CSS赋能 —— 预处理器
CSS 预处理器是一个能让你通过预处理器自己独有的语法来生成CSS的程序。市面上有很多CSS预处理器可供选择,且绝大多数CSS预处理器会增加一些原生CSS不具备的特性,例如代码混合,嵌套选择器,继承选择器等。这些特性让CSS的结构更加具有可读性且易于维护。
sass
sass是诞生最早,也是世界上最成熟、最稳定、最强大的专业级CSS扩展语言!(官网说的(O_o)?? )
sass可用使用变量,嵌套规则,混合器,继承等编程语言才有的概念,代码例子如下:
$nav-color: #F90;
nav {$width: 100px;width: $width;color: $nav-color;
}//编译后nav {width: 100px;color: #F90;
}
less
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
Stylus,富于表现力、动态的、健壮的 CSS
代码例子如下:
bodyfont 12px Helvetica, Arial, sans-serifa.buttonborder-radius 5px
完全不需要{} : ;
的预处理器,个人是特别不喜欢这种写法,但是对于很多喜欢简洁的开发者来说,这确实非常好的编写方式
如魔法师一般的存在 —— CSS Houdini
有点时候眼看CSS出来新的属性,但是因为浏览器兼容的问题,所以往往是只能看而不能用,即便有的属性可以用,但也因为各浏览器的现实情况而存在意想不到的BUG,那么这就意味着一个属性出来之后我们要等到5年甚至更久之后才能使用吗?都9012年了耶?
当然不是,接下来我们可以了解一下这个如魔法师一般的存在 —— CSS Houdini
CSS Houdini是什么?
CSS Houdini是一组底层API,它们公开了CSS引擎的各个部分,从而使开发者可以通过这组API来扩展CSS。它让开发者拥有了直接访问CSSOM的能力,开发者可以通过这组API来编写浏览器可解析的CSS代码,这让开发者可以在不需要等待浏览器的实现的前提下实现自己想要的CSS功能。
[图片来自:https://www.qed42.com/blog/building-powerful-custom-properties-CSS-houdini]
如上所示,不同的API所对应的就是浏览器不同的渲染环节,用时下流行的概念来解释就是浏览器加载时不同生命周期的钩子函数。
简单来说,CSS Houdini就是JS IN CSS,niubility ..
CSS Houdini是怎么工作的?
我们可访问的7个API如下:
1.Typed OM API2.Properties & Values API3.Paint API4.Layout API5.Animation worklet6.Parser API7.Font Metrics API
Mmmm,虽然是有7个API(Houdini drafts上还有一些),但浏览器实际的支持情况其实是这样的:
[图片来自:https://ishoudinireadyyet.com/]
CSS Houdini的工作流程如下:
[图片来自:https://www.qed42.com/blog/building-powerful-custom-properties-CSS-houdini]
1.钩子进入渲染的进程中2.JS是这个钩子的核心3.使用JS的Typed OM,可以挂载自定义的属性,绘制图形,布局以及动画4.还有其他两个API:Parser API 和 Font Metrics API。它们用于注册CSS相关的新事物
一些示例
本篇不打算细讲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样式,使用方法也很简单,我们可以看看https://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界的Babel —— PostCSS
说到底CSS Houdini其实也只是JS IN CSS,并不是纯正的CSS,那么对于一些新的CSS属性,我们相用的话,真的还得等5年后吗?还有即便是有各种工具,但是像一些兼容性写法,厂商前缀,循环,原生CSS也没有,我们不是还得需要依赖CSS预处理器吗?
其实也不是,这时候我们可以利用CSS界的Babel —— PostCSS
PostCSS是什么?
简单来说PostCSS就是可以让开发者使用JS来处理CSS的处理器,它分了以下5大类功能:
增强代码的可读性
利用从 Can I Use 网站获取的数据为 CSS 规则添加特定厂商的前缀。Autoprefixer[5] 自动获取浏览器的流行度和能够支持的属性,并根据这些数据帮你自动为 CSS 规则添加前缀。
例如我们输入以下代码:
:fullscreen {
}
那么就会输出:
:-webkit-:full-screen {
}
:-moz-:full-screen {
}
:full-screen {
}
将未来的 CSS 特性带到今天!
PostCSS Preset Env[6] 帮你将现代 CSS 语法转换成大多数浏览器都能理解的东西,根据你的目标浏览器或运行时环境来确定你需要的 polyfills,基于 cssdb 实现[7]。
例如我们输入以下代码:
@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
CSS 模块[8] 就是说你永远不用担心命名太大众化而造成冲突太普通,只要用最有意义的名字就行了。
例如我们输入以下代码:
.name {color: gray;
}
就会输出:
.Logo__name__SVK0g {color: gray;
}
避免 CSS 代码中的错误
通过使用 stylelint 强化一致性约定并避免样式表中的错误[9],stylelint 是一个现代化 CSS 代码检查工具。它支持最新的 CSS 语法,包括类似 CSS 的语法,例如 SCSS 。
例如我们输入以下代码:
a { color: #d3;
}
那么控制台会抛出错误:
app.css
2:10 Invalid hex color
强大的网格系统
LostGrid[10] 利用 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
cssdb是postcss-preset-env的实现基准,主要就是CSS的新功能功能及这些功能从提出到成为标准时所在的进程。
cssdb跟ecma一样,对新属性分了不同的进程,具体的进程如下:
1.Stage 0:脑袋风暴阶段。高度不稳定,可能会发生变化。2.Stage 1:实验阶段。也非常不稳定,可能会发生变化,但是该提案已得到W3C成员的认可。3.Stage 2:承认阶段。高度不稳定并且可能会发生变化,但是正在积极研究中。4.Stage3:拥抱阶段。稳定且变化不大,此功能可能会成为标准。5.Stage4:标准阶段。最终的解决方案,所有主流浏览器都支持。
这就是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我的脚手架:https://github.com/KRISACHAN/ying-template
(这是个多页面的webpack4脚手架,可以使用ES6+语法,TypeScript,各类CSS处理器,ESLint以及单元测试等现代前端开发所需常用的东西,有兴趣的可以去看看。)
我们可以通过https://preset-env.cssdb.org/playground这个网站来查看具体的编译结果。
编译结果图如下:
是不是非常神奇呢?
后话
随着前端工程的普及,某E浏览器的没落,CSS的发展可谓是一日千里,近日也有一些数学属性的提案在发起,以后会发展成什么样,没人可以知道。只是总的来说,CSS的未来是一片光明的。本文简单分享了一些现代化的CSS知识,通过这些知识,我们很容易就能写出完备且现代化的CSS代码,能够给创造出更多的效益,希望大家可以积极地用起这些知识,并对CSS可以有更多的思考以及想象。
CSS,未来可期
资料来源
1.https://developer.mozilla.org/zh-CN/docs/Archive/CSS32.http://oocss.org/3.http://getbem.com/4.http://smacss.com/5.https://sass-lang.com/6.http://lesscss.org/7.http://stylus-lang.com/8.https://blog.techbridge.cc/2017/05/23/css-houdini/9.https://www.smashingmagazine.com/2016/03/houdini-maybe-the-most-exciting-development-in-css-youve-never-heard-of/10.https://slides.iamvdo.me/waq19/fr/11.https://www.qed42.com/blog/building-powerful-custom-properties-CSS-houdini12.https://www.postcss.com.cn/13.https://cssdb.org/#staging-process14.https://s0dev0to.icopy.site/adrianbdesigns/postcss-preset-env-babel-for-css-12hp
References
[1]
KRISACHAN: https://github.com/KRISACHAN
[2]
Optional Chaining: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#optional-chaining
[3]
ying-template: https://github.com/KRISACHAN/ying-template
[4]
MDN: https://developer.mozilla.org/zh-CN/docs/Archive/CSS3
[5]
Autoprefixer: https://github.com/postcss/autoprefixer
[6]
PostCSS Preset Env: https://preset-env.cssdb.org/
[7]
cssdb 实现: https://cssdb.org/
[8]
CSS 模块: https://github.com/css-modules/css-modules
[9]
stylelint 强化一致性约定并避免样式表中的错误: http://stylelint.io/
[10]
LostGrid: https://github.com/peterramsing/lost
回复“加群”与大佬们一起交流学习~
点击“阅读原文”查看70+篇原创文章
【CSS】来自新时代的CSS相关推荐
- css 图片自适应_104道 CSS 面试题,助你查漏补缺(下)
(给前端大全加星标,提升前端技能) 作者:CavsZhouyou https://github.com/CavsZhouyou/Front-End-Interview-Notebook/blob/ma ...
- [CSS]30种时尚的CSS网站导航条
[原文地址]:http://coolshell.cn/?p=562 我想,大家在上网的时候一定见过很多很多种各式各样的网站导航条的设计.这些导航条基本上来说都是用CSS来做的.这里,我们将向你介绍几种 ...
- css text top,text-align属性(css中文本对齐属性)
text-align属性 设置h1.h2.h3元素的文本对齐方法: h1{text-align:center} h2{text-align:left} h3{text-align:right} 亲自试 ...
- 【CSS】【14】CSS中使用背景图像
默认情况下背景图像会自动向水平和竖直两个方向平铺,如果不希望不平铺,或者只希望沿一个方向平铺,可以使backgroud-repeat属性来控制,该属性可以取以下4种之一 repeat:沿水平和竖直两个 ...
- css php html介绍,对CSS知识的简单介绍
1.CSS定义 CSS 指层叠样式表 (Cascading Style Sheets),是一种样式表语言,用来描述 HTML 或 XML(包括如 SVG.XHTML 之类的 XML 分支语言)文档的呈 ...
- Atitit.css 规范 bem 项目中 CSS 的组织和管理
Atitit.css 规范 bem 项目中 CSS 的组织和管理 1. 什么是BEM?1 1.1. 块(Block)2 1.2. 元素(Element)2 1.3. BEM树(和DOM树类似).3 ...
- vue 导入公共css_HTML+CSS入门 vue引入通用CSS
本篇教程介绍了HTML+CSS入门 vue引入通用CSS,希望阅读本篇文章以后大家有所收获,帮助大家HTML+CSS入门. < 1.在入口 js 文件 main.js 中引入,一些公共的样式文件 ...
- CSS Dock Menu:JS+CSS 仿苹果MAC机桌面导航菜单
所需源文件--见下方文件附件 在HTML中的<head>标签中插入如下代码: <script type="text/javascript" src="j ...
- html css web笔记,Web/HTML/CSS/的笔记
一.web基本介绍 1.Web 是 Worl wide web 的缩写,称为全球广域网,俗称www 2.我们可以将Web理解为当前的一种互利网,对于我们来说更多的就是网站服务. 3.网站我们可以认为是 ...
最新文章
- ibatis解决sql注入问题 .
- spark 安装配置
- linux java setting,setting java_home and path environmental variables in linux [duplicate]
- 【报告分享】2020中国CRM指数测评报告.pdf(附下载链接)
- java: -source 1.5 中不支持 diamond 运算符
- 到底有多二 (15 分)
- 2019-06-19 阿里巴巴三面
- binlog的基本介绍和操作
- 杀毒软件哪个好?2011年12月(第六次)VB100认证结果出炉
- 基于微信小程序的驾校考试系统设计与实现毕业设计毕设开题报告参考
- Excel中截取特殊字符之前、之间、之后的数据
- 《亲密关系》读后感_设计的直觉和亲密感
- 13 年的 Bug 调试经验总结(来自蜗牛学院)
- Structured Sequence Modeling With Graph Convolutional Recurrent Networks
- Eclipse调试python
- 二维码的生成和解析(qrcode 和 zxing)
- 2012年桂城街道小学毕业生升初中
- bga封装扇出过孔_手把手教你BGA元器件如何扇出?-EDA/PCB-与非网
- Think Pad笔记本分区解决思路及方法
- 麦仑·沙迈追求漂亮女人的故事(一)
热门文章
- 笔记本电脑属于个人计算机吗,黄真真:笔记本电脑属于个人计算机的一种形式莫?...
- 江湖中常说的“网格交易法”到底是什么?
- P2455雾雨魔理沙
- python使用Tesseract,pytesseract图片处理识别(1)
- 2021威海高考成绩查询电话,2021威海高考成绩查询系统
- 高可用安装K8s集群1.20.x
- iPhone4/4s 5.1.1版本越狱后无法连接iTunes,出现0xE8000012错误的解决方法
- 为什么说“公益渴区块链久矣”?
- 淘宝(SpringBoot自动装配原理)
- 学术扫盲之期刊,数据库,会议都是什么