> 웹 프론트엔드 > CSS 튜토리얼 > Tailwind를 디자인 시스템으로 구성

Tailwind를 디자인 시스템으로 구성

Barbara Streisand
풀어 주다: 2024-09-19 14:15:03
원래의
641명이 탐색했습니다.

디자인 시스템에서는 일관성과 이해력이 가장 중요합니다. 좋은 디자인 시스템은 이를 구현하는 코드 구성을 통해 구현의 일관성을 보장합니다. 다음과 같아야 합니다.

  • 좋은 디자인이 요구하는 뉘앙스를 간과하지 않고 이해하기 쉽습니다.
  • 일관성을 저하시키지 않으면서 확장성과 유지 관리가 가능합니다.

Tailwind와 함께 내 기본 React 스택을 사용하여 타이포그래피, 색상 및 간격에 대한 고유한 기본값을 설정하는 것이 앱의 모양과 느낌을 차별화하기 위한 시작점이 아니라는 점을 보여 드리겠습니다. 더 중요한 것은 작성하고 유지 관리해야 하는 코드를 대폭 줄여 체계적이고 일관되며 오류 없는 방식으로 스타일을 구현하는 데 따른 정신적 부담을 줄여준다는 것입니다.

항상 볼 수 있는 주요 비판부터 시작하여 이를 해결하기 위해 사용하는 일련의 구성 단계를 분석하겠습니다.

사용의 용이성은 지식의 용이성과 동일하지 않습니다.

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-gray-100 dark:bg-gray-800과 같은 두 개의 클래스 대신 bg-canvas와 같은 하나의 클래스를 작성하고 관리한다는 의미입니다.

@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 범위가 이미 설정되어 있으므로 설정할 필요가 없습니다. Radix 색상이 마음에 들지 않으면 맞춤설정하거나 다른 라이브러리를 사용하거나 직접 작성할 수 있습니다.

그런 다음 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" />
로그인 후 복사

의미론적 명명

저는 의미론적 이름을 사용하기 위해 의미를 묶는 강제 기능이기 때문에 색상과 글꼴 크기에 의미론적 이름을 옹호합니다. 이렇게 하면 구현 추측 작업이 제거되고 오류가 줄어듭니다.

일관되지 않은 회색-50, 회색-100 또는 회색-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으로 문의하세요.
저자별 최신 기사
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