مزيد من خيارات التصميم <details>

تاريخ النشر: 6 تشرين الثاني (نوفمبر) 2024

اعتبارًا من الإصدار 131 من Chrome، تتوفّر لك خيارات إضافية لتنسيق بنية عنصرَي <details> و<summary>. يمكنك الآن استخدام هذه العناصر عند إنشاء التطبيقات المصغّرة لبيان الإفصاح أو التطبيقات المصغّرة للقوائم المنسدلة.

على وجه الخصوص، تتيح التغييرات التي تم إدخالها في الإصدار 131 من Chrome استخدام السمة display على هذه العناصر، وإضافة عنصر زائف ::details-content لتصميم الجزء الذي يتم توسيعه وتصغيره.

توافق المتصفّح

  • Chrome: 131
  • الحافة: 131
  • Firefox: غير متوافق
  • Safari: غير متوافق

ضبط display في عنصر <details>

في السابق، لم يكن من الممكن تغيير نوع عرض عنصر <details>. وقد تمّ الآن تخفيف هذا القيد، ما يتيح لك مثلاً استخدام تنسيقات الشبكة أو التنسيقات المرنة في عنصر <details>.

في المثال التالي، يتألف البيان الأوتوماتيكي الحصري من عدة عناصر <details> موضوعة جنبًا إلى جنب. عند توسيع أحد عناصر <details>، يتم وضع محتواه بجانب <summary>.

عرض توضيحي

جارٍ التسجيل

تسجيل https://codepen.io/web-dot-dev/pen/VwoBQjY في Chrome 131

ويتم تحقيق ذلك باستخدام تنسيق مرن على عنصر <details>، باستخدام ملف CSS التالي:

details {
  display: flex;
  flex-direction: row;
}

يُسمح أيضًا بقيم العرض الأخرى، مثل grid.

ملاحظة حول استخدام display: inline

قيمة display التي يمكن أن تؤدي إلى نتيجة غير متوقّعة هي inline. ليس بسبب عدم عملها، ولكن بسبب قيود محلل HTML.

عند وضع عنصر <details> داخل فقرة، يجبر ذلك منظِّم HTML على إغلاق الفقرة المفتوحة أولاً، كما هو موضّح في الفقرة 13.2.6.4.7 من معيار HTML:

علامة بداية اسم علامتها هو أحد الأسماء التالية: "address" أو "article" أو "aside" أو "blockquote" أو "center" أو "details" أو "dialog" أو "dir" أو "div" أو "dl" أو "fieldset" أو "figcaption" أو "figure" أو "footer" أو "header" أو "hgroup" أو "main" أو "menu" أو "nav" أو "ol" أو "p" أو "search" أو "section" أو "summary" أو "ul"

إذا كانت حزمة العناصر المفتوحة تحتوي على عنصر p في نطاق الزر، أغلِق عنصر p. أدخِل عنصر HTML للرمز المميّز.

ونتيجةً لذلك، يتدفق <details> في اتجاه الحظر، بغض النظر عمّا إذا كنت قد ضبطت display: inline.

على سبيل المثال، الترميز التالي

<p>Hello <details>…</details> world</p>

يصبح هذا بعد التحليل:

<p>Hello </p><details>…</details> world<p></p>

يمكنك الاطّلاع على ذلك بنفسك في هذا العرض التجريبي من خلال فحص الترميز الذي تم تحليله باستخدام أدوات مطوّري البرامج في Chrome.

يُرجى العِلم أنّ ذلك لا ينطبق إلا على تداخل <details> داخل <p>. يمكنك استخدام display: inline في <details> داخل <div>.

العنصر المستعار ::details-content

في المتصفّحات، يتم تنفيذ عنصر <details> باستخدام Shadow DOM. يحتوي على عنصر <slot> واحد للملخّص (مع عنصر ملخّص تلقائي) وعنصر <slot> لكل المحتوى المتبقّي، أي كل العناصر الفرعية لعنصر <details> باستثناء عنصر <summary>.

