CXYVIP官网源码交易平台_网站源码_商城源码_小程序源码平台-丞旭猿论坛
CXYVIP官网源码交易平台_网站源码_商城源码_小程序源码平台-丞旭猿论坛
CXYVIP官网源码交易平台_网站源码_商城源码_小程序源码平台-丞旭猿论坛

为自己的团队定制CSS框架-免费源码丞旭猿

去年很火的 Tailwind CSS 是何方神圣,到底是 Atomic CSS 余孽的卷土重来还是真的有点东西。Tailwind CSS 如何帮助我们建立界面样式到设计语言的连接,Utility-first 的 CSS 工作流是怎样的,以及,如何基于 Tailwind CSS 为自己的团队定制一套舒服的 CSS 框架。

我们太有限了,我们只能做我们觉得是对的事情,然后接受它的事与愿违。– 罗翔

CSS 工程化要解决的问题

至少在中后台研发领域,我觉得团队在 CSS 领域会遇到以下几个问题要解决:

  • 强制一致性:如何强制规约界面的字体、字号和颜色收敛。

  • 设计关联:如何形成界面样式到设计语言的连接与对应。

  • 语义化:关注点分离是银弹还是误解。

  • 内联样式:在何时进行抽象。

强制一致性

在解释什么是强制一致性之前,请大家来猜一下,在 yuque.com 上,有多少种不同的字号、文字颜色和背景颜色。

答案可能跟你预期的有些差异。yuque.com 上一共有 34 种不同的字号、77 种不同的文字颜色和 56 种不同的背景颜色。https://cssstats.com/stats/?url=https://yuque.com/

事实上 yuque.com 已经做得足够好了。因为在 Github.com 上一共有 56 种字号,163 种文字颜色和 147 种背景颜色。在一些企业级的 Web 应用上其实会更可怕,例如 Gitlab 一共有 59 种字号、402 种文字颜色和 239 种背景颜色。

为什么会出现这种事情?当设计师把设计稿交给我们之后,还原设计稿的最便捷方式之一就是使用设计工具的 “Copy as CSS” 功能导出对应的 CSS,看起来不错。

/* Lorem ipsum dolor si */position: absolute;width: 232px;height: 144px;font-family: Roboto;font-style: normal;font-weight: normal;font-size: 16px;line-height: 24px;/* or 150% */color: rgba(0, 0, 0, 0.541327);

观察这段 CSS,会发现,在这里,字体、字号和颜色都是一个自由的,没有规约的值。每一行 CSS 都是一个空白的画布,没有人能阻止你使用任何你想要的值。这就是为什么同样是视觉设计师想要的语雀品牌绿,在 CSS 中至少有六种写法,并且以下三种我基本看不出有啥区别……

所以这里所谓的 强制一致性指的是开发人员在书写 CSS 的过程中,属性的值应该总是从一个有限的集合中去取。而不是任意取值。

Design Token

再来。这是一份 Google Materia Design 的设计稿。会发现 Google 的设计师除了标注了这些元素的颜色值之外,还贴心的写了个名字 Gray 900。这就是所谓的 Design Token:

Design tokens are all the values needed to construct and maintain a design system — spacing, color, typography, object styles, animation, etc. — represented as data.

一份优秀的设计稿

在一份设计规范中,设计师首先会决定使用一些值。然后给它们设置一个上下文无关的名字,即 Global Token 。用于让其他的 token 引用。

在此之上,在特定的上下文和抽象中,会基于 Global Token 生成一个具名的 Alias Token,用于传达 Global Token 的设计预期。

最后,决定某个组件要使用某个特定 Design Token 时,会创建一个 Component-specific Token,让开发人员能给予 Alias Token 去定义组件的 Token 别名。

从色值到组件

下面来个例子。

普通开发

// css

button {

background: 2680EB;

}

裸写色值。无法做到强制一致性

文艺开发

// css

:root {

–blue400: 2680EB;

–ctaBackgroundColor: var(–blue400);

}

button {

background: var(–ctaBackgroundColor);

}

通过 css variable 把 Design Token 代码化。

使用的时候引用。不要裸写色值。

这里并没有再创建一遍 Component-specific Token

XX开发

// tailwind.config.js

