تاروپود — خودآموز HTML و CSS

فصل ۴ از ۱۱

پیشرفت ترم
۰٪

ترم ۶ · حرفه‌ای و واقعی

design system کوچک خودت

فصل ۴پیش‌نمایش رایگان
۸ دقیقه مطالعه فصل ۴

در این فصل چه می‌سازی#

فصلِ قبل component های مستقل ساختی. ولی وقتی چند component داری — کارت، دکمه، قیمت — از کجا مطمئن شوی همه یک زبانِ بصری دارند؟ یک آبیِ واحد، یک ریتمِ فاصلهٔ واحد، یک گوشهٔ گِردیِ واحد؟ حرفه‌ای‌ها این را با یک design system کوچک حل می‌کنند: چند مقدارِ پایه که یک بار تعریف می‌شوند و همه‌جا به‌کار می‌روند. این فصل رنگ و فاصله و فونتِ صفحه را به design token تبدیل می‌کنی و می‌بینی که تغییرِ یک خط، کلِ ظاهرِ سایت را هماهنگ عوض می‌کند.

چند design token در یک ستون سمت راست — چند نمونهٔ رنگ، چند پلهٔ فاصله، یک شکلِ گوشهٔ گِرد — که با خطوطی به یک کارت و یک دکمه در سمت چپ وصل شده‌اند و رنگ و فاصلهٔ آن‌ها را تغذیه می‌کنند

آخر این فصل می‌توانی:

  • رنگ و فاصله و فونت را به‌شکلِ design token در :root تعریف کنی
  • یک مقیاسِ فاصله بسازی و به‌جای عددهای دلبخواه از آن استفاده کنی
  • با var() همان token ها را در چند component به‌کار ببری
  • با عوض‌کردنِ یک خط، رنگِ کلِ صفحه را یک‌دست تغییر بدهی

قبل از شروع#

  • از ترم ۲: custom properties — --name، var()، و اینکه :root یعنی «کلِ صفحه». این فصل کاربردِ حرفه‌ایِ همان است.
  • از فصل ۱ همین ترم: اسم‌گذاریِ یک‌دست و بخش‌بندیِ فایل.
  • از فصل ۳ همین ترم: component ها (کارت و دکمه) که این‌بار با token تغذیه‌شان می‌کنیم.

مثل همیشه فقط یک مرورگر لازم داری، یا فقط همین آزمایشگاه.

۱. مشکلِ عددهای جادویی#

به این تکه نگاه کن. قیمت و دکمه هر دو قرار بوده «آبیِ برند» باشند، و هر کدام یک padding و margin دستی دارند:

.card__price {
  color: #2a6b93;
  margin-block-end: 14px;
}

.btn {
  background-color: #2b6d95;
  border-radius: 8px;
  padding: 8px 15px;
}

با دقت به دو رنگ نگاه کن: #2a6b93 و #2b6d95. این‌ها قرار بوده یک رنگ باشند، ولی چون هر کدام را جدا با دست تایپ کرده‌ای، کمی از هم فاصله گرفته‌اند. روی صفحه، قیمت و دکمه دو آبیِ کمی متفاوت دارند — و چشم این ناهماهنگیِ ریز را حس می‌کند، حتی اگر نتواند دقیق بگوید چرا.

🔧 اگر کار نکرد: به این «drift» می‌گویند — عددهایی که باید یکی باشند، به‌مرور از هم دور می‌افتند. مشکل این است که «آبیِ برند» در کدت اسم ندارد؛ فقط چند کپیِ دست‌نویسِ یک عدد است، و کپی‌ها هیچ‌وقت دقیق هم نمی‌مانند. حالا تصور کن بخواهی رنگِ برند را عوض کنی: باید تک‌تکِ این کپی‌ها را پیدا کنی و یکی را هم که جا انداختی، تا ابد آبیِ قدیمی می‌ماند. راهِ درست این است که آن رنگ را یک بار اسم بگذاری و همه‌جا به همان اسم اشاره کنی.

