إنشاء بطاقة

نظرة عامة

تجمع البطاقة جزءًا واحدًا من المحتوى ذي الصلة أو خيارًا واحدًا. وهو نمط مرئي، وليس نموذجًا دلاليًا أو تفاعليًا ثابتًا، لذا يجب الحفاظ على معنى المحتوى واستخدام التفاعل الأصلي الذي يتطابق مع الغرض منه.

الإرشادات

اختَر دلالات المحتوى وتفاعله بشكل منفصل:

  • استخدام <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> يتضمّن إجراءات مستقلة كروابط وأزرار مدمجة. قد يشارك رابط "قراءة المزيد" عنوان URL الخاص برابط العنوان، ولكن يجب منحه اسم العنصر الظاهر على واجهة المستخدم وصفيًا يسهل الوصول إليه ويبدأ بالنص المرئي، باستخدام نص مخفي بصريًا (على سبيل المثال، Read more<span> about poached eggs</span>)، لأنّ روابط "قراءة المزيد" المتطابقة تكون غامضة في قائمة روابط قارئ الشاشة. لا تضِف روابط تذييل أخرى تكرّر عنوان URL الخاص بالعنوان الرئيسي.

أبسط بطاقة هي <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> فقط عندما تحتوي على أكثر من عنصر واحد وتتشارك البطاقات المسارات. Cards that are not aligned with siblings need neither wrapper nor subgrid.

نماذج التفاعل

بطاقات المحتوى

استخدِم <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> بدلاً من استبدال عنصر select ببطاقات <div>. راجِع تنسيقات مخصّصة لأداة اختيار القائمة المنسدلة لمزيد من التفاصيل والحلول البديلة.