{"id":"l-css-2-5","courseId":"css-mastery","lang":"ar","kind":"lesson","summary":"اجعل بطاقة الجلسة تغيّر تخطيطها بحسب عرض الخانة التي تجلس فيها، باستخدام container queries للحجم ووحدات الحاوية واستعلامات النمط على الـ custom properties.","html":"<p>تستخدم Waypoint بطاقة الجلسة نفسها في ثلاثة أماكن: شبكة الجدول الرئيسية، وشريط جانبي ضيّق بعنوان «Up next»، وواجهة عريضة بكامل العرض للـ keynote. الـ media query لا تستطيع إلا أن تسأل «ما عرض الشاشة؟»، والشاشة بالعرض نفسه في الحالات الثلاث. فحصلت البطاقة في الشريط الجانبي على التخطيط العريض، مضغوطًا في 280px، إلى أن أضاف أحدهم تجاوزًا <code dir=\"ltr\">.sidebar .session-card</code>، ثم تجاوزًا <code dir=\"ltr\">.hero .session-card</code>، وهكذا.</p>\n<p>لا ينبغي أن تهتم البطاقة بمكانها. ينبغي أن تهتم بالمساحة المتاحة لها. والـ container queries (استعلامات الحاوية) تتيح لها أن تسأل عن ذلك بالضبط.</p>\n<h2 id=\"sec-1\" tabindex=\"-1\">أنشئ حاوية ثم استعلم عنها</h2>\n<p>خطوتان. الأولى أن تعلن أيّ عنصر هو الحاوية، أي الخانة التي تجلس فيها البطاقة:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"css\" data-index=\"0\"><div class=\"code-head\"><span class=\"code-title\">slots.css</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">.slot</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> {</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">  container</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: session / inline-size;</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span></code></pre></div>\n<p>هذا الاختصار يضبط <code dir=\"ltr\">container-name: session</code> و<code dir=\"ltr\">container-type: inline-size</code>. النوع يخبر المتصفّح أنك ستستعلم عن الحجم الأفقي (inline size) لهذا العنصر، أي عرضه في الكتابة الأفقية، لذا يجب أن يستطيع حساب هذا العرض دون النظر إلى المحتوى بداخله.</p>\n<p>والثانية أن تكتب تخطيط البطاقة على شكل استعلام عن تلك الحاوية:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"css\" data-index=\"1\"><div class=\"code-head\"><span class=\"code-title\">session-card.css</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">.session-card</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> {</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">  display</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">block</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">;</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">@container</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> session (width >= 400px) {</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">  .session-card</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> {</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">    display</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">grid</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">;</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">    grid-template-columns</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">6</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">rem</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 1</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">fr</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">;</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">    gap</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">1</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">rem</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">;</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">  }</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span></code></pre></div>\n<p>الآن تتراصّ البطاقة عموديًا في الشريط الجانبي بعرض 280px، وتنتقل إلى عمودين في الشبكة بعرض 640px، دون أن تعرف شيئًا عن أيٍّ منهما. الاسم اختياري؛ و<code dir=\"ltr\">@container (width &gt;= 400px)</code> بلا اسم تستخدم أقرب سلف له نوع حاوية حجم. والأسماء تفيد حين تتداخل الحاويات وتريد تخطّي إحداها.</p>\n<figure class=\"diagram\"><svg class=\"diagram-svg\" focusable=\"false\" viewBox=\"0 0 680 250\" role=\"img\" aria-labelledby=\"l-css-2-5-t1\"><defs><marker id=\"arrow-l-css-2-5-1\" viewBox=\"0 0 10 10\" refX=\"9\" refY=\"5\" markerWidth=\"7\" markerHeight=\"7\" orient=\"auto-start-reverse\"><path d=\"M0 0 L10 5 L0 10 z\" class=\"d-arrowhead\"/></marker></defs>\n  <title id=\"l-css-2-5-t1\">نافذة متصفّح فيها خانة جانبية ضيّقة وخانة رئيسية عريضة. البطاقة في الخانة الضيّقة متراصّة: الوقت فوق العنوان. والبطاقة في الخانة العريضة جنبًا إلى جنب: عمود الوقت بجوار العنوان.</title>\n  <rect class=\"d-box\" x=\"10\" y=\"10\" width=\"660\" height=\"230\" rx=\"12\"/>\n  <text class=\"d-label-muted\" x=\"24\" y=\"34\">الـ viewport: نفسه للاثنتين</text>\n  <rect class=\"d-box-accent d-dashed\" x=\"24\" y=\"50\" width=\"200\" height=\"176\" rx=\"10\"/>\n  <text class=\"d-code\" x=\"36\" y=\"72\">.slot 280px</text>\n  <rect class=\"d-box-primary\" x=\"40\" y=\"86\" width=\"168\" height=\"40\" rx=\"6\"/>\n  <text class=\"d-label\" x=\"52\" y=\"111\">09:30</text>\n  <rect class=\"d-box-primary\" x=\"40\" y=\"134\" width=\"168\" height=\"76\" rx=\"6\"/>\n  <text class=\"d-label\" x=\"52\" y=\"160\">العنوان</text>\n  <rect class=\"d-box-accent d-dashed\" x=\"244\" y=\"50\" width=\"412\" height=\"176\" rx=\"10\"/>\n  <text class=\"d-code\" x=\"256\" y=\"72\">.slot 640px</text>\n  <rect class=\"d-box-primary\" x=\"260\" y=\"86\" width=\"96\" height=\"124\" rx=\"6\"/>\n  <text class=\"d-label\" x=\"272\" y=\"111\">09:30</text>\n  <rect class=\"d-box-primary\" x=\"366\" y=\"86\" width=\"274\" height=\"124\" rx=\"6\"/>\n  <text class=\"d-label\" x=\"378\" y=\"111\">العنوان</text>\n</svg><figcaption>البطاقة نفسها في خانتين: الاستعلام يقيس الخانة لا الـ viewport</figcaption></figure>\n<h2 id=\"sec-2\" tabindex=\"-1\">القاعدتان اللتان يتعثّر بهما الجميع</h2>\n<p><strong>لا يستطيع العنصر أن يستعلم عن نفسه.</strong> الاستعلام يبحث عن حاوية بين <em>الأسلاف</em>، لذا فإن <code dir=\"ltr\">container-type</code> على <code dir=\"ltr\">.session-card</code> مع <code dir=\"ltr\">@container { .session-card { … } }</code> لا تفعل شيئًا للبطاقة نفسها. ضع الحاوية على غلاف.</p>\n<p><strong>الاحتواء يغيّر طريقة تحديد حجم الحاوية.</strong> احتواء <code dir=\"ltr\">inline-size</code> يعني أن عرض الحاوية لا يمكن أن يعتمد على أبنائها؛ وإلا لاستطاع الاستعلام أن يغيّر المحتوى، فيتغيّر العرض، فيتغيّر الاستعلام، إلى ما لا نهاية.</p>\n<aside class=\"callout callout-mistake\" role=\"note\"><p class=\"callout-title\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3\"/><path d=\"M12 9v4\"/><path d=\"M12 17h.01\"/></svg><span><span class=\"callout-kind\">خطأ شائع</span><span class=\"callout-sep\" aria-hidden=\"true\"> · </span>حاوية تنهار إلى الصفر</span></p>\n<p>ضع <code dir=\"ltr\">container-type: inline-size</code> على عنصر يتقلّص على محتواه (عنصر flex بلا حجم، أو inline-block، أو صندوق بـ <code dir=\"ltr\">width: fit-content</code>)، وسينهار، لأن عرضه كان يأتي من محتواه ولم يعد يستطيع. اجعل الحاوية عنصرًا يأتي عرضه من الخارج: عنصر block، أو خلية grid، أو عنصر flex له <code dir=\"ltr\">flex: 1</code>.</p>\n</aside>\n<h2 id=\"sec-3\" tabindex=\"-1\">وحدات الحاوية</h2>\n<p>داخل الحاوية تحصل على وحدات نسبية إليها: <code dir=\"ltr\">cqi</code> تساوي 1% من الحجم الأفقي للحاوية، و<code dir=\"ltr\">cqb</code> تساوي 1% من حجمها الرأسي (block size)، و<code dir=\"ltr\">cqmin</code>/<code dir=\"ltr\">cqmax</code> الأصغر أو الأكبر بينهما. إنها تجعل الـ component يتدرّج بسلاسة، لا عند نقاط التحوّل فقط:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"css\" data-index=\"2\"><div class=\"code-head\"><span class=\"code-title\">CSS</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">.session-card</span><span style=\"color:#116329;--shiki-dark:#7EE787\"> h3</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> {</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">  font-size</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">clamp</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">1</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">rem</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">0.75</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">rem</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> +</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 2</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">cqi</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">1.5</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">rem</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">);</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span></code></pre></div>\n<p>في الشريط الجانبي بعرض 280px يبقى العنوان قرب 1rem؛ وفي خانة بعرض 640px يكبر نحو 1.5rem. وإن لم يكن أيّ سلف حاوية حجم، ترجع وحدات الحاوية إلى وحدات الـ viewport الصغيرة، فلا تنكسر أبدًا.</p>\n<h2 id=\"sec-4\" tabindex=\"-1\">استعلامات النمط للأشكال المختلفة (variants)</h2>\n<p>الحجم ليس الشيء الوحيد الذي قد تستجيب له البطاقة. بطاقة الـ keynote في الواجهة الرئيسية <em>variant</em> (شكل مختلف)، واستعلامات نمط الحاوية تتيح للعنصر الأب أن يعلن ذلك عبر custom property:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"css\" data-index=\"3\"><div class=\"code-head\"><span class=\"code-title\">CSS</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">.hero</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { </span><span style=\"color:#953800;--shiki-dark:#FFA657\">--variant</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: featured; }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">@container</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> style(--variant: featured) {</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">  .session-card</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> {</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">    border-inline-start</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">6</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">px</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> solid</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> #6d28d9</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">;</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">  }</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span></code></pre></div>\n<p>لا تحتاج إلى <code dir=\"ltr\">container-type</code> هنا: كل عنصر حاوية نمط افتراضيًا، فيفحص الاستعلام قيمة <code dir=\"ltr\">--variant</code> المحسوبة على أقرب سلف. واستعلامات النمط تعمل اليوم مع الـ custom properties فقط؛ أما الاستعلام عن الخصائص العادية مثل <code dir=\"ltr\">style(display: grid)</code> فغير مدعوم في أيّ مكان بعد.</p>\n<aside class=\"callout callout-note\" role=\"note\"><p class=\"callout-title\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"M12 16v-4\"/><path d=\"M12 8h.01\"/></svg><span><span class=\"callout-kind\">ملاحظة</span><span class=\"callout-sep\" aria-hidden=\"true\"> · </span>الدعم</span></p>\n<p>استعلامات الحجم (size container queries) ووحدات الحاوية ضمن Baseline منذ فبراير 2023. أما استعلامات النمط على الـ custom properties فأصبحت ضمن Baseline (متاحة حديثًا) في مايو 2026، حين أطلقها Firefox 151 (وChrome منذ 111، وSafari منذ 18). إن كنت تدعم إصدارات أقدم من Firefox، فتعامل مع التنسيق عبر استعلامات النمط على أنه تحسين، وتأكّد من أن البطاقة الافتراضية تبدو مكتملة دونه.</p>\n</aside>\n<h2 id=\"sec-5\" tabindex=\"-1\">دورك الآن</h2>\n<p>في التمرين تستخدم البطاقة media query، فتحصل على التخطيط الخاطئ في خانة واحدة على الأقل. حوّل <code dir=\"ltr\">.slot</code> إلى حاوية مسمّاة، وانقل التخطيط إلى container query عند 400px، وأضف استعلام نمط للشكل المميّز. تغيّر الفحوصات عرض الخانة وتضبط <code dir=\"ltr\">--variant</code> عليها لترى استجابة البطاقة. وبهذا يُغلق قسم التخطيط؛ وبعده ستجعل الخطوط والمسافات تتدرّج بمرونة عبر كل أحجام الخانات هذه.</p>\n","toc":[{"id":"sec-1","text":"أنشئ حاوية ثم استعلم عنها","level":2},{"id":"sec-2","text":"القاعدتان اللتان يتعثّر بهما الجميع","level":2},{"id":"sec-3","text":"وحدات الحاوية","level":2},{"id":"sec-4","text":"استعلامات النمط للأشكال المختلفة (variants)","level":2},{"id":"sec-5","text":"دورك الآن","level":2}],"takeaways":["<code dir=\"ltr\">container-type: inline-size</code> تحوّل العنصر إلى حاوية (container)، و<code dir=\"ltr\">@container (width &gt;= 400px)</code> تنسّق العناصر داخله بحسب عرض ذلك العنصر، لا عرض الـ viewport.","لا يستطيع العنصر أن يستعلم عن نفسه؛ ضع <code dir=\"ltr\">container-type</code> على غلاف واكتب الاستعلام للعناصر التي بداخله.","احتواء الحجم الأفقي (inline-size containment) يعني أن عرض الحاوية لا يمكن أن يأتي من محتواها، لذا تنهار الحاوية الموضوعة في سياق يتقلّص على محتواه ما لم يعطها شيءٌ ما عرضًا.","وحدات الحاوية مثل <code dir=\"ltr\">cqi</code> (1% من الحجم الأفقي للحاوية) تتيح للخطوط والمسافات أن تتدرّج مع الـ component.","استعلامات النمط على الـ custom properties، مثل <code dir=\"ltr\">@container style(--variant: featured)</code>، دخلت Baseline في مايو 2026؛ أما استعلامات الحجم فضمن Baseline منذ 2023."],"further":[{"title":"Container size and style queries (MDN)","url":"https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Containment/Container_size_and_style_queries"},{"title":"@container (MDN)","url":"https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/At-rules/@container"},{"title":"Container queries (web.dev Learn CSS)","url":"https://web.dev/learn/css/container-queries"}],"quiz":[{"q":"<p>لماذا لا تنطبق هذه القاعدة أبدًا؟</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"css\" data-index=\"0\"><div class=\"code-head\"><span class=\"code-title\">CSS</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">.session-card</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">container-type</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: inline-size; }</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">@container</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> (width >= 400px) {</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">  .session-card</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">display</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">grid</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">; }</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span></code></pre></div>\n","options":[{"text":"<code dir=\"ltr\">@container</code> تحتاج إلى اسم حاوية لتعمل.","why":"الأسماء اختيارية. الاستعلام بلا اسم يستخدم أقرب حاوية من الأسلاف."},{"text":"يجب أن يستخدم الاستعلام <code dir=\"ltr\">min-width</code> بدل صيغة المدى.","why":"الـ container queries تدعم صيغة المدى (<code dir=\"ltr\">width &gt;= 400px</code>) في كل متصفّح يدعمها."},{"text":"<code dir=\"ltr\">inline-size</code> لا تعمل إلا على حاويات grid.","why":"أيّ عنصر يمكن أن يكون حاوية حجم، أيًّا كان نوع الـ display فيه."},{"text":"البطاقة تستعلم عن نفسها، لكن الـ container query لا تنسّق إلا العناصر داخل الحاوية.","why":"صحيح. البطاقة تبحث عن حاوية بين أسلافها فلا تجد. ضع <code dir=\"ltr\">container-type</code> على الغلاف (الخانة) ونسّق البطاقة من داخل الاستعلام."}],"answer":3},{"q":"<p>وضعت <code dir=\"ltr\">container-type: inline-size</code> على عنصر flex بلا عرض مضبوط، فانهار إلى عرض صفر. لماذا؟</p>","options":[{"text":"احتواء الحجم الأفقي يمنع عرض العنصر من الاعتماد على محتواه، وعرض عنصر flex يأتي عادةً من محتواه.","why":"صحيح. مع الاحتواء لا يساهم محتوى العنصر بشيء في حجمه؛ أعطه <code dir=\"ltr\">flex: 1</code> أو عرضًا، أو ضع الحاوية على عنصر يحدّد حجمَه أبوه."},{"text":"الـ container queries لا تعمل داخل flexbox.","why":"إنها تعمل في كل مكان؛ المشكلة في كيفية حصول الحاوية نفسها على حجمها."},{"text":"يخفي المتصفّح الحاويات حتى يطابق أحد الاستعلامات.","why":"الحاويات تُرسم بشكل طبيعي سواء طابق أيّ استعلام أم لا."}],"answer":0},{"q":"<p>لعنوان بطاقة <code dir=\"ltr\">font-size: clamp(1rem, 4cqi, 1.5rem)</code>. إلامَ تشير <code dir=\"ltr\">4cqi</code>؟</p>","options":[{"text":"4% من عرض الـ viewport.","why":"هذه <code dir=\"ltr\">4vw</code>. وحدات <code dir=\"ltr\">cqi</code> تُحسب نسبةً إلى أقرب حاوية، لا إلى الـ viewport."},{"text":"4% من الحجم الأفقي لأقرب حاوية حجم.","why":"صحيح. في خانة عرضها 400px تساوي <code dir=\"ltr\">4cqi</code> 16px؛ وفي خانة عرضها 600px تساوي 24px (وتُحدّ عند 1.5rem)."},{"text":"4% من عرض العنوان نفسه.","why":"لا يستطيع العنصر قياس نفسه بهذه الطريقة؛ وحدات الحاوية تنظر دائمًا إلى حاوية من الأسلاف."},{"text":"أربعة أضعاف حجم خط البطاقة.","why":"مضاعفات حجم الخط تُكتب <code dir=\"ltr\">4em</code>؛ و<code dir=\"ltr\">cqi</code> لا علاقة لها بحجم الخط."}],"answer":1},{"q":"<p>أيّ استعلام يطبّق الأنماط حين يضبط العنصر الأب <code dir=\"ltr\">--variant: featured</code>؟</p>","options":[{"text":"<code dir=\"ltr\">@media (--variant: featured)</code>","why":"الـ media queries تختبر الجهاز والـ viewport؛ ولا تستطيع قراءة الـ custom properties."},{"text":"<code dir=\"ltr\">@supports (--variant: featured)</code>","why":"<code dir=\"ltr\">@supports</code> تختبر ما إذا كان المتصفّح يفهم تصريحًا ما، لا القيمة التي يحملها عنصر."},{"text":"<code dir=\"ltr\">@container style(--variant: featured)</code>","why":"صحيح. استعلامات النمط تختبر القيمة المحسوبة لـ custom property على أقرب حاوية، وكل عنصر حاوية نمط افتراضيًا."}],"answer":2}],"exercise":{"kind":"web","mode":"dom","starter":{"html":"<div class=\"slot\">\n  <article class=\"session-card\">\n    <p class=\"time\">09:30</p>\n    <div class=\"body\">\n      <h3>Container Queries in Production</h3>\n      <p>Cards that adapt to the slot they're in, not the screen.</p>\n    </div>\n  </article>\n</div>","css":".slot {\n  width: 500px; /* the checks change this width */\n}\n.session-card {\n  padding: 12px;\n  border: 1px solid #e5e7eb;\n  border-inline-start: 6px solid #cbd5e1;\n  border-radius: 12px;\n}\n.session-card p, .session-card h3 { margin: 0; }\n.time { color: #6b7280; }\n\n@media (width >= 400px) {\n  .session-card {\n    display: grid;\n    grid-template-columns: 6rem 1fr;\n    gap: 1rem;\n  }\n}\n"},"solution":{"html":"<div class=\"slot\">\n  <article class=\"session-card\">\n    <p class=\"time\">09:30</p>\n    <div class=\"body\">\n      <h3>Container Queries in Production</h3>\n      <p>Cards that adapt to the slot they're in, not the screen.</p>\n    </div>\n  </article>\n</div>","css":".slot {\n  width: 500px; /* the checks change this width */\n}\n.session-card {\n  padding: 12px;\n  border: 1px solid #e5e7eb;\n  border-inline-start: 6px solid #cbd5e1;\n  border-radius: 12px;\n}\n.session-card p, .session-card h3 { margin: 0; }\n.time { color: #6b7280; }\n\n.slot {\n  container: session / inline-size;\n}\n\n@container session (width >= 400px) {\n  .session-card {\n    display: grid;\n    grid-template-columns: 6rem 1fr;\n    gap: 1rem;\n  }\n}\n\n@container style(--variant: featured) {\n  .session-card {\n    border-inline-start-color: #6d28d9;\n  }\n}\n"},"checks":[{"id":"named-container","test":"return style('.slot', 'container-type') === 'inline-size' && style('.slot', 'container-name').split(' ').includes('session');"},{"id":"wide-side-by-side","test":"const setW = async (w) => { $('.slot').style.width = w + 'px'; await tick(16); }; const t = () => $('.time').getBoundingClientRect(); const b = () => $('.body').getBoundingClientRect(); const side = () => t().right <= b().left && Math.abs(t().top - b().top) < 1; const stacked = () => b().top >= t().bottom - 0.5; await setW(500); return side();"},{"id":"narrow-stacked","test":"const setW = async (w) => { $('.slot').style.width = w + 'px'; await tick(16); }; const t = () => $('.time').getBoundingClientRect(); const b = () => $('.body').getBoundingClientRect(); const side = () => t().right <= b().left && Math.abs(t().top - b().top) < 1; const stacked = () => b().top >= t().bottom - 0.5; await setW(300); const ok = stacked(); await setW(500); return ok;"},{"id":"threshold","test":"const setW = async (w) => { $('.slot').style.width = w + 'px'; await tick(16); }; const t = () => $('.time').getBoundingClientRect(); const b = () => $('.body').getBoundingClientRect(); const side = () => t().right <= b().left && Math.abs(t().top - b().top) < 1; const stacked = () => b().top >= t().bottom - 0.5; await setW(399); const below = stacked(); await setW(400); const at = side(); await setW(500); return below && at;"},{"id":"featured-variant","test":"const card = $('.session-card'); const before = style(card, 'border-left-color'); $('.slot').style.setProperty('--variant', 'featured'); await tick(16); const after = style(card, 'border-left-color'); $('.slot').style.removeProperty('--variant'); await tick(16); return before === 'rgb(203, 213, 225)' && after === 'rgb(109, 40, 217)';"}],"title":"دع البطاقة تقيس خانتها","prompt":"<p>تنتقل البطاقة إلى عمودين باستخدام <strong>media query</strong>، فتقيس الشاشة بدل خانتها. تضبط الفحوصات عرض <code dir=\"ltr\">.slot</code> بين 300px و500px.</p>\n<ol>\n<li>اجعل <code dir=\"ltr\">.slot</code> حاوية حجم اسمها <code dir=\"ltr\">session</code> تتتبّع حجمها الأفقي (inline size).</li>\n<li>استبدل الـ media query بـ container query: حين تكون حاوية <code dir=\"ltr\">session</code> بعرض <strong>400px أو أكثر</strong>، تصبح البطاقة شبكة من عمودين؛ وتحت ذلك تبقى متراصّة.</li>\n<li>أضف استعلام نمط: حين تكون <code dir=\"ltr\">--variant</code> بقيمة <code dir=\"ltr\">featured</code>، يصبح حدّ البطاقة في جهة البداية (inline-start) بلون <code dir=\"ltr\">#6d28d9</code>.</li>\n</ol>\n","hints":["<code dir=\"ltr\">container: name / type</code> تضبط الاسم والنوع معًا في تصريح واحد.","يمكن نقل قواعد الـ grid كما هي إلى <code dir=\"ltr\">@container session (width &gt;= 400px) { … }</code>.","للشكل المميّز: <code dir=\"ltr\">@container style(--variant: featured) { .session-card { border-inline-start-color: #6d28d9; } }</code>."],"explanation":"<p><code dir=\"ltr\">container: session / inline-size</code> تجعل الخانة حاوية حجم مسمّاة، فتقارن <code dir=\"ltr\">@container session (width &gt;= 400px)</code> عرض <em>الخانة</em> بـ 400px أيًّا كان الـ viewport. ولا يمكن أن تكون البطاقة نفسها هي الحاوية، لأن الاستعلام لا ينسّق إلا العناصر داخل الحاوية التي يقيسها. واستعلام النمط لا يحتاج إلى نوع حاوية: كل عنصر حاوية نمط، والبطاقة تلتقط قيمة <code dir=\"ltr\">--variant</code> من خانتها الأب. وفي المتصفّحات التي لا تدعم استعلامات النمط، تحتفظ البطاقة ببساطة بحدّها الرمادي الافتراضي.</p>\n","checkLabels":{"named-container":"الخانة حاوية inline-size اسمها session","wide-side-by-side":"عند 500px يقع الوقت بجوار المحتوى","narrow-stacked":"عند 300px تتراصّ البطاقة","threshold":"يحدث التبديل عند 400px بالضبط","featured-variant":"–variant: featured تجعل الحدّ بنفسجيًا"}},"words":613,"readMinutes":4}