CSS in JS 新秀:vanilla-extract 淺析

前言

2021 年,vanilla-extract 作爲黑馬登頂了 css-in-js 滿意度榜首(雖然使用率僅爲 1%),號稱是一個類型安全、高度兼容 TS 場景的庫,國內相關討論還很少,稍微看了一下還挺好用的。

介紹

官方文檔:https://vanilla-extract.style/documentation/

打開vanilla-extract官網文檔,裏面已經羅列了他的那些優點。作爲一個如果使用 css-in-js 會首選styled-components的我來說,比較關注的點主要是:

這兩點說白了就是,零運行時且支持typescript

目前,業界大多數相關競品如 styled-components就是一個運行時方案且基於標籤模板進行書寫,主要基於stylis解析器解析,如果頻繁更新props還會造成style標籤大量插入到head裏。

安裝

Webpack 環境下,需要同時安裝 @vanilla-extract/css@vanilla-extract/webpack-plugin 插件:

yarn add @vanilla-extract/css @vanilla-extract/webpack-plugin

安裝完成後,修改 Webpack 配置:

const { VanillaExtractPlugin } = require('@vanilla-extract/webpack-plugin')

module.exports = {
  entry: './src/index.js',
  // ....
  plugins: [new VanillaExtractPlugin()]
};

這裏可以看見,當我們使用 vanilla-extract 時,需要安裝兩個庫:

構建樣式 API

這裏只會對vanilla-extract比較核心的構建樣式相關幾個 API 提及,其他API可以直接前往官網查看。

style

import { style } from '@vanilla-extract/css';

export const parentClass = style({
  background: 'red',
  ':hover'{
    background: 'blue',
  },
});

export const childClass = style({
  selectors: {
    '&:nth-child(2n)'{
      background: '#fafafa',
    },
    [`${parentClass} &`]{
      color: 'pink',
    },
  },
});
import { childClass, parentClass } from './index.styles.css';

const Demo = () =(
  <div className={parentClass}>
    <div className={childClass}>DEMO1</div>
    <div className={childClass}>DEMO2</div>
    <div className={childClass}>DEMO3</div>
  </div>
);

export default Demo;

這個簡單的demo我相信,看幾下就已經明白是怎麼使用了。但是需要理解的地方是,爲了提高可維護性,「每個樣式塊只能針對某個元素(或者說是使用這個樣式塊的元素)」。那麼在上述代碼裏的selectors而言,「其目標必須是」****&(也就是自身元素)而不能是其他元素。例如:`${parentClass} &`是 OK 的,但是`& div`是不允許的。這樣的設計,我覺得更是一種職責分離吧,每個樣式塊都針對某個元素,那麼對於項目而言,樣式的可維護性就大大提高了,相比於其他css in js(styled-components)就不容易出現樣式冗餘的問題。對於一些特殊情況,比如:在寫styled-components我們會利用其包裹arco組件(或是其他組件),然後對其內部元素樣式進行覆寫或是新增。

const StyledSelect = styled(Select)`
    div {
        color: red;
    }
`

那麼在vanilla-extract樣式塊裏是不能直接做到的,因爲每個樣式塊都是針對某個元素,是不能直接通過該樣式塊,直接對其兄弟元素、子元素進行樣式調整。但是,對於這種情況,是可以使用另一個 APIglobalStyle進行開發。

globalStyle

顧名思義,就是全局樣式 API。但是因爲本身vanilla-extractcss module,每個 className 都是獨一無二,那麼通過globalStyle來對其子元素進行樣式調整覆蓋完全是可行的。

import { style, globalStyle } from '@vanilla-extract/css';

export const parentClass = style({});

globalStyle(`${parentClass} > div`{
  color: 'red'
});

const Demo = () =(
    <div className={parentClass}>
        <Select/>
    </div>
)

相比於 Styled-components 的優點

總結

目前瞭解下來,vanilla-extract是一個總體還不錯的css in js庫,雖然目前使用率比較低,但是後續廠商平臺項目會考慮在一些地方使用看看效果(畢竟不會增大 js 體積)。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/ysjP4JoCDOIXLSXIf3WRpg