ساختن کارت

نمای کلی

کارت یک محتوای مرتبط یا یک انتخاب را گروه‌بندی می‌کند. این یک الگوی دیداری است، نه یک مدل معنایی یا تعاملی ثابت، بنابراین معنی محتوا را حفظ کنید و از تعامل بومی که با هدف آن مطابقت دارد استفاده کنید.

رهنمودها

معناشناسی را برای محتوا و تعامل آن به‌طور جداگانه انتخاب کنید:

  • از <article> به‌عنوان ریشه کارت استفاده کنید، چه به مقصدی پیوند داشته باشد چه نداشته باشد؛
  • از پیوند بومی برای پیمایش استفاده کنید. وقتی کل کارت یک مقصد است، یک پیوند تکی فقط درصورتی می‌تواند <article> را دربرگیرد که کارت حاوی هیچ عنصر تعاملی دیگری نباشد (a، button، input، select، textarea)؛
  • پیوندها و دکمه‌های کنش‌های مستقل را به‌عنوان کنترل‌های بومی جداگانه نگه دارید؛
  • وقتی کارت یک گزینه است، از دکمه رادیویی یا چارگوش انتخاب با <label> مرتبط، یا option در <select> اصلی استفاده کنید.

رسانه، عنوان، محتوای پشتیبانی، و کنش‌ها را در ترتیب منبع معنادار نگه دارید؛ از CSS order برای نقض آن استفاده نکنید (به طرح‌بندی‌های CSS و طراحی واکنش‌گرا مراجعه کنید).

پیاده‌سازی

نشانه‌گذاری را در حداقل نگه دارید و اجازه دهید گزینشگران CSS هر منطقه را تشخیص دهند، تا کارت‌های ساده ساده بمانند و کارت‌های غنی‌تر ممکن باشند. کارت حداکثر چهار منطقه دارد که به این ترتیب منبع هستند و هرکدام از آن‌ها را می‌توان حذف کرد. مناطق فرزندان مستقیم کارت هستند و در عناصر پوششی مانند .card__body گروه‌بندی نمی‌شوند، که این امر از قرار دادن و سبک‌دهی مناطق توسط انتخاب‌گر جلوگیری می‌کند. منطقه‌ای با یک عنصر، خود آن عنصر است، نه پیچیده: یک پاراگراف تنها <p> است. فقط زمانی از پوشاننده استفاده کنید که یک منطقه حاوی چند عنصر باشد.

  • رسانه: <img>، <picture>، <video>، یا <svg> به‌عنوان اولین فرزند. کلاس .media را فقط به محتوای پیشرو دلخواه که یکی از آن عناصر نیست اضافه کنید و هرگز <img> ساده را در عنصر .media قرار ندهید.
  • سرصفحه: سرصفحه‌ای که به‌تنهایی قرار دارد. از <hgroup> فقط زمانی استفاده کنید که عنوان دارای زیرعنوان یا عبارت تبلیغاتی باشد، و از <header> زمانی استفاده کنید که منطقه حاوی چیزی بیشتر از عنوان باشد، مثلاً نام نویسنده یا نشان. وقتی کارت مقصد اصلی دارد، پیوند داخل عنوان قرار می‌گیرد.
  • محتوا: یک <p>، <ul>، یا <dl> به‌تنهایی قرار دارد. وقتی محتوا از چند عنصر تشکیل شده است، مثلاً چند پاراگراف یا یک پاراگراف به‌علاوه یک فهرست، آن‌ها را در یک <div> گروه‌بندی کنید تا ناحیه یک مورد جدولی واحد باشد.
  • پانویس: <footer> که کنش‌های مستقل را به‌عنوان پیوندها و دکمه‌های بومی نگه می‌دارد. پیوند «بیشتر بخوانید» ممکن است نشانی وب پیوند عنوان را هم‌رسانی کند، اما نام دسترس‌پذیر توصیفی‌ای به آن بدهید که با نوشتار نمایان شروع شود و از نوشتار پنهان‌شده به‌صورت دیداری استفاده کند (برای مثال، Read more<span> about poached eggs</span>)، زیرا پیوندهای «بیشتر بخوانید» یکسان در فهرست پیوند صفحه‌خوان مبهم هستند. پیوندهای پانویس دیگری که نشانی وب عنوان را تکرار می‌کنند اضافه نکنید.

