الوحدة 2 · تخطيط يصمد
الـ Container Queries
20 دقراءة 4 دبيئة تجريب الكود
الدرس في لمحة
اجعل بطاقة الجلسة تغيّر تخطيطها بحسب عرض الخانة التي تجلس فيها، باستخدام container queries للحجم ووحدات الحاوية واستعلامات النمط على الـ custom properties.
- 1أنشئ حاوية ثم استعلم عنها
- 2القاعدتان اللتان يتعثّر بهما الجميع
- 3وحدات الحاوية
- 4استعلامات النمط للأشكال المختلفة (variants)
- 5دورك الآن
لا فيديو هنا، بل الشيء الحقيقي: درس مكتوب وأمثلة قابلة للتشغيل واختبار وتدريب.
تستخدم Waypoint بطاقة الجلسة نفسها في ثلاثة أماكن: شبكة الجدول الرئيسية، وشريط جانبي ضيّق بعنوان «Up next»، وواجهة عريضة بكامل العرض للـ keynote. الـ media query لا تستطيع إلا أن تسأل «ما عرض الشاشة؟»، والشاشة بالعرض نفسه في الحالات الثلاث. فحصلت البطاقة في الشريط الجانبي على التخطيط العريض، مضغوطًا في 280px، إلى أن أضاف أحدهم تجاوزًا .sidebar .session-card، ثم تجاوزًا .hero .session-card، وهكذا.
لا ينبغي أن تهتم البطاقة بمكانها. ينبغي أن تهتم بالمساحة المتاحة لها. والـ container queries (استعلامات الحاوية) تتيح لها أن تسأل عن ذلك بالضبط.
أنشئ حاوية ثم استعلم عنها
خطوتان. الأولى أن تعلن أيّ عنصر هو الحاوية، أي الخانة التي تجلس فيها البطاقة:
.slot {
container: session / inline-size;
}هذا الاختصار يضبط container-name: session وcontainer-type: inline-size. النوع يخبر المتصفّح أنك ستستعلم عن الحجم الأفقي (inline size) لهذا العنصر، أي عرضه في الكتابة الأفقية، لذا يجب أن يستطيع حساب هذا العرض دون النظر إلى المحتوى بداخله.
والثانية أن تكتب تخطيط البطاقة على شكل استعلام عن تلك الحاوية:
.session-card {
display: block;
}
@container session (width >= 400px) {
.session-card {
display: grid;
grid-template-columns: 6rem 1fr;
gap: 1rem;
}
}الآن تتراصّ البطاقة عموديًا في الشريط الجانبي بعرض 280px، وتنتقل إلى عمودين في الشبكة بعرض 640px، دون أن تعرف شيئًا عن أيٍّ منهما. الاسم اختياري؛ و@container (width >= 400px) بلا اسم تستخدم أقرب سلف له نوع حاوية حجم. والأسماء تفيد حين تتداخل الحاويات وتريد تخطّي إحداها.
القاعدتان اللتان يتعثّر بهما الجميع
لا يستطيع العنصر أن يستعلم عن نفسه. الاستعلام يبحث عن حاوية بين الأسلاف، لذا فإن container-type على .session-card مع @container { .session-card { … } } لا تفعل شيئًا للبطاقة نفسها. ضع الحاوية على غلاف.
الاحتواء يغيّر طريقة تحديد حجم الحاوية. احتواء inline-size يعني أن عرض الحاوية لا يمكن أن يعتمد على أبنائها؛ وإلا لاستطاع الاستعلام أن يغيّر المحتوى، فيتغيّر العرض، فيتغيّر الاستعلام، إلى ما لا نهاية.
وحدات الحاوية
داخل الحاوية تحصل على وحدات نسبية إليها: cqi تساوي 1% من الحجم الأفقي للحاوية، وcqb تساوي 1% من حجمها الرأسي (block size)، وcqmin/cqmax الأصغر أو الأكبر بينهما. إنها تجعل الـ component يتدرّج بسلاسة، لا عند نقاط التحوّل فقط:
.session-card h3 {
font-size: clamp(1rem, 0.75rem + 2cqi, 1.5rem);
}في الشريط الجانبي بعرض 280px يبقى العنوان قرب 1rem؛ وفي خانة بعرض 640px يكبر نحو 1.5rem. وإن لم يكن أيّ سلف حاوية حجم، ترجع وحدات الحاوية إلى وحدات الـ viewport الصغيرة، فلا تنكسر أبدًا.
استعلامات النمط للأشكال المختلفة (variants)
الحجم ليس الشيء الوحيد الذي قد تستجيب له البطاقة. بطاقة الـ keynote في الواجهة الرئيسية variant (شكل مختلف)، واستعلامات نمط الحاوية تتيح للعنصر الأب أن يعلن ذلك عبر custom property:
.hero { --variant: featured; }
@container style(--variant: featured) {
.session-card {
border-inline-start: 6px solid #6d28d9;
}
}لا تحتاج إلى container-type هنا: كل عنصر حاوية نمط افتراضيًا، فيفحص الاستعلام قيمة --variant المحسوبة على أقرب سلف. واستعلامات النمط تعمل اليوم مع الـ custom properties فقط؛ أما الاستعلام عن الخصائص العادية مثل style(display: grid) فغير مدعوم في أيّ مكان بعد.
دورك الآن
في التمرين تستخدم البطاقة media query، فتحصل على التخطيط الخاطئ في خانة واحدة على الأقل. حوّل .slot إلى حاوية مسمّاة، وانقل التخطيط إلى container query عند 400px، وأضف استعلام نمط للشكل المميّز. تغيّر الفحوصات عرض الخانة وتضبط --variant عليها لترى استجابة البطاقة. وبهذا يُغلق قسم التخطيط؛ وبعده ستجعل الخطوط والمسافات تتدرّج بمرونة عبر كل أحجام الخانات هذه.
أهم النقاط
container-type: inline-sizeتحوّل العنصر إلى حاوية (container)، و@container (width >= 400px)تنسّق العناصر داخله بحسب عرض ذلك العنصر، لا عرض الـ viewport.- لا يستطيع العنصر أن يستعلم عن نفسه؛ ضع
container-typeعلى غلاف واكتب الاستعلام للعناصر التي بداخله. - احتواء الحجم الأفقي (inline-size containment) يعني أن عرض الحاوية لا يمكن أن يأتي من محتواها، لذا تنهار الحاوية الموضوعة في سياق يتقلّص على محتواه ما لم يعطها شيءٌ ما عرضًا.
- وحدات الحاوية مثل
cqi(1% من الحجم الأفقي للحاوية) تتيح للخطوط والمسافات أن تتدرّج مع الـ component. - استعلامات النمط على الـ custom properties، مثل
@container style(--variant: featured)، دخلت Baseline في مايو 2026؛ أما استعلامات الحجم فضمن Baseline منذ 2023.