<details>
  ↳ #shadow-root (user-agent)
      <slot id="details-summary">
        <summary>Details</summary>
        <!-- The summary goes here -->
      </slot>
      <slot id="details-content">
        <!-- All content goes here -->
      </slot>
</details>

بالإضافة إلى استخدام المزيد من أنواع العرض في <details>، يمكن الآن استهداف خانة المحتوى باستخدام العنصر النائب ::details-content. يمكنك استخدام هذا العنصر الوهمي لتصميم الحاوية التي تلتف حول محتوى العنصر <details>.

details::details-content {
  border: 5px dashed hotpink;
}

لتطبيق النمط المحدّد فقط عندما يكون عنصر <details> في الحالة المفتوحة، أضِف محدِّد [open] قبله.

[open]::details-content {
  border: 5px dashed hotpink;
}

يُنصح بعدم تطبيق التنسيق على العنصر النائب ::details-content إلا عندما يكون العنصر <details> في الحالة [open].

عرض توضيحي

جارٍ التسجيل

تسجيل https://codepen.io/web-dot-dev/pen/oNKMEYv في Chrome 131

تم ضبط نوع display من ::details-content على block في جدول التنسيق في Universal Analytics، في حين كان display: contents في السابق. قد يضرّك هذا التغيير في بعض الحالات، مثل المحتوى الذي تم الإفصاح عنه ويعتمد على height: 100%. إذا كان ذلك يُسبِّب مشكلة لك، يمكنك حلّها من خلال ضبط نوع display على contents مرة أخرى، على النحو التالي: details[open]::details-content { display: contents; }.

إضافة حركة إلى العنصر المستعار ::details-content

يمكنك إضافة حركة إلى محتوى العنصر <details> أثناء توسيع العنصر. في المثال التالي، يتم عرض العرض بشكل متحرك من 0px إلى 300px.

::details-content {
  transition: width 0.5s ease, content-visibility 0.5s ease allow-discrete;
  width: 0;
}

[open]::details-content {
  width: 300px;
}

بالإضافة إلى نقل السمة width، يجب أيضًا نقل السمة content-visibility. ويعود السبب في ذلك إلى أنّ قيمته تتغيّر بين الحالة غير المفتوحة والحالة المفتوحة، كما هو محدّد في جدول تنسيق User-Agent. ولأنّ هذه السمة هي سمة يمكن إضافة مؤثرات متحركة إليها بشكل منفصل، ستحتاج إلى الكلمة الرئيسية allow-discrete لكي تعمل.

بالإضافة إلى العرض الحصري لأزرار Accordion الذي تمت مشاركته سابقًا، تظهر النتيجة على النحو التالي:

عرض توضيحي

جارٍ التسجيل

تسجيل https://codepen.io/web-dot-dev/pen/XWvBZNo في Chrome 131

يمكن أيضًا أن يكون الرمز height متحركًا. لإضافة تأثير متحرك إلى height: auto، عليك استخدام interpolate-size أو calc-size(). بالإضافة إلى ذلك، لمنع خروج المحتوى من العنصر النائب ::details-content، يمكنك تطبيق overflow: clip عليه.

::details-content {
    transition: height 0.5s ease, content-visibility 0.5s ease allow-discrete;
    height: 0;
    overflow: clip;
}

/* Browser supports interpolate-size */
@supports (interpolate-size: allow-keywords) {
    :root {
        interpolate-size: allow-keywords;
    }

    [open]::details-content {
        height: auto;
    }
}

/* Fallback for browsers with no interpolate-size support */
@supports not (interpolate-size: allow-keywords) {
    [open]::details-content {
        height: 150px;
        overflow-y: scroll; /* In case the contents should be taller than 150px */
    }
}

يمكنك الاطّلاع على الرمز البرمجي في العمل في العرض التجريبي التالي المستوحى من ميزة "الأكورديون" في Material UI. يتم عرض محتوى كل عنصر من عناصر <details> بشكل متحرك بشكل جميل.

عرض توضيحي

جارٍ التسجيل

تسجيل https://codepen.io/web-dot-dev/pen/ExqpQZM في Chrome 131