ساده‌ترین کارت <article> است که حاوی عنوان و پاراگراف است. پیوند و الگوی کنشی را که با رفتار کارت مطابقت دارد انتخاب کنید؛ مدل‌های تعامل را ببینید.

برای تصاویر یا ویدیوهای کارتی که باید ناحیه‌ای با نسبت ثابت را پر کنند، aspect-ratio و object-fit: cover را روی خود <img> یا <video> تنظیم کنید تا ناحیه را بدون اعوجاج پر کند (ممکن است برش رخ دهد). از aspect-ratio ظرف .media فقط برای محتوای پیشرو دیگر استفاده کنید. درغیراین‌صورت، نسبت ذاتی رسانه را حفظ کنید. برای تصاویر اطلاعاتی، متن جایگزین مناسبی ارائه دهید؛ برای تصاویر تزئینی از alt="" استفاده کنید.

مطابق با فضای دردسترس

چیدمان را براساس فضای دردسترس کارت تنظیم کنید، نه ناحیه نمایش. برای تطبیق دادن فرزندان کارت (رسانه، نوشتار، کنش‌ها)، کارت را به اندازه محفظه (container-type: inline-size) درآورید و قوانین @container را برای فرزندان آن بنویسید. از اندازه‌گذاری از شبکه یا فهرست والد اجتناب کنید: عرض واقعی کارت می‌تواند به تعداد ستون‌ها، فاصله‌ها و غیره بستگی داشته باشد، که باعث می‌شود نقاط شکست مبتنی بر والد نویزدار باشند.

در محفظه باریک، مناطق را به‌ترتیب منبع روی‌هم قرار دهید. در یک ظرف عریض، رسانه را در ستون کناری کنار مناطق دیگر قرار دهید، اما فقط برای کارت‌هایی که رسانه دارند: آن قوانین را با :has() در فرزند رسانه (مثلاً .card:has(> img)) محدود کنید تا تعاریف ستون و جای‌گذاری‌های grid-column هرگز برای کارت بدون رسانه اعمال نشوند. کارت بدون رسانه در هر عرضی تک‌ستونی باقی می‌ماند و نباید ستون رسانه خالی رزرو کند.

تراز کردن کارت‌ها در جدول

وقتی کارت‌های موجود در یک ردیف باید ارتفاع مناطقشان را هم‌رسانی کنند، از subgrid استفاده کنید: هر کارت را طوری تنظیم کنید که چهار ردیف مشترک (رسانه، سرصفحه، محتوا، پاصفحه) را پوشش دهد و مناطق را با انتخابگر عنصر قرار دهید، و هر چیزی را که رسانه، عنوان، یا <footer> نیست به‌عنوان محتوا درنظر بگیرید. کارتی که منطقه‌ای را حذف می‌کند، قطعه آن را خالی می‌گذارد، بنابراین مناطق باقی‌مانده همچنان با کارت‌های مجاور هم‌تراز می‌شوند. هر قطعه یک مورد جدولی را نگه می‌دارد، بنابراین ناحیه محتوا را فقط زمانی در <div> بپیچید که بیش از یک عنصر داشته باشد و کارت‌ها قطعه‌ها را به‌اشتراک بگذارند. کارت‌هایی که با هم‌رده‌ها تراز نیستند به پوشاننده یا زیرشبکه نیاز ندارند.

مدل‌های تعامل

کارت‌های محتوا

از <article> به‌عنوان ریشه کارت استفاده کنید. پیوندها و دکمه‌ها را به‌عنوان کنترل‌های بومی جداگانه نگه دارید.

کارت‌های تک‌مقصدی

وقتی کل کارت یک مقصد است و کنش‌های مستقل ندارد، از یک پیوند بومی استفاده کنید. پیوند می‌تواند <article> را دربرگیرد. پیوندها، دکمه‌ها، یا کنترل‌های فرم دیگر را در پیوند قرار ندهید و هرگونه نوشتار «بیشتر بخوانید» را به‌صورت <p> یا <span> ساده نگه دارید. چون نام قابل‌دسترس پیوند کل نوشتار کارت است، محتوا را کوتاه نگه دارید؛ اگر کارت نوشتار یا کنش‌های دیگری دارد، از الگوی پیوند کشیده زیر استفاده کنید تا فقط عنوان پیوند باشد:

<a href="/recipes/poached-eggs">
  <article class="card">
    <h3>Poached eggs</h3>
    <p>Two poached eggs served on toasted sourdough.</p>
  </article>
</a>

کارت‌های قابل‌کلیک با کنش‌های مستقل

اگر کلیک کردن روی کارت به‌جای پیمایش، کنشی را راه‌اندازی می‌کند، به‌جای پیوند از <button> استفاده کنید.

وقتی کارت محتوا به مقصد اصلی پیوند می‌دهد، حاوی عناصر تعاملی دیگر نیز هست، و باید به‌طور کامل کلیک‌کردنی باشد:

  • از یک موافقت کردن، در خود پیوند اصلی استفاده کنید: .card-link را دقیقاً در یک پیوند برای هر کارت (پیوند عنوان) قرار دهید. پانویس و پیوندهای دیگر هرگز آن را دریافت نمی‌کنند، یا هرکدام هم‌پوشانی خود را گسترش می‌دهند و آخرین مورد کل کارت را ضبط می‌کند.
  • عنوان آن را پیوند دهید و ناحیه ضربه اشاره‌گر را با ::after در سراسر کارت بکشید
.card:has(a.card-link) {
    position: relative;
}

.card a.card-link::after {
    content: "";
    position: absolute;
    inset: 0;
}
  • عناصر تعاملی را با position: relative; z-index: 1 ارتقا دهید تا همچنان قابل‌استفاده باشند. به‌جای اینکه ازطریق کلاس‌ها موافقت کنید، انواع عناصر (مثلاً a, button) را هدف قرار دهید.
  • z-index را برای کل محفظه‌ها اعمال نکنید زیرا باعث می‌شود رویدادهای اشاره‌گر را که هیچ کنشی ایجاد نمی‌کنند ضبط کنند.
.card:has(a.card-link) {
    /* Keep other interactive elements above the overlay */
    a:not(.card-link), button, input, x-button {
        position: relative;
        z-index: 1;
    }
}
  • به‌جای پیوند کشیده‌شده، خود کارت را در حالت نگه داشتن نشانگر/تمرکز سبک‌بندی کنید:
.card {
    a.card-link {
        &:focus-visible {
            outline: none; /* Draw it on the card instead */
        }
    }
    
    &:has(a.card-link:focus-visible) {
        /* Focus ring */
    }

    &:has(a.card-link:hover) {
        /* Hover styles */
    }
}

کارت‌های انتخاب

برای کارت‌هایی که انتخاب‌های ازپیش تعریف‌شده را نشان می‌دهند، از <label class="card"> با چارگوش انتخاب یا دکمه رادیویی به‌عنوان فرزند مستقیم استفاده کنید.

کارت انتخاب‌شده را با :has(:checked) سبک‌بندی کنید. هرگز ویژگی‌های تأثیرگذار بر چیدمان مانند border-width، padding، یا font-weight را در انتخاب تغییر ندهید، زیرا کارت و همسایگان آن جابه‌جا می‌شوند؛ تأکید را با outline، box-shadow، یا حاشیه شفافی که فقط رنگ آن تغییر می‌کند، ترسیم کنید:

.card {
  border: 2px solid transparent;

  &:has(> :checked) {
    border-color: var(--accent);
  }
}

چارگوش انتخاب یا دکمه رادیویی قابل‌مشاهده خودش نشانگر غیررنگی انتخاب است، بنابراین تغییر رنگ به‌تنهایی کافی است. اگر کنترل به‌صورت دیداری پنهان است (آن را قابل‌تمرکز و در درخت دسترس‌پذیری نگه دارید، هرگز display: none)، نشانگر غیررنگی اضافه کنید که بر چیدمان تأثیر نگذارد، مثلاً نماد علامت تیک یا outline ضخیم‌تر.

وقتی گزینه‌ها به انتخابگر کرکره‌ای تعلق دارند که گزینه‌های آن به‌صورت کارت چیده شده‌اند، از <select> بومی با appearance: base-select و عناصر سبک ::picker(select) و <option> استفاده کنید، به‌جای اینکه انتخاب را با کارت‌های <div> جایگزین کنید؛ برای جزئیات بیشتر و گزینه‌های جایگزین، به چیدمان‌های انتخابگر سفارشی مراجعه کنید.