{

theme: {

extend: {

colors: {

blue: {

400: 2680EB

}

}

}

}

}

// css

@layer components {

.cta-background-color {

@apply bg-blue-400;

}

.button-cta-background-color {

@extend .cta-background-color;

}

}

// html

Click Me

通过 tailwind.config.js 把 Design Token 与值做关注点分离

通过 tailwind 的 layer directive 把 Design Token 与 Alias token 做连接

创建出 Component-specific Token,通过类名暴露给 HTML 组件使用

语义化和关注点分离

看到这里可能有小伙伴开始懵逼了,是不是有哪里搞错了,不是说好了 Tailwind CSS 就是当初被喷成狗的 Atomic CSS 换了个皮卷土重来么,怎么跟你上面讲的不太一样?甚至官网上的示例都是这样一串 class,是不是你在过度解读 Tailwind CSS,夹带了私货?

前面已经讨论了如何把样式和设计通过 Design Token 连接起来。但接下来可能要讨论一些比较奇怪的东西。

用雨燕首页的 最近常访问的应用 列表为例。按照古典时代关注点分离的最佳实践,也就是传说中的 写 HTML 的时候不用关心样式,我们会怎么写这样的列表:

class="application-list"><li><ahref="/yuyan/yuyanAssets"><imgsrc="https://gw.alipayobjects.com/zos/basement_prod/9a7a9c64-01ee-45ca-a615-6063a24f70a9.svg"/><div><h4>yuyanAssetsh4><span>雨燕前端应用span>div>a>li>ul>
.application-list{list-style:none;>li {background:fff;>a {display:block;padding:18px 22px;>img {display:block;width:38px;height:38px;float:left;}>div {display:inline-block;>h4 {color:314659;font-weight:600;margin:0;}>span {color:697b8c;font-size:12px;}}}}}

现在谁这么写 CSS 绝对可能会被揍。它最大的坏处是 HTML 和 CSS 的层次结构必须完全对应。HTML 怎么嵌套的, CSS 就必须怎么嵌套。

后来我们开始有了 BEM,写出来的 HTML 会不那么欠揍了:

class="application-list"><liclass="application-list__item"><aclass="application-list__link"href="/yuyan/yuyanAssets"><imgclass="application-list__img"src="https://gw.alipayobjects.com/zos/basement_prod/9a7a9c64-01ee-45ca-a615-6063a24f70a9.svg"/><divclass="application-list__content"><h4class="application-list__title">yuyanAssetsh4><spanclass="application-list__description">雨燕前端应用span>div>a>li>ul>
.application-list{list-style:none;&__item{background:fff;}&__link{display:block;padding:18px 22px;}&__img{display:block;width:38px;height:38px;float:left;}&__content{display:inline-block;}&__title{color:314659;font-weight:600;margin:0;}&__description{color:697b8c;font-size:12px;}}

现在看起来舒服多了。但是问题来了。如何复用?

例如现在需要写一个结构非常类似的列表,例如雨燕首页的进行中的迭代的列表,希望最大限度复用上面这个结构。一种不纠结的做法是拷一遍。另一种做法是使用注入 less / sass 的 mixin 或者 extends 功能复用样式。

复用:使用 mixin 或者 extends

class="application-list"><liclass="application-list__item"><aclass="application-list__link"href="/yuyan/yuyanAssets"><imgclass="application-list__img"src="https://gw.alipayobjects.com/zos/basement_prod/9a7a9c64-01ee-45ca-a615-6063a24f70a9.svg"/><divclass="application-list__content"><h4class="application-list__title">yuyanAssetsh4><spanclass="application-list__description">雨燕前端应用span>div>a>li>ul>class="sprint-list"><liclass="sprint-list__item"><aclass="sprint-list__link"href="/yuyan/yuyanAssets"><imgclass="sprint-list__img"src="https://gw.alipayobjects.com/zos/rmsportal/yeSGzTolyopHKmBeKQHC.svg"/><divclass="sprint-list__content"><h4class="sprint-list__title">迭代1h4><spanclass="sprint-list__description">basement/basementwebspan>div>a>li>ul>
.application-list{list-style:none;&__item{background:fff;}&__link{display:block;padding:18px 22px;}&__img{display:block;width:38px;height:38px;float:left;}&__content{display:inline-block;}&__title{color:314659;font-weight:600;margin:0;}&__description{color:697b8c;font-size:12px;}}.sprint-list{.application-list;}

