设计系统:使用 TailwindCSS 覆盖样式
Posted
技术标签:
【中文标题】设计系统:使用 TailwindCSS 覆盖样式【英文标题】:Design system: styles override using TailwindCSS 【发布时间】:2021-06-08 21:09:05 【问题描述】:我正在尝试使用 ReactJS 和 TailwindCSS 创建一个设计系统。
我创建了一个默认的Button
组件,其基本样式如下:
import React from "react";
import classNames from "classnames";
const Button = React.forwardRef(
( children, className = "", onClick , ref) =>
const buttonClasses = classNames(
className,
"w-24 py-3 bg-red-500 text-white font-bold rounded-full"
);
const commonProps =
className: buttonClasses,
onClick,
ref
;
return React.createElement(
"button",
...commonProps, type: "button" ,
children
);
);
export default Button;
然后我在我的页面中使用Button
,例如:
import Button from "../src/components/Button";
export default function IndexPage()
return (
<div>
<Button onClick=() => console.log("TODO")>Vanilla Button</Button>
<div className="h-2" />
<Button
className="w-6 py-2 bg-blue-500 rounded-sm"
onClick=() => console.log("TODO")
>
Custom Button
</Button>
</div>
);
这是显示的内容:
有些属性像 background-color
一样被覆盖,但有些不是(其余的)。
原因是 TailwindCSS 提供的类是按照 bg-blue-500
放在 bg-red-500
之后的顺序编写的,因此会覆盖它。另一方面,自定义按钮中提供的其他类在基本按钮上的类之前编写,因此不会覆盖样式。
TailwindCSS 会发生这种行为,但只要类顺序可以产生这种情况,其他任何样式方法都可能会发生这种情况。
您是否有任何解决方法/解决方案来启用这种自定义?
如果需要,这里是完整的CodeSanbox。
【问题讨论】:
【参考方案1】:一种方法是在组件层中使用 Tailwind 的 @apply
从组件中获取 extract component classes。
/* main.css */
@layer components
.base-button
@apply w-24 py-3 bg-red-500 text-white font-bold rounded-full;
// Button.js
const Button = React.forwardRef(( children, className = "", onClick , ref) =>
const buttonClasses = classNames("base-button", className);
// ...
);
这会将样式提取到新的base-button
类中,这意味着它们可以很容易地被您传递给Button
组件的实用程序类覆盖。
【讨论】:
谢谢我今天早上在文档中发现了@apply 的用法,但直到现在才有时间尝试。您的回答是确认这应该是处理此问题的正确方法。立即测试。 确认它按预期工作并且似乎是解决此问题的正确方法。 在 Next 应用程序中使用 Styled Components 的任何方式?尝试使用父样式组件中的指令,但它没有做任何事情【参考方案2】:另一种使用 Tailwind 创建可重用 React 组件的方法如下。
阅读此要点
https://gist.github.com/RobinMalfait/490a0560a7cfde985d435ad93f8094c5
举一个很好的例子。
避免使用 className 作为道具。否则,你很难知道你的组件处于什么状态。如果你想添加一个额外的类,你可以很容易地扩展。
您需要一个助手来有条件地组合类名字符串。本要点的作者 Robert 也与我们分享了辅助函数:
export function classNames(...classes: (false | null | undefined | string)[])
return classes.filter(Boolean).join(" ");
【讨论】:
npm 上的 classNames 包已经做到了这一点,并在原帖中使用。【参考方案3】:要解决这个问题,我建议做 Bootstrap 所做的事情。为您的默认按钮使用默认类,例如:
.button
width: 2rem;
background-color: red;
border-radius: 0.25rem;
然后,在自定义按钮时,您应该应用位于 CSS 文件中按钮类之后的类,或者位于在默认 CSS 文件之后调用的不同 CSS 文件中的类,或者使用 !important
声明。
旧答案 使用您的浏览器开发工具来观察您的浏览器如何在元素上加载 CSS 样式。例如,在 Chrome 中,右键单击自定义按钮并选择“检查”。将打开一个 DevTools 窗口,该元素将在 DOM 中突出显示。
在右侧,您应该有一个样式窗格。在那里,您将看到应用于元素的所有 CSS 样式的列表。带有删除线的样式被其他 CSS 类或内联样式调用的样式所覆盖。
在您的情况下,自定义按钮同时具有“CommonProps”类和您在 IndexPage 中添加的类。例如w-6
类和w-24
类。
类 w-24
是覆盖类 w-6
因为 CSS 优先级。 Read more about CSS precedence here. 在接受的答案中查看规则#3。我想这就是发生在你身上的事情。
要解决这个问题,您可能需要从 commonProps 中删除一些类。或者在某些类上使用!important
声明。这是您需要考虑的设计系统的一部分。看看 Bootstrap 等其他系统是如何做到的。
【讨论】:
感谢您的快速回答。事实上,我知道问题与 CSS 优先级有关,这也是我在问题本身中所解释的。无论如何,谢谢你的努力。 @Florian_L 抱歉,我没有阅读您的整个问题,并认为我知道这一切。更新了我的答案。 是的,我知道如何使用常规 css 方法解决此排序问题。但是,当使用 tailwindcss.com 作为实用程序优先的框架时,您不是编写 CSS 的人,而是更多地使用定义的类来编写样式。我想知道的是,是否有任何选项可以让我使用 TailwindCSS 以 100% 完成使用。 @Florian_L 我认为您不能仅使用 Tailwind 就拥有基本样式。查看有关该主题的文档:tailwindcss.com/docs/adding-base-styles 他们建议为此使用他们的 Preflight 样式表。 是的,我同意。要走的路是使用tailwindcss.com/docs/extracting-components以上是关于设计系统:使用 TailwindCSS 覆盖样式的主要内容,如果未能解决你的问题,请参考以下文章
如何使表格占据所有水平空间 TailwindCSS (React)
NuxtJS + BootstrapVue + TailwindCSS:我可以有效地使用 Bootstrap Vue 组件,但使用 Tailwind CSS 样式?