۲. design token: یک بار تعریف کن، همه‌جا استفاده کن#

یک design token چیزی جز یک custom property با اسمِ بامعنا نیست — همان --name که در ترم ۲ ساختی، ولی این‌بار به‌عنوان واحدِ پایهٔ یک سیستم. token ها را در :root تعریف کن تا کلِ صفحه ببیندشان:

:root {
  --color-brand: #2a6b93;
  --color-surface: #ffffff;
  --color-ink: #2c2114;
}

حالا هرجا آن آبی را می‌خواهی، به‌جای تایپِ دوبارهٔ عدد، به token اشاره کن:

.card__price {
  color: var(--color-brand);
}

.btn {
  background-color: var(--color-brand);
}

چک کن: حالا قیمت و دکمه دقیقاً یک آبی دارند، چون هر دو به همان یک token اشاره می‌کنند؛ دیگر امکانِ drift نیست. مهم‌تر: خطِ --color-brand: #2a6b93; را به یک رنگِ دیگر (مثلاً #7a4f9e) عوض کن. هم قیمت، هم دکمه، با هم بنفش می‌شوند. یک خط، کلِ برند.

Checkpoint. قبل از ادامه، جواب بده: اگر برندِ سایت را از آبی به سبز ببری، در نسخهٔ اولِ این فصل (با عددهای دستی) چند جا را باید عوض کنی، و در نسخهٔ token چند جا؟ (جواب: در نسخهٔ دستی، هر جایی که عدد کپی شده — و همیشه خطرِ جا انداختنِ یکی هست؛ در نسخهٔ token، دقیقاً یک جا.)

۳. یک مقیاس برای فاصله‌ها#

همان بیماری برای فاصله‌ها هم هست: یکی 14px، یکی 15px، یکی 20px — عددهایی که هیچ منطقی بینشان نیست. جوابش یک مقیاس است: یک فهرستِ کوتاه و منظم از فاصله‌های مجاز که همه از آن انتخاب می‌کنند. یک مقیاسِ ساده و پرکاربرد، هر پله را روی پلهٔ قبلی می‌سازد:

:root {
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 16px;
  --space-4: 24px;
}

حالا به‌جای عددهای دلبخواه، از این پله‌ها استفاده کن: padding: var(--space-3)، gap: var(--space-3)، margin-block-end: var(--space-2). چون همه از یک مقیاس می‌آیند، فاصله‌های صفحه یک ریتمِ یک‌دست پیدا می‌کنند، نه یک مشت عددِ تصادفی.

💡 نکته: مقیاس فقط برای فاصله نیست. همان فکر را برای گوشهٔ گِرد (--radius) و فونت (--font-base) هم به‌کار ببر. هر مقداری که بیش از یک بار تکرار می‌شود، یک نامزدِ خوب برای token است. قانون: اگر دو بار تایپش کردی، احتمالاً باید یک token باشد.

کد کاملِ این فصل#

اول styles.css با همهٔ token ها بالای فایل، و بعد component ها که فقط به token اشاره می‌کنند:

/* styles.css */
:root {
  /* rang-ha */
  --color-page: #f6edda;
  --color-surface: #ffffff;
  --color-ink: #2c2114;
  --color-brand: #2a6b93;

  /* meghyas-e faseleh: har pele rooye ghabli mikhabad */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 16px;
  --space-4: 24px;

  /* shekl */
  --radius: 10px;
  --font-base: Tahoma, sans-serif;
}

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

body {
  font-family: var(--font-base);
  background-color: var(--color-page);
  color: var(--color-ink);
  line-height: 1.7;
}

.page {
  max-width: 560px;
  margin-inline: auto;
  padding: var(--space-4);
}

h1 {
  margin-block-end: var(--space-4);
}

.cards {
  list-style: none;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-3);
}

.card {
  background-color: var(--color-surface);
  border: 1px solid #d8ccae;
  border-radius: var(--radius);
  padding: var(--space-3);
}

