css3 子类选择器-具有零运行时间和 TS 支持的 CSS-in-JS 框架

2023-09-02 0 3,829 百度已收录

以前如果使用CSS-in-JS来编译项目样式文件,会优先考虑styled-components。 其特点是使用模板字符串来编译样式组件,使用方便css3 子类选择器,易于上手。 反对的声音之一是styled-components使用运行时机制,减少了产品的体积,担心运行时开销会造成一些性能损失。

前段时间我在个人项目中使用了 VanillaExtract(访问查看该项目)。 与其他 CSS-in-JS 解决方案不同,它可以在编译时编译 CSS 样式文件,实现零运行时并支持 TypeScript。

下面css3 子类选择器,我们将为您介绍VanillaExtract的特点和应用

什么是香草精?

VanillaExtract 是一个新的 CSS-in-JS 库,用于编译 CSS 样式文件。 它于 2021 年开源,并在年度全球 CSS 报告中获得 CSS-in-JS 满意度第一名。

框架友好

VanillaExtract 是一个通用库,不绑定任何 JavaScript 框架。 你可以在React、Vue、Angular等框架中使用它,但在此之前,你需要让自己的创建工具支持它。

VanillaExtract已经集成了最流行的后端创建工具,包括:webpack、esbuild、Vite等。

本文以在Vite中使用为例。 首先,您需要安装两个库:@vanilla-extract/css 和 @vanilla-extract/vite-plugin。 **@vanilla-extract/css 是我们样式开发中主要使用的库**。

npm install @vanilla-extract/css @vanilla-extract/vite-plugin

css3 子类选择器-具有零运行时间和 TS 支持的 CSS-in-JS 框架

然后将vanillaExtractPlugin插件添加到vite配置中。 CSS的编译和处理主要是通过这个插件完成的。 编译样式文件时,文件名必须以**.css.ts**结尾。

// vite.config.ts
import { defineConfig } from 'vite';
import { vanillaExtractPlugin } from '@vanilla-extract/vite-plugin';

export default defineConfig({
  plugins: [vanillaExtractPlugin()],
});

零运行时间和 TS 支持

使用TypeScript是VanillaExtract的核心,它可以让VanillaExtract在创建时准确定位样式的位置并生成所有样式,就像SaaS和Less一样,这也与其他CSSinJS解决方案(StyledComponents和Emotion)不同。

使用 TypeScript 编译 CSS 样式的另一个用途是它为样式带来类型安全。 如果编译出不正确的值,编译时就会报错给我们。 编者也会在编码过程中给我们一些风格提示。

image.png常用样式API

本文介绍了日常开发中常用的一些样式API是如何在vanillaextract中编译的。 **@vanilla-extract/css 库的 style() 方法是常用的基本 API**。

样式文件需要以 **.css.ts** 结尾。 CSS样式属性名称采用驼峰式大小写书写,与CSS样式的正常书写没有太大区别。

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

export const todoList = style({
  marginTop: '20px',
  background: '#ccc',
});

export const todoInfo = style({
  paddingTop: '10px',
});

然后在我们的App组件中,导出样式文件并将值设置为标签的className属性的形参。 使用方法还是和其他CSS-in-JS库不同。 例如,styled-component 样式采用组件的形式。 来编译和使用。

// app.tsx
import * as styled from './styled.css';

const App = () => {
  return 
    

          
  • 学习 React 开发</li>
          
  • 学习 Node.js 开发</li>
        </ul>
      </
    >
    }

vanillaextract 支持一些伪类选择器、子选择器、媒体查询、**@supports** 以及通过引用 style() 函数创建的其他类。

export const todoInfo = style({
  paddingTop: '10px',
  // 伪类选择器
  ':hover': {
    color: 'red',
  },
  selectors: {
    // 选择自身的最后一个元素
    '&:last-child': {
      paddingBottom: '10px',
    },
    // 选择器还可以包含对其他作用域类名称的引用,这会改变 todoList 这个类的背景颜色
    [`${todoList} &`]: {
      background: 'yellow',
    },
  },
  // 媒体查询
  '@media': {
    'screen and (min-width: 568px)': {
      color: 'blue',
    },
  },
  '@supports': {
    // 摘自官网示例
    '(display: grid)': {
      display: 'grid',
    },
  },
});

文档中指出:为了提高可维护性,每个样式块只能针对单个元素。 这意味着你不能直接调整它的子元素或兄弟元素,例如以下需求:

.todo-list > li { // 期望的写法
    color: green !important;
}

export const todoList = style({
  marginTop: '20px',
  background: '#ccc',
  '& > li': { // 错误的实现
    color: green !important;
  }
});

VanillaExtract 提供了 GlobalStyle() API 来全局定位当前元素的子节点。 这里不需要担心重复,VanillaExtract 具有本地范围的类名,并且像 CSSModule 一样,不存在类名冲突的风险。

import { style, globalStyle } from '@vanilla-extract/css';
export const todoList = style({ ... });

// 对局部作用类名的样式设置
globalStyle(`${todoList} > li`, {
  color: 'green !important',
});

VanillaExtract 全局样式不支持嵌套,某些情况下可能需要多次调用 globalStyle() 函数来设置样式。

