张世民跟随创客、开发人员、函数式语言和怪诞字体的粉丝。

# 使用 Sprinkles 构建您自己的类型安全版本的 Tailwind CSS

##

2022 年 7 月 15 日 6 分钟阅读

我是 CSS 库vanilla-extract的忠实粉丝;在我看来,它是自 Tailwind CSS 以来最令人兴奋的 CSS 工具。如果您是vanilla-extract的新手,它是由 Mark Dalgleish 创建的 CSS-in-JS 库,可让您利用 TypeScript 的强大功能来编写 CSS。

我对 vanilla-extract 的杀手级功能Sprinkles API感到特别兴奋。Sprinkles 允许您根据首要原则创建完全定制的设计系统。您可以使用 Sprinkles 创建自己的原子、实用程序优先的 CSS 框架,而不是使用现成的库,例如Tailwind 和 Tachyon。

在本教程中,我们将设置一个新的 Next.js 应用程序并使用 vanilla-extract 的 Sprinkles API 创建一个自定义的、实用程序优先的 CSS 框架,称为 Sprinkles Tailwind。然后,我们将使用我们的新框架在 Tailwind CSS 主页上重新创建产品卡片演示。在此过程中,我们将看到 vanilla-extract 和 Sprinkles 如何处理伪类、响应式设计和暗模式主题。

- 为什么要使用洒水器?
- Next.js 和 vanilla-extract 入门
- 使用 Sprinkles 创建设计系统
- 将我们的 Sprinkles 库与 Tailwind CSS 进行比较
- 实施主题和响应式设计
- 添加深色主题

那么,当我们可以简单地使用 Tailwind 时,我们为什么要开发我们自己的基于 Sprinkles、实用程序优先的 CSS 库,它已经是一个如此流行的工具?三个原因:类型安全、自定义和本地范围。

首先,使用 Sprinkles,您可以获得与使用任何其他 Typescript 变量相同的类型提示和编译时验证,不再需要文档验证和类名拼写错误。

其次,Tailwind 既固执己见,也有一点学习曲线,尤其是在您不使用 Tailwind 预设语法的情况下。使用 Sprinkles,您正在编写 CSS 而不是 Tailwind 的速记类名。由于 Sprinkles 不以任何内置值开头,因此您可以按照自己喜欢的方式创建 CSS 框架。

最后,还有局部范围。vanilla-extract 在底层使用 CSS 模块的好处之一是,您的所有实用程序类现在默认情况下都是组件范围的。这意味着您可以轻松地将多个设计系统整合到单个应用程序中,而不必担心样式冲突。

## Next.js 和 vanilla-extract 入门

让我们首先创建一个新的 Next 应用程序并安装 vanilla-extract。您可以在此处的 GitHub 存储库中查看此演示项目的完整源代码。

首先创建一个新的 TypeScript 版本的 Next,如下所示:

------

超过 20 万开发人员使用 LogRocket 来创造更好的数字体验了解更多 →

------

```typescript
npx create-next-app@latest --typescript 洒-tailwind
```

运行yarn dev以确保我们的安装按预期工作后,我们将安装 vanilla-extract 和 Sprinkles:

```shell
纱线添加 @vanilla-extract/css @vanilla-extract/babel-plugin @vanilla-extract/next-plugin @vanilla-extract/sprinkles
```

接下来,通过更新以下内容,在我们的 webpack 构建过程中包含 vanilla-extract/next-plugin next.config.js:

```js
常量 {
  createVanillaExtractPlugin
} = require('@vanilla-extract/next-plugin');
const withVanillaExtract = createVanillaExtractPlugin();

/** @type {import('next').NextConfig} */
常量 nextConfig = {
  reactStrictMode:真,
};

module.exports = withVanillaExtract(nextConfig);
```

最后,因为我们希望我们的新 Sprinkles 类型被 TypeScript 编译器和我们的 IDE 的 TypeScript 服务器拾取,我们将添加*.css.ts到我们的项目中tsconfig.json:

```json
{
    ...
    "include": ["next-env.d.ts", "**/*.ts", "**/*.css.ts", "**/*.tsx"],
    ...
}
```