في المتصفّحات التي لا تتوافق مع ::details-content، سيظلّ المكوّن يعمل بشكل جيد. إنّ الصورة المتحركة هي العنصر الوحيد الذي لا يظهر للزوّار.

رصد الميزات

لعرض إمكانية رصد العنصر النائب ::details-content في CSS، استخدِم المقتطف التالي.

@supports selector(::details-content) {
  
}

يمكنك أيضًا استخدام عملية رصد هذه القيمة كفحص دقيق لمعرفة ما إذا كان المتصفّح الذي يستخدمه الزائر يتوافق مع قيم العرض الإضافية أم لا.

اعتبارات تسهيل الاستخدام

إنّ إدخال العنصر النائب ::details-content وإمكانية تغيير نوع العرض لا يؤثران في إمكانية وصول المستخدمين إلى العنصر <details>.

كما في السابق، في المتصفّحات المستندة إلى Chromium على الأقل ووفقًا لمعيار HTML، يكون عنصر <details> قابلاً للبحث عنه ويتم توسيعه تلقائيًا عندما يحاول المتصفّح الانتقال إلى محتوياته المخفية استجابةً لطلبات البحث في الصفحة وScrollToTextFragment والتنقّل في أجزاء العناصر. ولن يتغيّر هذا الإجراء.

ومع ذلك، قبل استخدام الجداول التوافقية الحصرية، ننصحك بالتفكير في ما إذا كانت مفيدة للمستخدمين أو ضارة بهم. على الرغم من أنّ استخدام نموذج أكورديون حصري يقلل من المساحة المرئية التي يشغلها المحتوى، قد يحتاج المستخدمون إلى فتح العديد من العناصر للاطّلاع على جميع المعلومات. وقد يتسبب ذلك في انزعاج المستخدمين الذين يريدون الاطّلاع على عناصر متعدّدة في الوقت نفسه.

ماذا عن تصميم العلامة؟

لا يمكن حاليًا تنسيق علامة القائمة بشكل متوافق لأنّ هناك طريقتَين مختلفتَين، إحداهما متّبعة في Gecko وChromium (الحالي)، والأخرى متّبعة في WebKit (التي تمت مشاركتها سابقًا مع Chromium).

بعد أن تصبح الميزة قابلة للتشغيل التفاعلي، نهدف إلى منحك مزيدًا من التحكّم في كيفية تصميم العلامة.

المزيد من العروض التوضيحية

في الختام، إليك بعض العروض التوضيحية الإضافية التي يمكنك الاطّلاع عليها. وجميعها تستخدم ::details-content.

UIKit Accordion

عرض توضيحي

جارٍ التسجيل

تسجيل https://codepen.io/web-dot-dev/pen/rNXrJyQ في Chrome 131

تم إنشاء هذا العرض الترويجي بعد Accordion في UIKit. إنّ الرمز هو نفسه تقريبًا رمز ملف الأركان المنسدلة في واجهة مستخدم Material UI الذي تمت مشاركته من قبل.

التطبيق المصغّر لبيان الإفصاح المفتوح جزئيًا

عرض توضيحي

جارٍ التسجيل

تسجيل https://codepen.io/web-dot-dev/pen/PoMBQmW في Chrome 131

يعرض هذا العرض الترويجي تطبيقًا مصغّرًا للإفصاح مفتوحًا جزئيًا يظهر محتواه على الشاشة. لتحقيق ذلك، يتم ضبط content-visibility دائمًا على visible. يتمّ تحريك height باستخدام calc-size() لأنّه يتمّ إجراء عملية حسابية.

::details-content {
  content-visibility: visible; /* Make it always visible */
    
  transition: height 0.5s ease;
  height: 150px;
  overflow: clip;
}

[open]::details-content {
  height: calc-size(auto, size + 0.5rem); /* calc-size because we need to add a length */
}

لتسهيل التصميم، يتم لف المحتوى في div ملفوف. يحصل div الملفوف على أنماط التنسيق، مثل padding، ويتم تطبيق ::details-content الزائف على الرسوم المتحركة.