globalStyle('html, body', {
  margin: 0
});
globalStyle('a', {
  color: 'blue',
});
globalStyle('a:hover', {
  color: 'red',
});

风格组合,就像父类和泛型类型的继承关系一样,体现了风格的通用部分。

import { style } from '@vanilla-extract/css';
const base = style({ padding: 12 });
export const primary = style([
  base,
  { background: 'blue' }
]);
export const secondary = style([
  base,
  { background: 'aqua' }
]);

CSS 变量与主题 CSS 变量

CSS 变量有时称为 CSS 自定义属性。 当定义了CSS变量后,它就可以在整个网站的样式文件中重复使用。

例如,在网站开发中,可能会有很多重复的值,比如颜色,用原生CSS编译如下:

// css 变量声明与使用
:root {
  --blue-color: blue;
}
.one {
  colorvar(--blue-color);
}
.two {
  colorvar(--blue-color);
}

// javascript 操作 css
element.style.getPropertyValue("--blue-color");// 获取一个 Dom 节点上的 CSS 变量
getComputedStyle(element).getPropertyValue("--blue-color");// 获取任意 Dom 节点上的 CSS 变量
element.style.setProperty("--blue-color", jsVar + 4);// 修改一个 Dom 节点上的 CSS 变量

vanillaextract 没有重新发明轮子,而是广泛使用浏览器内置的原生 CSS 变量函数。 由于 vanillaextract 具有本地作用域的类名,因此另一个用途是能够在样式块内限定 CSS 变量的作用域。

css3 子类选择器-具有零运行时间和 TS 支持的 CSS-in-JS 框架

创建主题

应用程序只有一个全局主题时,建议使用createGlobalTheme方法。 使用起来并不复杂。 只需查看文档即可。

有时我们的应用程序会有多个主题,例如“深色模式”。 您需要做的第一件事是使用 createGlobalThemeContract() 方法创建主题合约。 这个key的值可以先设置为null,这样也保证了创建。 主体可以拥有正确的密钥。 以后“主题合约”返回的值将作为createTheme()方法的第一个参数传入。

import { createTheme, createThemeContract } from '@vanilla-extract/css';

const colors = createThemeContract({
  colornull,
  backgroundColornull,
});

export const lightTheme = createTheme(colors, {
  color'#000000',
  backgroundColor'#ffffff',
});

export const darkTheme = createTheme(colors, {
  color'#ffffff',
  backgroundColor'#000000',
});
export const vars = { colors };

应用主题

里面的createTheme()方法返回的值是一个类名,可以在HTML标签的className中使用它来声明CSS变量。 在应用程序需要获取CSS样式的根标签中,设置该类名。

import { darkTheme, lightTheme } from './styles/theme.css';
import { useState } from 'react';

const App = () => {
  const [isDarkTheme, setIsDarkTheme] = useState(false);
  return (
    <div id="app" className={isDarkTheme ? darkTheme : lightTheme}>
      <button
        type="button"
        onClick={() =>
 setIsDarkTheme((currentValue) => !currentValue)}
       >
         Switch to {isDarkTheme ? 'light' : 'dark'} theme
       </button>
    </div>

  );
};

**代码片段中通过一个简单的Demo来展示如何应用主题。 如果想让体验更好,还可以通过监听系统主题来设置默认主题颜色。 请参阅项目 **#L27。

export const useSystemTheme = () => {
  const [name, setName] = useState(Theme.Light);

  useEffect(() => {
    if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
      setName(Theme.Dark);
    } else {
      setName(Theme.Light);
    }

    window
      .matchMedia('(prefers-color-scheme: dark)')
      .addEventListener('change', (event: MediaQueryListEvent) => {
        if (event.matches) {
          setName(Theme.Dark);
        } else {
          setName(Theme.Light);
        }
      });
  }, []);

  return {
    name,
    isDarkMode: name === Theme.Dark,
    isLightMode: name === Theme.Light,
  };
};

当切换主题按钮时,可以看到CSS样式表中包含了以下两个主题的CSS变量。

使用主题

在组件样式中使用声明的主题变量。 vars 是 theme.css.ts 文件中导入的变量。

import { style } from '@vanilla-extract/css';
import { vars } from '../../styles/theme.css';

export const todoList = style({
  marginTop'20px',
  backgroundColor: vars.colors.backgroundColor,
  color: vars.colors.color,
});

我们来看看效果。 就像直接编写原生 CSS 变量一样,使用 var 来获取 CSS 变量,而不是直接进行值替换。

总结

在这篇文章中,我们主要介绍了 VanillaExtract 的一些特性及其在 React 中的应用。 与任何其他CSS-in-JS解决方案不同,它的样式不是在JavaScript运行时生成的,而是在编译阶段就已经完成了。

VanillaExtract 是一个新的 CSS-in-JS。 虽然目前它的使用量远低于竞争对手,但在 2021 年全球 CSS 满意度调查中仍然排名第一,也是一项值得关注的技术。

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

悟空资源网 css3 css3 子类选择器-具有零运行时间和 TS 支持的 CSS-in-JS 框架 https://www.wkzy.net/game/189827.html

常见问题

相关文章

官方客服团队

为您解决烦忧 - 24小时在线 专业服务