## 使用 Sprinkles 创建设计系统

Tailwind CSS 的主要卖点之一是它如何迫使用户在定义明确的设计系统的约束下工作,而不是不一致的一次性值。

Tailwind 还预装了一个默认系统,该系统具有合理的值和合理的快捷方式,可满足常见的布局需求。在我们的项目 Sprinkles Tailwind 中,我们将从Open Props项目中获取调色板、排版和尺寸比例。我们还将为布局添加一些常见的 Tailwind 值。

首先,我们将首先colors.css.ts在目录下创建一个文件./styles并定义我们的颜色值:

```typescript
常量调色板 = {

'灰色-0':'#f8f9fa',

'灰色-1':'#f1f3f5',
...

'灰色 9': '#212529',

'red-0': '#fff5f5',

... /* 完整调色板请参见 https://github.com/Shimin-Zhang/TailSprinkles/blob/main/styles/colors.css.ts */

};

导出默认调色板;

我们将为 , 做同样的事情border.css.ts来size.css.ts建立typography.css.ts我们设计系统的基础。

一旦我们设置了我们的设计系统值,我们将像这样定义我们的 Sprinkles 系统:

```typescript
进口 {
  定义属性,
  创建Sprinkles,
} 来自'@vanilla-extract/sprinkles';

从'./colors.css'导入调色板;
从'./typography.css'导入{fontFamily,fontWeight,lineHeight,fontSize};
从'./size.css'导入{大小,空间};
从'./border.css'导入{borderSize,borderRadius};

const responsiveProperties = defineProperties({
  特性: {
    显示:['none','flex','block','inline'],
    flexDirection:['行','列'],
    证明内容:[
      '拉紧',
      '弹性开始',
      '中央',
      '弹性端',
      '空间周围',
      '空间之间'
    ],
    对齐项目:[
      '拉紧',
      '弹性开始',
      '中央',
      '弹性端'
    ],
    paddingTop:空间,
    paddingBottom:空间,
    paddingLeft:空间,
    paddingRight:空格,
...
  },
  速记:{
    填充:[
      '填充顶部',
      '填充底部',
      'paddingLeft',
      'paddingRight'
    ],
    paddingX: ['paddingLeft', 'paddingRight'],
    paddingY: ['paddingTop', 'paddingBottom'],
...
    placeItems: ['justifyContent', 'alignItems']
  }
});

阿里云盘TV电视盒子,所有资源无限速下载,在线播放无限制!常量系统属性 = 定义属性({
  特性: {
    颜色:调色板,
    背景:调色板,
    字体家族:字体家族,
    字体大小:字体大小,
    ...
  }
});

出口常量洒= createSprinkles(
  响应属性,
  系统属性
);

导出类型 Sprinkles = 参数<typeof splashs>[0];

Sprinkles 的defineProperties功能将我们的设计系统标记转换为一组样式值。然后通过 将这些值组合在一起,createSprinkles以便用户可以以 CSS-in-JS 方式使用它们。

请注意,我们将属性分为两个单独的类别。responsiveProperties是我们稍后将以类似于 Tailwind 的视口前缀的响应方式设置样式,即md:. 系统属性将取决于主题,类似于 Tailwind 的dark:前缀。然后,我们导出生成原子类的 Sprinkles 对象及其类型,这为我们提供了类型安全性。

该shorthands键允许我们定义类似于 CSS 速记和 Tailwindpx-*, p-*类的 CSS 速记值。

接下来,我们将创建一个新页面并导入我们新的类型安全实用程序框架:

```typescript
从“下一个/头”导入头
从'../styles/sprinkles.css'导入{洒};

导出默认函数颜色(){
    返回 (
        <div>
            <头部>
            </头>
            <h1 类名={
              小雨({
                ...风格在这里
              })
            }>
                欢迎来到颜色
            </h1>
        </div>
    );
}
```

## 将我们的 Sprinkles 库与 Tailwind CSS 进行比较

让我们看看 Sprinkles 的类型安全操作。首先,我们将尝试添加一个有效的 CSS 属性 ,backgroundColor它没有在我们的 Sprinkles 应用程序中定义。我们看到它抛出了一个类型错误:

接下来,我们添加color键并看到有效值列表显示为建议:

正如预期的那样,使用不在系统内的颜色值会立即引发类型错误:

这比在文档中查找正确的 Tailwind 类名称、打错字、然后等待浏览器刷新才注意到它要快得多。

设计系统全部设置好后,我们现在可以从 Tailwind 主页中获取产品卡片示例,复制示例 HTML,并将其转换为我们新的 Sprinkles Tailwind 框架:

```html
<h1>
  顺风洒水
</h1>
<div
类名 = {
  英石({
    显示:'弹性',
    fontFamily: '无衬线',
    宽度:'尺寸内容-3',
    marginY: '自动尺寸',
    背景:“白色”,
    边界半径:'radius-3',
    boxShadow:'shadow-2'
  })
}>
  <div
    类名 = {
      英石({
        弹性:'无',
        宽度:“尺寸-12”,
        高度:'尺寸-13',
        位置:'相对',
      })
    }
    >
    <img src="/jacket.jpg" alt=""
    加载="懒惰" 类名 = {
      英石({
        位置:'绝对',
        宽度:'满',
        高度:“满”,
        objectFit: '封面',
        插图:'0'
      })}/>
  </div>
    ...
    /* 完整文件见 https://github.com/Shimin-Zhang/TailSprinkles/blob/main/pages/index.tsx */

因为我们已经在我们的sprinkles.css.ts文件中定义了我们的速记,我们可以marginY在我们的样式中使用而不是marginTop单独marginBottom编写。

我们在设计产品卡时遇到了一些问题,这些问题仅靠 Sprinkles 无法解决。Sprinkles 是纯 CSS 属性之上的最小抽象层,因此我们无法访问实用程序类,例如指示我们的按钮可点击srOnly的伪选择。:hover

我们需要引入 vanilla-extract 来创建这些更复杂的样式:

```typescript
// 首先我们导入 vanilla-extract
从'@vanilla-extract/css'导入{样式};

// 我们创建更复杂的类
导出 const srOnly = style({
  位置:'绝对',
  宽度:'1px',
  高度:'1px',
  填充:'0',
  边距:'-1px',
  溢出:'隐藏',
  剪辑:'矩形(0, 0, 0, 0)',
  whiteSpace: 'nowrap',
  边框宽度:'0'
});