.card__title {
  font-size: 1.1rem;
  margin-block-end: var(--space-2);
}

.card__price {
  color: var(--color-brand);
  margin-block-end: var(--space-3);
}

.btn {
  font: inherit;
  background-color: var(--color-brand);
  color: var(--color-surface);
  border: none;
  border-radius: var(--radius);
  padding: var(--space-2) var(--space-3);
  cursor: pointer;
}

و index.html:

<!-- index.html -->
<!DOCTYPE html>
<html lang="fa" dir="rtl">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>design system کوچک</title>
    <link rel="stylesheet" href="styles.css">
  </head>
  <body>
    <main class="page">
      <h1>محصولات</h1>
      <ul class="cards">
        <li class="card">
          <h2 class="card__title">هدفون</h2>
          <p class="card__price">۲۵۰ هزار تومان</p>
          <button class="btn">خرید</button>
        </li>
        <li class="card">
          <h2 class="card__title">کیبورد</h2>
          <p class="card__price">۴۸۰ هزار تومان</p>
          <button class="btn">خرید</button>
        </li>
      </ul>
    </main>
  </body>
</html>

چک کن: دو کارتِ هماهنگ می‌بینی؛ گوشه‌ها یک‌اندازه گِرد، آبیِ قیمت و دکمه دقیقاً یکی، و فاصله‌ها با یک ریتمِ منظم. حالا فقط --radius را از 10px به 2px عوض کن — کارت‌ها و دکمه‌ها، همه با هم، تیزگوشه می‌شوند. این کلِ ایدهٔ design system است: چند مقدارِ پایه که همه‌چیز از آن‌ها تغذیه می‌شود.

دو کارتِ محصولِ کاملاً هماهنگ کنارِ هم، با گوشه‌های یک‌اندازه گِرد، دکمه‌های هم‌رنگ، و فاصله‌های منظم — همه از یک مجموعه token واحد

🤖 با AI: فهرستِ token هایت را به دستیار AI ات بده و بپرس «کدام عددهای دیگرِ این فایل بهتر است token شوند؟». جوابش را با معیارِ خودت بسنج (هر مقداری که بیش از یک بار تکرار شده) و در آزمایشگاه امتحان کن. مواظب باش: AI گاهی پیشنهاد می‌کند برای هر مقدار token بسازی، حتی آن‌هایی که فقط یک بار به‌کار رفته‌اند — این سیستم را شلوغ می‌کند، نه یک‌دست. token برای چیزی است که تکرار می‌شود.

واژه‌های تازهٔ این فصل#

کلمه تلفظ به حروف فارسی یعنی چه
design token دیزاین توکِن یک مقدارِ پایهٔ نام‌دار (رنگ/فاصله/فونت) که همه‌جا به‌کار می‌رود
scale اِسکِیل یک فهرستِ منظم و کوتاه از مقدارهای مجاز (مثلِ مقیاسِ فاصله)
drift دِریفت وقتی چند کپیِ دستیِ یک مقدار، به‌مرور از هم دور می‌افتند
consistency کانسیستِنسی یک‌دستی؛ اینکه همهٔ component ها یک زبانِ بصری داشته باشند

تمرین‌ها

اول خودت فکر کن یا امتحان کن — بعد اینجا را باز کن.

در فصل بعد#

الان یک design system کوچکِ خودت را داری: token های رنگ و فاصله و فونت که کلِ ظاهر را یک‌دست و قابل‌تغییر نگه می‌دارند. تا اینجا همهٔ گرافیک‌هایمان مستطیل و دایره و رنگ بوده. فصل بعد یک ابزارِ تازه برای گرافیک یاد می‌گیری: <svg> — که با آن می‌توانی آیکون‌ها و شکل‌های بُرداریِ دقیق بسازی که در هر اندازه‌ای تیز و تمیز می‌مانند، و حتی رنگشان را با همین token هایی که امروز ساختی کنترل کنی.

به آخر این فصل رسیدی!

اگر ساختی و جواب داد، این دکمه مال توست.