Fower: 一个可在 Vue 和 React 方便使用的 CSS in JS 库 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
forsigner
V2EX    程序员

Fower: 一个可在 Vue 和 React 方便使用的 CSS in JS 库

  •  6
     
  •   forsigner
    forsigner 2021 年 4 月 23 日 5269 次点击
    这是一个创建于 1758 天前的主题,其中的信息可能已经有所发展或是发生改变。

    今天给大家介绍一个我断断续续花了半年开发的 CSS 项目: Fower.

    Fower 是什么?

    Fower 是一个让你高效开发 UI 的样式工具库,目标是让你写 CSS 不再痛苦。Fower 的核心特点是原子化(Atomic/utility-first)、类型安全(Type Safe)、CSS in JS,它非常注重开发体验,让你快速且开心的开发界面。

    Fower 是框架无关的,你可以在 React 、Vue 、React native 、小程序等任何 Javascript 项目中使用。

    项目背景

    一年前,我所在的团队同时在开发 Web 、React native 、小程序项目。在这三类项目中,我们使用了各不相同的样式方案:

    • 在 Web 项目中,我们使用的是 Styed-component ;
    • 在 React native 项目中,我们使用 React native 自带的 StyleSheet.create
    • 在小程序项目中,我们使用 Taro 开发,样式方案是 Sass;

    三种样式的方案写法各不相同,导致我们编写样式时特别痛苦:

    • 开发体验差,开发同样的界面,却要不同的写法,需要不断切换习惯和思维
    • 工具链太广太复杂,Styled-component 、Sass 、StyleSheet.create...
    • 开发效率低下,重复代码特别多
    • CSS 天生缺点多,可维护性差

    后面,我发现了 Tailwindcss,一个 utility 优先(utility-first) 的 CSS 框架,在我的推动下,我们团队开始在 Web 项目中使用 Tailwindcss 。一段时间后,我们发现开发体验很不错,开发效率也很高,特别适合在我们这种需要高度定制界面的项目使用。可惜的是,Tailwindcss 无法直接在 React native 、小程序等非 Web 项目使用。

    我们团队的成员都喜欢 Tailwindcss 这种样式写法。所以我创建了 Fower,希望能统一了所有项目的样式编写方式。

    和 Tailwindcss 类似,我们也使用了 utility-first 的理念,但有 Fower 又有点不同,Fower 使用 Atomic style props 的方式编写样式,代码如下:

    <div toCenterY p-10 w-260 rounded-10 shadow> <img circle-48 src="http://www.v2ex.com/img/jobs.jpg" /> <div ml-10> <div textXL fontBold>Steve Jobs</div> <span gray800>Co-founder of Apple Inc.</span> </div> </div> 

    核心理念

    Fower 是 opinionated 的,我们基于以下理念创建了它:

    • utility-first,这种方式让我们更快速地编写样式,和其他 "utility-first" CSS 框架不同的是,Fower 使用 "Atomic style prop" 编写样式

    • Type safe,我们团队是 TypeScript 重度使用用户,Type safe 带来的智能提示,让我们几乎很少翻阅文档,并且在编写代码时不依赖任何编辑插件就有准确的自动补全

    • Framework-agnostic,这是我们创建 Fower 的最主要原因之一,Fower 可以让你用一致的写法在 React 、Vue 、React Native 编写样式

    • CSS in JS,我们讨厌在独立的 CSS 文件中编写 CSS,纯 CSS 有非常多缺点,如:无法访问 JS 变量;容易产生样式冲突;容易产生死代码... 我们喜欢使用 JS (CSS in JS) 编写样式,它更适合在组件化时代中使用。实际上,Fower 不仅仅是 CSS in JS,它也是 CSS in HTML 。

    一些很酷的特性

    Fower 有非常多的特性,如原子类、响应式、伪类、主题、设计系统、CSS in JS...,我觉这些是 Fower 的基础功能,并不是特色功能。

    Fower 有几个我认为很酷的功能:

    1. Layout Toolkit

    如果要我在 Fower 中选一个最喜欢的特性,那毫无疑问是 Layout Toolkitd

    Fower 提供了一个强大的基于 Flexdiv 的布局工具,通过调整布局的方向(Direction)和对齐(Alignment),可以实现大部分的布局,使布局工作更轻松。

    相比传统的 flex 布局,Fower 的布局更加抽象精简,Fower 的布局抽象为 toCentertoCenterXtoCenterYtoLefttoToptoRighttoBottomtoBetweentoEvenlytoAround 十种原子对齐方式,使用时你可以忘记传统 flex 布局中的主轴( main axis )和交叉轴( cross axis )的概念,你只需要有方向感即可。

    使用方式如下:

    <div toCenter bgGray100 square-200> <div square-60 bgAmber400 rounded-8></div> <div square-80 bgBlue400 rounded-8></div> </div> 

    更详细的使用方法请看文档: Layout Toolkitd

    2. Predictable style

    另外一个我个人很喜欢的特性的是 Predictable style 。在传统的 CSS 中,我认为样式是不可预测的。为什么这么说?这里举个例子。

    我们有如下的 CSS:

    .red { color: red; } .blue { color: blue; } 

    有如下的的 html, css 类名分别为 "red blue" 和 "blue red":

    <div> <span className="red blue">Fower</span> <span className="blue red">Fower</span> </div> 

    你能确定文字的颜色吗?不好确定,如果我们不翻看上面的 CSS 代码,你无法直接判断文字的颜色,只能通过开发者工具调试得知。

    在 Flower 中,你可以轻易判断下面文字的颜色:

    <div> <span red400 blue400> text will be color blue400 </span> <span blue400 red400> text will be color red400 </span> </div> 

    这有什么用呢?除了让我们更容易判断样式结果,我觉的最有用的是:当我们抽象出一个可复用的组件时,比如一个通用的 Button, 那调用方可以轻易的覆盖组件默认样式,比如这样类似的代码 <Button bgRed300></Button> 可以安全的设置背景色。

    更详细的使用方法请看文档:Predictable style

    3. 颜色助手

    Fower 的另一个很酷的功能是颜色助手,您可以使用一些后缀来处理颜色。

    使用 --D{0-100} 这样的后缀来加深一个颜色:

    <div toEvenly toCenterY> <div red300>normal</div> <div red300--D40>darken</div> <div color="#fff--D40">darken</div> <div bgRed300 square-84></div> <div bgRed300--D40 square-84></div> <div border borderRed300 square-84></div> <div border borderRed300--D40 square-84></div> </div> 

    使用 --L{0-100} 后缀来变浅一个颜色:

    <div toEvenly> <div red500>normal</div> <div red500--T40>transparentize</div> <div color="#000--T40">transparentize</div> <div bgRed500 square-84></div> <div bgRed500--T40 square-84></div> <div border borderRed300 square-84></div> <div border borderRed300--T40 square-84></div> </div> 

    使用 --T{0-100} 后缀来增加颜色的透明度:

    <div toEvenly> <div red500>normal</div> <div red500--T40>transparentize</div> <div color="#000--T40">transparentize</div> <div bgRed500 square-84></div> <div bgRed500--T40 square-84></div> <div border borderRed300 square-84></div> <div border borderRed300--T40 square-84></div> </div> 

    使用 --O{0-100} 后缀来增加颜色的不透明度:

    <div toEvenly> <div color="rgba(0,0,0,0.4)">0.4</div> <div color="rgba(0,0,0,0.4)--O40">Opacify to 0.6</div> <div bg="rgba(0,0,0,0.4)" square-84></div> <div bg="rgba(0,0,0,0.4)--O40" square-84></div> <div border borderColor="rgba(0,0,0,0.4)" square-84></div> <div border borderColor="rgba(0,0,0,0.4)--O40" square-84></div> </div> 

    更详细的使用方法请看文档:Color helper

    4. 可组合的后缀

    Fower 提供一些后缀来快速处理样式, 如: --hover, --focus, --sm, --dark, --T{amount}...

    Flower 的另一个很酷的功能是可组合的后缀。 您可以组合一些后缀,并且顺序是任意的:

    <div square-84 bgOrange300 bgOrange400--D10--hover--sm></div> 

    下面的代码和上面是等价的:

    <div square-84 bgOrange300 bgOrange400--hover--sm--D10></div> 

    最后

    如果你想了解更多关于 Fower 的信息,你可以访问项目网站和官方文档。

    67 条回复    2021-04-26 15:41:53 +08:00
    v2NPC
        1
    v2NPC  
       2021 年 4 月 23 日
    跟 tailwind 相比较呢?
    forsigner
        2
    forsigner  
    OP
       2021 年 4 月 23 日
    @XiaMuCoder 都是 utility-first 理念,但是很大不同,这是 JS 方案,类型安全、更灵活、尺寸小,且无痛支持 web 、小程序、react native 等
    Liam1997
        3
    Liam1997  
       2021 年 4 月 23 日
    已 star
    顺便问下,你这个文档官网 https://fower.vercel.app/zh-cn/ 是 nextjs 的 nextra 做的么?
    forsigner
        4
    forsigner  
    OP
       2021 年 4 月 23 日
    shakukansp
        5
    shakukansp  
       2021 年 4 月 23 日
    样式封装就是先定义一个 object
    然后<div {...object} /> 么

    <div css={{...object}} />
    towry
        6
    towry  
       2021 年 4 月 23 日
    感觉入侵 vue 太深了,日后必是大坑 /技术债
    codingguy
        7
    codingguy  
       2021 年 4 月 23 日
    “start with vue/react”。必须选一种框架的话,感觉不能叫框架无关吧
    Jirajine
        8
    Jirajine  
       2021 年 4 月 23 日 via Android
    看起来不错,顺便把 svelte 也支持一下?
    forsigner
        9
    forsigner  
    OP
       2021 年 4 月 23 日
    @shakukansp 可以直接用 styled Api, 类似 styled-component, 有相关文档:
    forsigner
        11
    forsigner  
    OP
       2021 年 4 月 23 日
    @Jirajine 可以
    forsigner
        12
    forsigner  
    OP
       2021 年 4 月 23 日
    @codingguy @fower/core 是跟框架无关的,这看怎么定义框架无关了
    forsigner
        13
    forsigner  
    OP
       2021 年 4 月 23 日
    @towry 文档有写:
    forsigner
        14
    forsigner  
    OP
       2021 年 4 月 23 日
    @towry 文档有写,如果你接受不了原子属性这种写法,你也可以使用 css 类名:

    ```html
    <template>
    <div class="toCenterY p-10 w-260 bgWhite rounded-10 shadow">
    <img src="http://www.v2ex.com/img/vue-logo.png" class="circle-48" />
    <div class="ml-10">
    <div class="textXL fontBold">Evan You</div>
    <span class="gray800">Creator of Vue.js.</span>
    </div>
    </div>
    </template>
    ```

    入侵还好,你用 tailwind 也一样,不过这其实不重要,重要的是要写的爽,效率高,好维护。
    agdhole
        15
    agdhole  
       2021 年 4 月 23 日
    打包大小和性能如何?
    forsigner
        16
    forsigner  
    OP
       2021 年 4 月 23 日
    @agdhole 和 tailwindcss 相比,尺寸小很多:

    - 在 React 中 15.2kB: https://bundlephobia.com/result?p=@fower/[email protected]
    - 在 Vue 中 13.8kB: https://bundlephobia.com/result?p=@fower/[email protected]

    性能比一般 CSS in JS 库好,因为每个原子类是缓存的
    agdhole
        17
    agdhole  
       2021 年 4 月 23 日
    @forsigner #16 打包性能呢? tailwind 因为打包过于缓慢直接上了 jit
    shakukansp
        18
    shakukansp  
       2021 年 4 月 23 日
    @forsigner .vue 组件也是这样用么
    forsigner
        19
    forsigner  
    OP
       2021 年 4 月 23 日
    @agdhole 这是 js 啊,直接跟普通 js 一起打包的,没打包性能问题
    forsigner
        20
    forsigner  
    OP
       2021 年 4 月 23 日
    @shakukansp 是的,配置非常简单,可以看看: https://fower.vercel.app/zh-cn/docs/use-with-vue
    narmgalaxy
        21
    narmgalaxy  
       2021 年 4 月 23 日
    @forsigner tailwindcss 是按需打包的,用到多少打入多少
    forsigner
        22
    forsigner  
    OP
       2021 年 4 月 23 日
    @narmgalaxy taildwind 很不错,但不够灵活。举个小例子,我们一个项目使用过 tailwindcss,一大痛点就是太不灵活了,比如设置 padding,tailwind 中 p-2 代表 8px,我想要 10px 就很麻烦,使用 Fower,p2 代表你 padding: 8px, 但 p-{value} 可以是任意值
    dartabe
        23
    dartabe  
       2021 年 4 月 23 日
    为什么要把所有的类都变成原子类呢 感觉部分原子类就行了 多了不好记也没用
    Shyla
        24
    Shyla  
       2021 年 4 月 23 日
    哈哈看到楼主的头像就想起一个 hexo 的模板作者,没想到点进来真的是~膜拜大佬~
    3dwelcome
        25
    3dwelcome  
       2021 年 4 月 23 日
    不能做成 jit 的库吗?不想预编译啊。
    反正全部都是 JS 代码,放在前端编译一次后,动态生成的 CSS 缓存在本地不是挺好的。
    forsigner
        26
    forsigner  
    OP
       2021 年 4 月 23 日
    forsigner
        27
    forsigner  
    OP
       2021 年 4 月 23 日
    @Shyla 那是很久之前的项目了,难得你记得 哈哈
    forsigner
        28
    forsigner  
    OP
       2021 年 4 月 23 日
    @3dwelcome 有计划做,做个 webpack-loader 就可以
    crs0910
        29
    crs0910  
       2021 年 4 月 23 日   1
    看起来很有吸引力,Layout 的 toRight demo 好像有点问题?
    xiqingongzi
        30
    xiqingongzi  
       2021 年 4 月 23 日
    能够在 Wxa.js 里使用么= =
    codingguy
        31
    codingguy  
       2021 年 4 月 23 日
    @forsigner #12 点进文档确实有 vanilla 版本的。是我疏忽了
    pabupa
        32
    pabupa  
       2021 年 4 月 23 日
    看了文档,感觉很不错!
    u3u
        33
    u3u  
       2021 年 4 月 23 日
    https://tailwindcss.com/docs/just-in-time-mode#arbitrary-value-support
    @forsigner tailwindcss v2.1.0 的 jit 模式已经支持 p-[10px] 这种写法了 配合 twin.macro 已经很爽了 不过只支持 react
    如果可以直接整合 tailwindcss 的 class 就好了 真的不想再学一套命名了啊喂
    damao2250
        34
    damao2250  
       2021 年 4 月 23 日   1
    文档中( https://fower.vercel.app/zh-cn/docs/use-with-vue )“只能提示”是否应为“智能提示”?
    hewelzei
        35
    hewelzei  
       2021 年 4 月 23 日
    已 star,最近正好在想办法在 electron 使用 windicss,奈何官方的 webpack loder 有 bug,又不想直接使用 tailwindcss 。
    国内的前端开发人员好像不是很注重如何优雅编写样式,看到有一个像样的库,官方文档又详细,着实很欣慰啊。
    forsigner
        36
    forsigner  
    OP
       2021 年 4 月 23 日
    @crs0910 是有 bug,新版已经修复,你可以看看文档,你真有眼光,fower-layout 是 fower 最好用的功能,也是我自己最新喜欢功能。
    forsigner
        37
    forsigner  
    OP
       2021 年 4 月 23 日
    forsigner
        38
    forsigner  
    OP
       2021 年 4 月 23 日
    @pabupa 欢迎在项目中体验,包香
    forsigner
        39
    forsigner  
    OP
       2021 年 4 月 23 日
    @u3u 除了 layout toolkit, 类名基本上是和 tailwindcss 一致的,只不过是驼峰而已,其实切换成本不高
    forsigner
        40
    forsigner  
    OP
       2021 年 4 月 23 日
    @damao2250 是的,已修改,谢谢
    forsigner
        41
    forsigner  
    OP
       2021 年 4 月 23 日
    @hewelzei [国内的前端开发人员好像不是很注重如何优雅编写样式] 这个赞同,不知为啥,国内很多前端都理所当然的认为“关注点分离”就是对的,而且国内 CSS in JS 也用得不多,可能国内真的太多前端是非科班转过了的
    narmgalaxy
        42
    narmgalaxy  
       2021 年 4 月 23 日
    @forsigner svelte 可用吗
    huijiewei
        43
    huijiewei  
       2021 年 4 月 23 日
    感谢分享

    最近在关注可以生成 atom css 的 CSS-IN-JS 库

    https://github.com/seek-oss/vanilla-extract
    cereschen
        44
    cereschen  
       2021 年 4 月 23 日
    不错 抓住了国外框架不考虑小程序的痛点 应该可以收割一批用户
    3dwelcome
        45
    3dwelcome  
       2021 年 4 月 23 日
    @forsigner "有计划做,做个 webpack-loader 就可以"

    我说的 JIT, 是类似 vue.js ,前端包含一个 js 后,页面载入前,前端能动态编译 v-if, bgOrange300 之类的,到对应的 js/css 代码。
    和 webpack 没关系,总觉得我们聊的不是一个 Just In Time Compiler 。
    oop99
        49
    oop99  
       2021 年 4 月 23 日 via iPhone
    Mark 一下感觉不错,有机会试用再提意见
    ShareManT
        50
    ShareManT  
       2021 年 4 月 23 日
    楼主思路不错。不过楼上好多人提到 tailwind 不香的地方可以看看 windicss,都有弥补、
    hewelzei
        51
    hewelzei  
       2021 年 4 月 24 日 via Android
    @forsigner 国内是有好几个好用的 UI 组件库,像 antd, element ui 之类的,但是却少有 styled-components, emotion.js, stylable 之类的能改变样式编写方式的库。
    forsigner
        52
    forsigner  
    OP
       2021 年 4 月 24 日
    @narmgalaxy 这两天支持一下
    forsigner
        53
    forsigner  
    OP
       2021 年 4 月 24 日
    @huijiewei 这种单纯是为了 atomic,不把开发体验放在重要位置,不看好
    forsigner
        54
    forsigner  
    OP
       2021 年 4 月 24 日
    @3dwelcome 我我以为你说的是 zero-runtime, 本来 fower 本来就是不需要预编译的,它是 js 动态生成样式的,可以说本来就是 Just In Time
    forsigner
        55
    forsigner  
    OP
       2021 年 4 月 24 日
    @oop99 欢迎使用
    forsigner
        56
    forsigner  
    OP
       2021 年 4 月 24 日
    @ShareManT windicss 也不错,不过它还是纯 css 方案,fower 是 css in js 方案,看各自喜好吧
    forsigner
        57
    forsigner  
    OP
       2021 年 4 月 24 日
    @hewelzei 是的,antd, element 是更上层业务,不能改变样式编写方式
    xiqingongzi
        58
    xiqingongzi  
       2021 年 4 月 24 日
    @forsigner 是的
    FightPig
        59
    FightPig  
       2021 年 4 月 24 日
    @forsigner tailwindcss 新版已经支持 p-[value] 随意写了
    FightPig
        60
    FightPig  
       2021 年 4 月 24 日
    @ShareManT tailwind 新版的 jit 感觉就是和 windicss 一个意思,windicss 作者还在推特上说起这事
    damao2250
        61
    damao2250  
       2021 年 4 月 25 日
    @forsigner 貌似大标题没改 (非鸡蛋挑骨头,如有冒犯的话)
    forsigner
        62
    forsigner  
    OP
       2021 年 4 月 25 日
    @damao2250 文档代码改了,没发布,现在可以了 ,,老哥,在 vue 中可以用吗?
    forsigner
        63
    forsigner  
    OP
       2021 年 4 月 25 日
    @FightPig p-[100], 感觉挺别扭的 哈哈
    forsigner
        64
    forsigner  
    OP
       2021 年 4 月 25 日
    @xiqingongzi 应该可以支持,不过这个框架貌似有点小众,我晚点看看
    forsigner
        65
    forsigner  
    OP
       2021 年 4 月 25 日
    @Jirajine svelte 已经支持,欢迎测试 bug https://fower.vercel.app/docs/use-with-svelte
    forsigner
        66
    forsigner  
    OP
       2021 年 4 月 25 日   1
    @narmgalaxy svelte 已经支持,欢迎体验
    FightPig
        67
    FightPig  
       2021 年 4 月 26 日
    @forsigner 不是,是 p-100px,这样的
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1859 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 31ms UTC 10:47 PVG 18:47 LAX 02:47 JFK 05:47
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86