导出 const clickable = style ({
  ':悬停':{
    光标:'指针'
  }
})
```

进行了一些配置,但我们设法复制了相同的夹克产品卡!虽然这不是一个精确的复制品(我们的设计系统基于 Open Props),但它是一个合理的复制品,捕捉了原始设计的精神:

------

- 不要错过来自 LogRocket 的精选时事通讯The Replay
- 使用 React 的 useEffect优化应用程序的性能
- 在多个 Node 版本之间切换
- 了解如何使用 AnimXYZ 为您的 React 应用程序制作动画
- 探索 Tauri,一个用于构建二进制文件的新框架
- 比较NestJS 与 Express.js
- 发现TypeScript 领域中使用的流行 ORM

------

仔细查看生成的 HTML,我们看到 Sprinkles 根据我们的设计标记生成了带前缀的实用程序类名称。请注意,每个类都通过 CSS 模块限定为组件:

## 实施主题和响应式设计

我们的卡在桌面上看起来很棒,但是当我们缩小视口时它没有响应。为了解决这个问题,我们将在 Sprinkles 设置中添加基于视口的条件。还记得之前我们命名了布局属性responsiveProperties吗?我们现在将添加该视口信息:

```typescript
const responsiveProperties = defineProperties({
  条件: {
    移动的: {},
    平板电脑:{'@media':'屏幕和(最小宽度:768px)'},
  },
  默认条件:'平板电脑',
  特性: {
    ... 和之前一样

因为我们从桌面版本开始,我们无法从移动优先设计开始,而是默认使用平板电脑视图。使用 Sprinkles 可以轻松创建响应式样式;而不是property: value我们目前看到的格式,我们将使用property: { condition-name: value }语法来代替。

这是带有附加移动视口布局的组件的外观:

```css
        <div
        类名 = {
          英石({
            显示:'弹性',
            fontFamily: '无衬线',
            宽度: {
              平板电脑:'size-content-3',
              移动设备:“尺寸自动”
            },
            marginY: '自动尺寸',
            边距X:{
              平板电脑:'尺寸自动' ,
              手机:'size-3' ,
            },
            背景:“白色”,
            可以做半径:' radius-3 ' ,
            boxShadow:' shadow-2 '
          })
        } >
```

添加其余的移动视口布局后,我们的卡片现在可以响应了:

我们的产品卡真的要凑齐了!

## 添加深色主题

如今,我们组件通常需要的最后一个功能是能够在各种主题之间切换。让我们为我们的产品卡片添加一个深色主题,以展示它是如何使用 Sprinkles 完成的。

与响应式设计一样,我们首先向系统属性添加条件和默认值:

```typescript
常量系统属性 = 定义属性({
  条件: {
    灯光模式:{},
    darkMode: { '@media': '(prefers-color-scheme: dark)' }:{ '@media' :'(首选颜色方案:深色)' }    
  },},
  默认条件:'lightMode',: '光模式' , 
```

与我们的响应式大小不同,这里的默认lightMode值已经是我们想要的。我们只需要在需要时添加深色主题变体。就像响应式道具一样,我们将使用条件名称来区分两个主题。

早期的<div>响应式设计和暗模式现在看起来像这样:

```css
< div 
类名= {  
  st ({
    显示:'flex',
    fontFamily : '无衬线' ,
    宽度:{
      平板电脑:'size-content-3',
      移动:“尺寸自动”
    },
    marginY : '尺寸自动' ,
    边距X:{
      平板电脑:“尺寸自动”,
      手机:'size-3',
    },
    背景:{
     lightMode : '白色' ,
     darkMode : 'grape-9' ,
    },
    边界半径:' radius-3 ' ,
    boxShadow:'影子-2 '
  })
} >
```

现在,我们最终的深色主题产品卡片如下所示:

## 结论

我希望这篇文章能说服你在下次开始一个新项目并在市场上寻找一个新的 CSS 框架时尝试一下 vanilla-extract。

就像 Tailwind CSS 一样,Sprinkles 框架允许您创建基于设计系统基础的实用程序优先的 CSS 框架。

与 Tailwind CSS 不同,使用 Sprinkles,您可以获得与其他 TypeScript 文件相同的类型安全保证,您可以按照您想要的方式对其进行完全自定义,并且您可以获得 CSS 模块的范围安全。

我非常看好 vanilla-extract 引入的类型安全的 CSS 范例。请在下面的评论部分分享您从 Tailwind CSS 迁移到 Sprinkles 的想法和经验。

## 您的前端是否占用了用户的 CPU?

随着 Web 前端变得越来越复杂,资源贪婪的功能对浏览器的要求也越来越高。如果您对监控和跟踪生产环境中所有用户的客户端 CPU 使用情况、内存使用情况等感兴趣,请尝试使用 LogRocket。

LogRocket就像一个用于 Web 和移动应用程序的 DVR,记录您的 Web 应用程序或网站中发生的一切。无需猜测问题发生的原因,您可以汇总和报告关键前端性能指标、重放用户会话以及应用程序状态、记录网络请求并自动显示所有错误。

使用 Sprinkles 构建您自己的类型安全版本的 Tailwind CSS相关推荐

  1. WCF 项目应用连载[6] - 升级Lig服务 - 设计ILigger 构建一个完善的Lig版本

    前面我们已经搞定了对ChannelFactory与ServiceHost的扩展,形成了我们自己用的两个类: public class LWCF<T> public class LServi ...

  2. tailwind css_如何使用Tailwind CSS构建样式化的登陆页面

    tailwind css 介绍 (Introduction) Developers use Cascading Style Sheets (CSS) to style websites. But of ...

  3. maven 构建java项目,jdk版本问题

    为什么80%的码农都做不了架构师?>>>    使用maven构建Java项目,默认的 jdk 版本是1.5 详情见官方说明:https://maven.apache.org/plu ...

  4. Pytorch:RNN、LSTM、GRU 构建人名分类器(one-hot版本、Embedding嵌入层版本)

    日萌社 人工智能AI:Keras PyTorch MXNet TensorFlow PaddlePaddle 深度学习实战(不定时更新) 2. RNN经典案例 2.1 使用RNN模型构建人名分类器 学 ...

  5. Android APK 的构建流程以及Gradle多版本构建

    一.APK 构建流程 1.通过AAPT2工具将各种xml文件汇总登记到R.java文件中:同时将AndroidManifest.xml生成对应的二进制文件: 2.通过AIDL工具将.aidl文件生成. ...

  6. Cmake构建_指定gcc/g++版本

    平时我们电脑上可能有多个编译器版本,可以通过设置CMAKE_C_COMPILE和CMAKE_CXX_COMPILER两个变量来设置我们的编译器路径 SET(CMAKE_C_COMPILER " ...

  7. 构建稳固的、可升缩的CSS框架的八大原则

    为什么80%的码农都做不了架构师?>>>    这些原则都是我从这些年工作中所含盖的各个大型.复杂的web项目中总结出来的.而这些事情也都是我这些年被多次问到的,所以觉得将其用文档的 ...

  8. 兼容IE各版本的纯CSS二级下拉菜单

    这是一个标准的CSS下拉菜单制作教程,有针对目前流行的IE6/IE7/IE8不同版本的CSS代码,因此可以在IE之间完全兼容,不过其它的浏览器像火狐/GG浏览器之类的没有测试,如果兼容IE8的话,那么 ...

  9. html使用最ie高版本,从html,css,javascript三方面谈谈“浏览器兼容性”的问题

    不同浏览器的标签默认的外补丁和内补丁不同 *{margin:0;padding:0;} css的hack问题:主要针对IE的不同版本,不同的浏览器的写法不同 IE的条件注释hack: 块属性标签flo ...

  10. 版本向量 使用css时正确区分IE版本[转]

    Windows Internet Explorer Web Windows Internet Explorer 8 版本向量是指的内部版本号,它存储在浏览器启动时读取的注册表项中.开发人员可以使用版本 ...

最新文章

  1. SpringBoot_配置-@Conditional自动配置报告
  2. ubuntu apache php mysql phpmyadmin_Ubuntu下Apache+PHP+MySQL+phpMyAdmin的快速安装步骤
  3. opencv 模板匹配(cvMatchTemplate)
  4. html怎么在字体中加波浪线,CSS3实现文字波浪线效果
  5. 项目验收文档合并技巧
  6. Swift 3.0 使用Core Data
  7. 「硬见小百科」一文详解红外遥控模块工作原理
  8. java定时每小时_java 定时任务,每日运行和每小时运行。
  9. 监理项目的服务器,idc服务器机房搬迁工程施工监理的重点
  10. 多层交换机静态路由实验
  11. 移植内核2.6.24.4到S3C2440
  12. 在Linux服务器上解压rar压缩文件
  13. 【板绘手绘线稿素材资料】从素描到板绘,超全的人物嘴巴画法!
  14. MATLAB画带厚度的圆弧线
  15. sqlite如何创建数据库
  16. elasticsearch win10 安装
  17. Make It a Chorus: Knowledge- and Time-aware Item Modeling for Sequential Recommendation sigir 20
  18. web网页设计期末课程大作业:动漫主题网站设计——关于我转生史莱姆这件事(6页)HTML+CSS
  19. 【数据结构】数据结构的基本概念——逻辑结构、存储结构、抽象数据类型
  20. RabbitMQ的应用场景

热门文章

  1. Docker Build Cache 缓存清理
  2. 《诗经·王风·黍离》
  3. Retrofit 框架详解和使用
  4. 微信小程序云开发之云函数与本地数据库获取数据
  5. 汇编语言小写字母转大写字母
  6. Android实现校园新闻APP,基于android平台的校园新闻app的开发 大学毕业论文.doc
  7. python中的join是什么意思_python里join是什么意思
  8. 2022hdu多校1C题题解
  9. 松下P2卡数据恢复-删除/格式化100%完美恢复-解决方案
  10. Win11删除英文输入法的方法教程