首頁 > web前端 > css教學 > 主體

將 Tailwind 配置為設計系統

Barbara Streisand
發布: 2024-09-19 14:15:03
原創
621 人瀏覽過

對設計系統來說,一致性和理解性就是一切。一個好的設計系統透過實現它的程式碼的配置來確保實現的一致性。它需要是:

  • 易於理解,無需放棄優秀設計所需的細微差別;
  • 可擴充和可維護,且不影響一致性。

使用我的預設 React 堆疊和 Tailwind,我將向您展示如何設定自己的版式、顏色和間距預設值,而不僅僅是區分應用程式外觀和感覺的起點。更重要的是,它大大減少了我們需要編寫和維護的程式碼,從而減少了以系統化、一致和無錯誤的方式實現樣式的精神負擔。

我將從我經常看到的一個主要批評開始,然後分解我用來解決它的一系列配置步驟。

易於使用並不等於易於掌握知識

Tailwind 讓開發人員可以輕鬆編寫樣式,這對於快速原型設計非常有用。但這種輕鬆並不能保證良好的設計或可擴展、可維護的設計系統。

像 Tailwind 這樣的預設和零配置工具是基礎設施速度層,可以為建置創造更多時間。但是,如果您要擴展一個使用設計系統來區分自己的應用程序,則不能僅僅依賴“像午餐一樣免費”的開箱即用配置。

如果您使用預設的 Tailwind 配置運行並將樣式管理推送到組件上的類應用程序,結果通常是一堆難以推理的類分佈在組件中,偽裝成設計系統。

Configuring Tailwind as a Design System

上面就是一個很好的例子。它幾乎難以辨認,需要大量時間才能理解,更不用說操縱了。嘗試這樣做很可能會導致重複和錯誤,從而逐漸偏離整個應用程式的設計一致性。

很容易將您的設計類別合併到單一 className 中。但要這麼做並不容易。

配置您的系統以方便了解

易用性需要權衡。使用別人的標準意味著依賴他們的專業知識。這可能是有益的,但也可能是個陷阱。讓我們退後一步,思考一下設計系統的基礎知識包含哪些內容:

  • 排版
  • 顏色
  • 間距
  • 反應能力(含顏色模式)

在 React with Tailwind 的背景下,這些和許多其他設計系統元素都在 Tailwind 配置中設置,我們可以對其進行自訂。

{/* 更漂亮-忽略 */}

const config = {
  theme: {
    fontSize: { /* ... */ },
    colors: { /* ... */ },
    spacing: { /* ... */ },
  },
};
登入後複製

印刷預設值

您是否曾經努力記住小文本的正確字母間距?如果您可以設定一次然後忘記它怎麼辦?

我們可以直接在 tailwind.config 中將前導(行高)和追蹤(字母間距)設定為每個字體大小元組的參數。這意味著當我們使用字體大小類別時,我們不需要設定行距或追蹤。無需記住(或無法找到)小文本的字母間距是多少。

fontSize: {
  small: [
    "13px",
    { lineHeight: 1.5, letterSpacing: "0.015em" },
  ],
  base: [
    "16px",
    { lineHeight: 1.5, letterSpacing: 0 },
  ],
}
登入後複製

現在使用 text-small 設定字體大小、行高和字母間距。將核心印刷元組封裝在一個類別中,將這些值的實作集中到配置中,而不是跨程式碼庫。可維護性的巨大勝利。

/* 13px/1.5 with 0.015em letter-spacing */
<div className="text-small" />
登入後複製

顏色預設值

我們可以使用 CSS 變數在 :root 和 html.dark 範圍下設定響應式顏色。這意味著我們編寫和管理一個類,例如 bg-canvas,而不是兩個類,例如 bg-gray-100 dark:bg-gray-800。

@import "@radix-ui/colors/gray.css";
@import "@radix-ui/colors/gray-dark.css";

:root {
  --color-gray-base: var(--gray-1);
  --color-gray-bg: var(--gray-3);
  --color-gray-line: var(--gray-4);
  --color-gray-border: var(--gray-5);
  --color-gray-solid: var(--gray-10);
  --color-gray-fill: var(--gray-12);
}
登入後複製

因為我在這裡使用 Radix Colors,所以我不需要設定 .dark 範圍,因為這已經為我完成了。如果您不喜歡基數顏色,您可以自訂它們、使用其他庫或編寫自己的庫。

然後在 Tailwind 配置中設定 CSS 變數。

colors: {
  canvas: "var(--color-gray-base)",
  background: "var(--color-gray-bg)",
  line: "var(--color-gray-line)",
  border: "var(--color-gray-border)",
  solid: "var(--color-gray-solid)",
  fill: "var(--color-gray-fill-contrast)",
}
登入後複製

現在使用 bg-canvas 在淺色或深色模式下設定適當的顏色。在程式碼庫中刪除這種重複可以將顏色管理集中到我們的配置中,而不是將其分散到元件上的類別的實作中。認知和可維護性的巨大勝利。

/* sets --gray-1 as #fcfcfc on :root or #111111 on html.dark */
<div className="bg-canvas" />
登入後複製

語意命名

我提倡顏色和字體大小的語義名稱,因為語義命名是一種將含義與使用聯繫起來的強制功能。這樣做可以消除實現猜測工作並減少錯誤。

我看過無數項目,其中背景都使用了不一致的gray-50、gray-100或gray-200。透過定義一種稱為背景的顏色可以輕鬆解決這個問題。

