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

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

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

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

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

  • Chrome: 131
  • Edge: غير متوافق
  • 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 في ورقة أنماط UA، ولكن كان في السابق 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 لكي تعمل.

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

عرض توضيحي

جارٍ التسجيل

تسجيل 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 الزائف على الرسوم المتحركة.