【问题标题】:Design system: styles override using TailwindCSS设计系统:使用 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

【问题讨论】:

    标签: javascript css reactjs tailwind-css


    【解决方案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
    猜你喜欢
    • 2022-06-19
    • 1970-01-01
    • 2016-10-12
    • 2018-01-06
    • 2015-04-30
    • 2011-12-11
    • 1970-01-01
    • 2012-12-07
    • 2013-01-19
    相关资源
    最近更新 更多