In the same way, it is easier to remember the names for dark and light text colors when they are called fill and solid. It's harder and more error-prone when they're called gray-900 and gray-600 because then you have to remember specifically that it wasn't gray-950 and gray-500, or gray-800 and gray-700.

But naming things—and agreeing on naming—is hard. In the spirit of zero-config, I suggest taking Radix Color's backgrounds, borders, solids & fills paradigm. Or this palette semantics.

And once you've set this in tailwind.config, Typescript will jog your memory at your fingertips with autocomplete.

Avoid namespace clashes

If you're extending a Tailwind theme and not writing your own, don't use a scale key that's already been used. You may inadvertently overwrite a class that you need to use.

You'll note in the previous colour config example that I set the --color-gray-base var to canvas, not base. If I used base then using this color scale as a text colour (text-base) would clash with the default font-size base value, which is also text-base.

This isn't a downfall of customising the Tailwind config, it's a legacy of its theme naming: setting font-size or color classes in Tailwind both use text-*.1

Spacing defaults

We can also use CSS variables to set spacings.

:root {
  --height-nav: 80px;
  --height-tab: 54px;
  --space-inset: 20px;
  --container-text-px: 660px;
  --container-hero-px: 1000px;
}
登入後複製
spacing: {
  em: "1em", /* relate icon size to parent font-size */
  nav: "var(--height-nav)",
  inset: "var(--space-inset)",
  text: "var(--container-text)",
  hero: "var(--container-hero)",
}
登入後複製

One could argue this is over-engineering. Except that when it comes time to compute complex interactive layouts like sticky headers, scroll margins and so on, this upfront configuration work makes it straight forward and error-free, to the pixel.

<div className="top-[calc(theme(spacing.nav)+theme(spacing.tab))]">
  <div className="scroll-mt-[calc(theme(spacing.nav)+theme(spacing.tab))]">
    /* ... */
  </div>
</div>
登入後複製

Note again the use of semantic naming makes it easy to remember and use.

Augmenting your Tailwind config

We have now configured typography, colour and spacing tokens in a manner that is easy to understand and maintain in a single, centralised place. And we don't need to wrire as many classes to implement the system. Winning. And there's further steps we can take to reduce this implementation overhead.

Clamp() your classes

What if I told you there's a way to completely avoid writing text-lg lg:text-xl xl:text-2xl p-2 md:p-4 lg:p-8 everywhere?

We can avoid setting responsive font-size classes by using clamp as a a font-size value in tailwind.config. Here's the simple clamp function I use.

fontSize: {
  title: [
    /* clamp(17px, 14.1429px + 0.5714vw, 21px) */
    generateClampSize(500, 1200, 17, 21),
    { lineHeight: 1.5, letterSpacing: "-0.015em" },
  ];
}
登入後複製

So instead of writing text-lg lg:text-xl xl:text-2xl we can just write text-title. Once again, by hoisting font-size responsiveness into a clamp value, we avoid the "implement classes" pitfall again, saving mental effort, errors and debugging time.

Keep in mind, this means we've moved from text-lg lg:text-xl xl:text-2xl leading-none tracking-wide to text-title by properly configuring Tailwind. Winning!

/* 17px at 500px, 21px at 1200, fluidly calculated inbetween */
/* …with default line-height and letter-spacing also specified */
<h2 className="text-title">
  Heading copy
</h2>
登入後複製

We can also do this for spacing. When extending a theme, I prefix these keys with d for "dynamic" to differentiate it from the default spacing scale.

spacing: {
  /* lower value is 2/3 of upper value */
  d4: generateClampSize(500, 1200, 10.5, 16),
  d8: generateClampSize(500, 1200, 21, 32),
  d16: generateClampSize(500, 1200, 43, 64),
  d24: generateClampSize(500, 1200, 64, 96),
  d64: generateClampSize(500, 1200, 171, 256),
}
登入後複製

This allows us to write py-d24 instead of py-16 md:py-20 lg:py-24. This alleviates the weight of holding a range of website versions for each media-query in our minds. Instead it encourages us to picture fluidly responsive layouts where measurements don't matter as much as consistent relationships.

<main className="pt-d24 pb-d64 space-y-w8">
  <header className="container max-w-hero space-y-1">
    /* ... */
  </header>
  <article className="container space-y-2">
    /* ... */
  </article>
</main>
登入後複製

Summary

Well-crafted UI is your last defense against the coming slopwave of careless AI apps. Here's how customizing Tailwind can save you time and headaches so you can focus on the irrational amount of care it takes to build UI that works in the blink of an eye:

  • Use tailwind.config to its full potential. Centralize and group your design tokens and avoid the "implement classes everywhere" trap.
  • Use clamp() for fluid typography and spacing.
  • Set color variables on :root and .dark for effortless dark mode.
  • Name colors and spacing semantically: background beats gray-100 any day.
  • Relate icons to text size with size-em.

Yes, there's an upfront time cost. But it pays off in spades: less code, fewer errors, greater design consistency, and a team that actually understands the system.

Next up: We'll explore how to use Class Variance Authority to create a bulletproof styling API with semantic props drawn from Tailwind. Stay tuned.


  1. This is also why I dislike using tailwind-merge to remove duplicate Tailwind classes in JSX. More often than not, I find it removing a text-color in favour of a text-fontSize when both are needed. I'm surprised more developers don't raise this issue. ↩

以上是將 Tailwind 配置為設計系統的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:dev.to
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!