复用:创建内容无关样式

另一种方案是创建一个内容无关的 CSS,由 application 和 sprint 两个实体列表共同使用。如果需要只修改 sprint 列表中的样式,又不想影响到其他 entiry-list,就需要语义化的增加一个 class,然后通过这个新的语义化 class 来覆盖样式。

class="entity-list"><liclass="entity-list__item"><aclass="entity-list__link"href="/yuyan/yuyanAssets"><imgclass="entity-list__img"src="https://gw.alipayobjects.com/zos/basement_prod/9a7a9c64-01ee-45ca-a615-6063a24f70a9.svg"/><divclass="entity-list__content"><h4class="entity-list__title">yuyanAssetsh4><spanclass="entity-list__description">雨燕前端应用span>div>a>li>ul>class="entity-list sprint"><liclass="entity-list__item"><aclass="entity-list__link"href="/yuyan/yuyanAssets"><imgclass="entity-list__img"src="https://gw.alipayobjects.com/zos/rmsportal/yeSGzTolyopHKmBeKQHC.svg"/><divclass="entity-list__content"><h4class="entity-list__title">迭代1h4><spanclass="entity-list__description">basement/basementwebspan>div>a>li>ul>
.entity-list{list-style:none;&__item{background:fff;}&__link{display:block;padding:18px 22px;}&__img{display:block;width:38px;height:38px;float:left;}&__content{display:inline-block;}&__title{color:314659;font-weight:600;margin:0;}&__description{color:697b8c;font-size:12px;}}.entity-list.sprint{.entity-list__img{margin-right:8px;}}

这只是一个选择……

  • 要么保持关注度分离,在写 HTML 的时候(尽量)不关心 CSS,使用 mixin 和 extends 做复用。

  • 要么开始尝试创建内容无关的样式,并以可复用的方式命名所有内容,这就是 Tailwind CSS 作者的理念。

内联样式

if(status ===FAIL) {returnF5222D, fontSize: 16,float:right}} />;}

不知道大家怎么看这样的代码。这是一个 Icon,在这个场景下我们需要去给它设置颜色和字号。这样写内联样式总觉得很奇怪,其实也合理。因为如果我们真的为了这个场景去创建个样式出来,就真的太奇怪了。并且会带来额外的起名负担。还会担心重名(于是我们又引入了 css module),所以很可能你会写出来这样一个 class:

// JSX:if(status ===FAIL) {return"redCloseIconRight"/>;}// CSS.redCloseIconAlignRight {color:F5222D;fontSize:16px;float: right;}

内联样式会带来两个问题:

  • 无法做到强制一致性。除非你要在内联样式里写 CSS Variable,否则没办法保证样式值的收敛。

  • 过于复杂的内联样式很恶心,例如 box-shadow、font-family。很容易又转回到创建一个局部 class 的情形。

在这两种情况下,为一些常用的样式设定 Utility Classes 其实非常方便。.clearfix就是特别典型的例子。Tailwind CSS 的另一个爽点就在这里。通过配置,可以创建出链接到 Design Token 的 Utility Classes。不管在 css 里通过 apply 复用,还是直接在 jsx 里用,都非常方便:

// JSX:if(status ===FAIL) {return"text-red-500 text-base"/>;}// 加个 shadow 也很方便:if(status ===FAIL) {return"text-red-500 text-base shadow-sm"/>;}

正式介绍一下 Tailwind CSS

写到这里终于可以正式介绍一下 Tailwind CSS 了。

Q: Tailwind CSS 是 Atomic CSS 吗?

A: 不是。它是一个 Utility First 的 CSS 框架。提供了对提升 CSS 开发效率的一系列 Utility Class 的抽象,以及自定义 Utility Class 的方法。

Q: 然后呢

A: 以 tailwind.config.js 为桥梁,建立起属于自己团队的从 Design System 到 CSS 框架的连接。

Q: 那如何低成本解决原先有个 class 叫.black,然后很多组件都用了,但是突然有需求要把他们改成蓝色的问题

