لسنوات طويلة احتجنا جافاسكريبت (أو مكتبات كاملة) لبناء نافذة منبثقة أو قسم قابل للطي. اليوم HTML نفسه يوفّر عناصر جاهزة تفعل ذلك — بإمكانية وصول مدمجة، وبأقل قدر من الكود.
<dialog>: نافذة منبثقة أصلية
<button id="open">افتح النافذة</button>
<dialog id="confirm">
<p>هل تريد حذف هذا العنصر؟</p>
<button id="close">إغلاق</button>
</dialog>
<script>
const dialog = document.getElementById('confirm');
document.getElementById('open').onclick = () => dialog.showModal();
document.getElementById('close').onclick = () => dialog.close();
</script>
dialog.showModal()يفتح النافذة كمودال حقيقي: يعتّم الخلفية تلقائيًا (طبقة::backdrop)، يحبس التركيز (Focus Trap) داخل النافذة فلا يهربTabخارجها، ويغلقها مفتاحEscapeتلقائيًا — كل هذا بلا أي كود إضافي منك.dialog.show()(بدونModal) يفتحها كنافذة غير حابسة للتركيز — مناسبة لتنبيه غير مُلحّ لا يمنع التفاعل مع باقي الصفحة.dialog.close()يغلقها، ويمكن أيضًا استخدام<form method="dialog">بداخلها ليُغلقها زر الإرسال تلقائيًا دون جافاسكريبت إطلاقًا.
🔑 قبل
<dialog>، بناء "مودال" يدويًا يعني إعادة اختراع حبس التركيز والإغلاق بـ Escape والتعتيم — أخطاء وصول شائعة جدًا حين تُبنى يدويًا.<dialog>يمنحك الثلاثة مجانًا.
<details> و<summary>: طي وكشف بلا جافاسكريبت
<details>
<summary>ما الفرق بين HTML وCSS؟</summary>
<p>HTML يبني الهيكل والمحتوى، وCSS يتحكّم بالشكل والتصميم.</p>
</details>
<details open>
<summary>هذا القسم مفتوح افتراضيًا</summary>
<p>خاصية <code>open</code> البوليّة تجعله مفتوحًا عند تحميل الصفحة.</p>
</details>
<summary>هو العنوان الظاهر دائمًا والقابل للنقر — الوسم الأول داخل<details>تحديدًا، والباقي هو المحتوى المخفي/الظاهر.- المتصفح يضيف سهم توسيع تلقائيًا، ويستجيب لـ
Enter/Spaceمن لوحة المفاتيح تلقائيًا — عنصر تفاعلي كامل بلا سطر جافاسكريبت. - استخدام واقعي شائع جدًا: قسم "الأسئلة الشائعة" (FAQ) بالكامل — كل سؤال
<details>، وكل جواب محتواه.
<h2>الأسئلة الشائعة</h2>
<details>
<summary>هل الدورة مجانية؟</summary>
<p>نعم، كل محتوى The Code Fix مجاني بالكامل.</p>
</details>
<details>
<summary>هل أحتاج خبرة سابقة؟</summary>
<p>لا، تبدأ من الصفر تمامًا.</p>
</details>
خاصية popover: طبقة عائمة عامة
<button popovertarget="tip">اعرض تلميحًا</button>
<div id="tip" popover>
هذا محتوى يظهر فوق باقي الصفحة، ويُغلق تلقائيًا عند الضغط خارجه.
</div>
popoverسمة بوليّة تجعل أي عنصر طبقة عائمة فوق بقية الصفحة (تُعرض في طبقة العرض العلوية Top Layer نفسها التي يستخدمهاdialog) — تُغلق تلقائيًا بالضغط خارجها أو بمفتاحEscape، دون أي جافاسكريبت.popovertargetعلى الزر يربطه بمعرّف العنصر الذي يفتحه/يُغلقه — تبديل تلقائي (toggle) بلاonclickمكتوب يدويًا.- هذه إضافة حديثة نسبيًا لمعيار HTML — تحقّق من دعم المتصفحات على caniuse قبل الاعتماد عليها كخيار وحيد بمشروع يستهدف متصفحات أقدم، ووفّر بديلًا (مثل
dialogأو تنفيذ يدوي) عند الحاجة لدعم أوسع.
متى تختار أيًّا منها؟
| الحاجة | العنصر المناسب |
|---|---|
| نافذة تتطلّب قرارًا قبل متابعة أي شيء آخر (تأكيد حذف) | <dialog> مع showModal() |
| تنبيه غير مُلحّ لا يمنع باقي التفاعل | <dialog> مع show()، أو popover |
| قسم أسئلة شائعة أو محتوى طويل قابل للطي ضمن سياق الصفحة | <details>/<summary> |
| تلميح صغير أو قائمة منسدلة عائمة بسيطة | popover |
<details> كأكورديون حصري: السمة name
عدّة عناصر <details> تشترك بنفس قيمة name تُصبح مجموعة حصرية: فتح واحد منها يُغلق البقية تلقائيًا — أكورديون كامل بلا أي جافاسكريبت:
<details name="faq"><summary>سؤال 1</summary><p>جواب 1</p></details>
<details name="faq"><summary>سؤال 2</summary><p>جواب 2</p></details>
إعادة التركيز بعد إغلاق dialog
نقطة وصول يُنسى غالبًا: بعد إغلاق <dialog> (بـ close() أو زر <form method="dialog">)، يجب أن يعود التركيز إلى العنصر الذي فتحها أصلًا (الزر الذي استدعى showModal()) — لا أن يضيع في أعلى الصفحة. المتصفحات الحديثة تفعل هذا تلقائيًا في أغلب الحالات، لكن تحقّق منه فعليًا بلوحة المفاتيح: افتح النافذة بـ Tab+Enter، أغلقها، وتأكد أن Tab التالي يكمل من نفس الزر لا من بداية الصفحة.
الاستخدام الواقعي
- تأكيد حذف عنصر في لوحة تحكّم:
<dialog>معshowModal(). - قسم "الأسئلة الشائعة" في صفحة تسويقية: سلسلة
<details>. - قائمة إشعارات صغيرة تظهر عند الضغط على أيقونة الجرس:
popover.
الأخطاء الشائعة
- ❌ فتح
<dialog>بتعديل CSS (display: block) بدلshowModal()/show()— يفقد حبس التركيز والتعتيم التلقائي وإغلاق Escape، فتضطر لإعادة بنائها يدويًا رغم أنdialogوُجد أصلًا لتوفير ذلك. - ❌ نسيان أن
<summary>يجب أن يكون أول عنصر داخل<details>— ترتيب خاطئ يكسر السلوك المتوقع. - ❌ الاعتماد على
popoverدون فحص الدعم لمشروع يحتاج توافقًا واسعًا مع متصفحات أقدم. - ❌ استخدام
<dialog>لمحتوى ليس نافذة فعليًا (كقسم عادي بالصفحة) — يفرض عليك تعاملًا خاصًا (فتح/إغلاق برمجي) لا داعي له.
خلاصة
<dialog> يمنحك نافذة منبثقة كاملة (حبس تركيز، تعتيم، إغلاق Escape) بسطرين جافاسكريبت فقط لفتحها وإغلاقها. <details>/<summary> يمنحانك طيًّا وكشفًا بلا أي جافاسكريبت إطلاقًا. وpopover يعمّم فكرة الطبقة العائمة على أي عنصر. ثلاثتها يوفّرون تفاعلًا حقيقيًا كان يحتاج مكتبات خارجية سابقًا — راجع مرجعي dialog وdetails للتفاصيل الكاملة.