A: 按照上面 Design Token 的做法,做component-layer封装即可。

如何做?

以 yuyanAssets 为例子:

1. 在 tailwind.config.js 中定义 Design Token

module.exports={darkMode:false, // or media or classpurge:[./src/**/*.{js,jsx,ts,tsx}],theme:{extend:{fontFamily:{mono:[ Menlo, Consolas, monaco, monospace ],},fontSize:{xs:12px,sm:14px,base:16px,lg:20px,xl:24px,},fontWeight:{light:300,normal:400,medium:500,},colors:{primary:1890ff,info:2c92f6,warn:ffbf00,success:00a854,fail:f04134,doing:697b8c,pause:a3b1bf,enable:52c41a,disable:f5222d,danger:f04135,icon:{0:f04134,1:00a854,2:108ee9,3:f5317f,4:f56a00,5:7265e6,6:ffbf00,7:00a2ae,}},boxShadow:{DEFAULT:0px 4px 4px rgba(0, 55, 107, 0.04),},},},variants:{extend:{},},plugins:[],}

2. 把原先 less 中散落的各种 Design Token 使用 apply 描述。

.panel-body {flex:1;background:@background-color-content;border-radius:@border-radius-default;box-shadow:@shadow-default;overflow: hidden;}改成@layercomponents {.panel-background {@applygb-white;}}.panel-body {.panel-background;@applyflex-1rounded shadow;overflow: hidden;}

3. 去除无用抽象。把内联样式改写成 Utility Class

<divstyle={{width:120,marginLeft:16,marginRight:12}}><Progresspercent={progress}format={percent=>`${percent}%`} />div><AvatarclassName={`icon-producticon-color-${colorIndex}`}>{iconLetter}Avatar>// 改成<divclassName="w-28 ml-4 mr-3"><Progresspercent={progress}format={percent=>`${percent}%`} />div><AvatarclassName={`icon-productbg-color-${colorIndex}`}>{iconLetter}Avatar>

多余的话

在 2021 年的当下,一个前端工程师在工作中,花在 JavaScript、CSS 和 Html 的上的时间占比大概跟前面的排序一样。JavaScript > CSS >>> Html。早年间前端工程师可能还会通过模板关注到 Html 的结构,而现在,随着 React 接管了 DOM,前端工程师的关注点已经慢慢从 HTML 移动到了 JSX 上。

甚至在整个生产过程也跟古典的写语义化的 HTML -> 给他们取个 Class -> 写选择器 -> 写 CSS 不同了。工程师总是尝试优先使用已经写好的组件(如果没有就写一个),然后组合搭建出整个界面。甚至在布局的时候都很少关注 HTML:比如 antd 已经提供了 Layout 布局组件,又比如 Material Design 整个布局都是基于 Responsive Layout 的,基本上没有考虑有关 HTML 文档流的什么事情。

在 React 刚出来的时候,有很大一部分前端工程师表示 JSX 这种把逻辑和模板混在一起写的方式就是倒退。但随着 Flutter 和 Swift UI 的流行,大家惊奇的发现整个业界都在倒退。

所以也许我们可以换个想法,把 HTML 和 CSS 当成 UI 框架输出的结果。在书写代码的过程中,它们是什么样子的,可能并没有那么重要。

structContentView:View{varbody: someView{VStack{Text("Turtle Rock").font(.title)Text("Joshua Tree National Park").font(.subheadline)}}}
@overrideWidgetbuild(BuildContext context) {returnGestureDetector(onTap:() {controller..reset()..forward();},child:RotationTransition(turns:animation,child:Stack(children:[Positioned.fill(child:FlutterLogo(),),Center(child:Text(Clickme!,style:TextStyle(fontSize:60.0,fontWeight:FontWeight.bold,),),),],),),);

引用

https://spectrum.adobe.com/page/design-tokens/

https://adamwathan.me/css-utility-classes-and-separation-of-concerns/

https://css-tricks.com/bem-101/


关注「Alibaba F2E」微信公众号(左)微信视频号(右)

把握阿里巴巴前端新动向

声明:本文部分素材转载自互联网,如有侵权立即删除 。

© 版权声明
THE END
喜欢就支持一下吧
点赞0赞赏 分享
相关推荐
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容