CSS3 والتصميم المتجاوب

استعلامات الحاوية

25 دقيقة الدرس 37 من 60

ما هي استعلامات الحاوية ولماذا توجد

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

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

قيود استعلامات الوسائط

كانت استعلامات الوسائط حجر الزاوية في تصميم الويب المتجاوب منذ أن نشر إيثان ماركوت المفهوم عام 2010. تعمل من خلال الاستعلام عن خصائص نافذة العرض -- بشكل أساسي عرضها وارتفاعها. عندما تكتب @media (min-width: 768px)، فأنت تسأل المتصفح ما إذا كانت نافذة العرض بعرض 768 بكسل على الأقل، وإذا كان الأمر كذلك، يتم تطبيق مجموعة من الأنماط.

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

ومع ذلك، تقصر استعلامات الوسائط عندما يتعلق الأمر بالاستجابة على مستوى المكون. إليك السبب:

  • المكونات لا تعرف حجمها الخاص: يخبرك استعلام الوسائط بعرض نافذة العرض، لكن مكونا داخل شريط جانبي قد يشغل فقط 300 بكسل من نافذة عرض بعرض 1200 بكسل. لا يملك المكون طريقة لمعرفة عرضه المتاح باستخدام استعلامات الوسائط وحدها.
  • سياق التخطيط يتغير: قد يظهر نفس المكون في منطقة كاملة العرض في صفحة وعمود ضيق في صفحة أخرى. لا يمكن لاستعلامات الوسائط مراعاة ذلك دون تكرار أو تعقيد CSS الخاص بك.
  • قابلية إعادة الاستخدام تتأثر: عندما تكون أنماط المكون مرتبطة بنقاط توقف نافذة العرض، فإن نقل ذلك المكون إلى سياق تخطيط مختلف يتطلب إعادة كتابة أنماطه المتجاوبة.
  • أنظمة التصميم تنهار: في نظام تصميم أو مكتبة مكونات، يجب أن يكون كل مكون مستقلا بذاته. الأنماط المتجاوبة المعتمدة على نافذة العرض تسرب افتراضات التخطيط إلى المكونات.

المشكلة: استعلامات الوسائط لا يمكنها التكيف مع حجم الحاوية

/* هذه البطاقة تستجيب لعرض نافذة العرض، وليس حاويتها */
.card {
    display: flex;
    flex-direction: column;
}

@media (min-width: 768px) {
    .card {
        flex-direction: row;
    }
}

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

تعريف سياق الاحتواء

قبل أن تتمكن من استخدام استعلامات الحاوية، يجب عليك أولا تحديد العناصر التي تعمل كحاويات. يتم ذلك باستخدام خاصية container-type. بشكل افتراضي، لا يوجد عنصر يعتبر حاوية استعلام -- يجب عليك الاشتراك صراحة. وذلك لأن استعلامات الحاوية تتطلب من المتصفح تتبع حجم الحاوية بشكل مستقل عن أبنائها، مما له تأثيرات على الأداء. يحتاج المتصفح لإنشاء سياق احتواء لتجنب التبعيات الدائرية حيث يعتمد نمط الابن على حجم الأب، الذي بدوره يعتمد على حجم الابن.

container-type

تقبل خاصية container-type ثلاث قيم:

  • inline-size -- تنشئ حاوية استعلام لاستعلامات الحجم السطري (العرض في أوضاع الكتابة الأفقية). هذه هي القيمة الأكثر استخداما لأن الغالبية العظمى من قرارات التصميم المتجاوب تعتمد على العرض المتاح. يكتسب العنصر احتواء الحجم السطري، مما يعني أن حجمه السطري يُحدد بشكل مستقل عن أبنائه.
  • size -- تنشئ حاوية استعلام لكل من استعلامات الحجم السطري والحجم الكتلي (العرض والارتفاع). استخدم هذا عندما تحتاج للاستعلام عن كلا البعدين. لاحظ أن هذا يعني أيضا أن ارتفاع العنصر يجب تعيينه صراحة أو تحديده بشيء آخر غير محتواه، لأن احتواء الحجم الكتلي يمنع العنصر من التحجيم بناء على ارتفاع أبنائه.
  • normal -- القيمة الافتراضية. العنصر ليس حاوية استعلام لاستعلامات الحجم، رغم أنه لا يزال يمكن استخدامه مع استعلامات أنماط الحاوية (ميزة CSS مستقبلية).

إعداد حاوية

/* الأكثر شيوعا: الاستعلام بناء على العرض فقط */
.card-wrapper {
    container-type: inline-size;
}

/* الاستعلام بناء على كل من العرض والارتفاع */
.dashboard-panel {
    container-type: size;
    height: 400px; /* مطلوب! احتواء الحجم الكتلي يحتاج ارتفاعا صريحا */
}

/* ليست حاوية (السلوك الافتراضي) */
.regular-div {
    container-type: normal;
}
تحذير: عند استخدام container-type: size، لا يمكن للعنصر استمداد ارتفاعه من محتواه. يجب عليك تعيين ارتفاع صريح أو min-height أو أن يُحدد الارتفاع بواسطة آلية تخطيط خارجية (مثل كونه ابنا لـ flex أو grid مع محاذاة تمدد). بدون ارتفاع صريح، سينهار العنصر إلى ارتفاع صفر لأن احتواء الحجم الكتلي يمنعه من استخدام أبنائه لتحديد ارتفاعه الخاص.

container-name

عندما يكون لديك عدة حاويات متداخلة، قد ترغب في أن يستجيب عنصر ابن لحاوية سلف محددة بدلا من الأقرب. تتيح لك خاصية container-name تعيين اسم واحد أو أكثر لحاوية، يمكنك بعد ذلك الإشارة إليها في قواعد @container الخاصة بك.

تسمية الحاويات

/* سمِّ حاوياتك للاستهداف الدقيق */
.sidebar {
    container-type: inline-size;
    container-name: sidebar;
}

.main-content {
    container-type: inline-size;
    container-name: main;
}

.card-wrapper {
    container-type: inline-size;
    container-name: card;
}

/* أسماء متعددة على حاوية واحدة */
.dashboard-widget {
    container-type: inline-size;
    container-name: widget panel;
    /* يمكن الإشارة لهذه الحاوية بـ "widget" أو "panel" */
}
ملاحظة: أسماء الحاويات ليست مثل أسماء فئات CSS -- لا تستخدم نقاطا أو علامات هاش. إنها معرفات بسيطة. يمكن أن يكون للحاوية عدة أسماء مفصولة بمسافات. يمكن استخدام كل اسم بشكل مستقل في قواعد @container لاستهداف تلك الحاوية المحددة.

الاختصار container

تجمع خاصية الاختصار container بين container-name وcontainer-type في تصريح واحد. الصيغة هي container: <name> / <type>.

استخدام اختصار container

/* اختصار: الاسم / النوع */
.sidebar {
    container: sidebar / inline-size;
}

/* ما يعادله بالتصريحات المطولة */
.sidebar {
    container-name: sidebar;
    container-type: inline-size;
}

/* أسماء متعددة مع الاختصار */
.widget {
    container: widget panel / inline-size;
}

/* النوع فقط (بدون اسم) */
.wrapper {
    container: / inline-size;
    /* أو ببساطة استخدم container-type: inline-size; */
}

كتابة استعلامات الحاوية مع @container

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

صيغة @container الأساسية

/* استعلام أقرب حاوية سلف */
@container (min-width: 400px) {
    .card {
        flex-direction: row;
    }
}

/* استعلام حاوية مسماة محددة */
@container sidebar (max-width: 300px) {
    .nav-link {
        font-size: 0.875rem;
        padding: 4px 8px;
    }
}

/* دمج الشروط */
@container card (min-width: 500px) and (max-width: 800px) {
    .card-title {
        font-size: 1.5rem;
    }
}

/* صيغة نطاق العرض (مشابهة لصيغة نطاق استعلامات الوسائط) */
@container (400px <= width <= 800px) {
    .card {
        grid-template-columns: 1fr 2fr;
    }
}

عندما تكتب @container (min-width: 400px) بدون تحديد اسم، يستهدف الاستعلام أقرب سلف تم تعيين container-type عليه إلى inline-size أو size. عندما تكتب @container sidebar (min-width: 400px)، فإنه يستهدف تحديدا أقرب حاوية سلف مسماة "sidebar"، متخطيا أي حاويات غير مسماة أو حاويات بأسماء مختلفة.

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

وحدات طول استعلامات الحاوية

تقدم استعلامات الحاوية مجموعة جديدة من وحدات الطول النسبية لحجم حاوية الاستعلام. هذه مشابهة لوحدات نافذة العرض (vw، vh) لكنها نسبية للحاوية بدلا من نافذة العرض.

  • cqw -- 1% من عرض حاوية الاستعلام.
  • cqh -- 1% من ارتفاع حاوية الاستعلام.
  • cqi -- 1% من الحجم السطري لحاوية الاستعلام (العرض في أوضاع الكتابة الأفقية).
  • cqb -- 1% من الحجم الكتلي لحاوية الاستعلام (الارتفاع في أوضاع الكتابة الأفقية).
  • cqmin -- القيمة الأصغر بين cqi وcqb.
  • cqmax -- القيمة الأكبر بين cqi وcqb.

استخدام وحدات استعلامات الحاوية

.card-wrapper {
    container: card / inline-size;
}

.card-title {
    /* حجم الخط يتدرج مع عرض الحاوية */
    font-size: clamp(1rem, 4cqi, 2rem);
}

.card-image {
    /* الصورة تأخذ 40% من عرض الحاوية */
    width: 40cqi;
    height: auto;
}

.hero-text {
    /* استخدم cqmin لتدرج متسق بغض النظر عن الاتجاه */
    font-size: 5cqmin;
    padding: 2cqi;
}

/* وحدات الحاوية تعمل في أي خاصية CSS تقبل الأطوال */
.responsive-padding {
    padding: 3cqi 5cqi;
    margin-bottom: 2cqb;
    border-radius: 1cqi;
}
ملاحظة: وحدات استعلامات الحاوية تُحل مقابل أقرب حاوية استعلام سلف. إذا لم يكن للعنصر سلف مع احتواء منشأ، تُحل وحدات استعلامات الحاوية إلى صفر. أيضا، cqh وcqb تتطلب أن يكون للحاوية container-type: size (وليس فقط inline-size) لأن الحاوية يجب أن تتبع حجمها الكتلي أيضا.

بناء مكونات متجاوبة قابلة لإعادة الاستخدام حقا

تظهر القوة الحقيقية لاستعلامات الحاوية عندما تبني مكونات تتكيف بالكامل بناء على حجم حاويتها. دعنا نبني مكون بطاقة متجاوب كامل يعمل بشكل مثالي سواء وُضع في منطقة محتوى عريضة أو شريط جانبي ضيق أو أي شيء بينهما.

مثال: مكون بطاقة متجاوب بالكامل

<style>
    /* الخطوة 1: إنشاء سياق الاحتواء على غلاف البطاقة */
    .card-container {
        container: card / inline-size;
    }

    /* الخطوة 2: الأنماط الأساسية -- الهاتف أولا، تخطيط عمودي */
    .responsive-card {
        display: grid;
        grid-template-columns: 1fr;
        gap: 0;
        border-radius: 12px;
        overflow: hidden;
        box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
        background: white;
    }

    .responsive-card .card-image img {
        width: 100%;
        height: 200px;
        object-fit: cover;
        display: block;
    }

    .responsive-card .card-body {
        padding: 16px;
    }

    .responsive-card .card-title {
        font-size: 1.125rem;
        margin: 0 0 8px 0;
    }

    .responsive-card .card-text {
        font-size: 0.875rem;
        color: #666;
        line-height: 1.5;
    }

    .responsive-card .card-meta {
        display: none;
    }

    /* الخطوة 3: عندما تكون الحاوية بعرض 400px على الأقل، انتقل للتخطيط الأفقي */
    @container card (min-width: 400px) {
        .responsive-card {
            grid-template-columns: 200px 1fr;
        }

        .responsive-card .card-image img {
            height: 100%;
            min-height: 180px;
        }

        .responsive-card .card-body {
            padding: 20px;
            display: flex;
            flex-direction: column;
            justify-content: center;
        }

        .responsive-card .card-title {
            font-size: 1.25rem;
        }
    }

    /* الخطوة 4: عندما تكون الحاوية بعرض 600px على الأقل، أظهر تفاصيل أكثر */
    @container card (min-width: 600px) {
        .responsive-card {
            grid-template-columns: 280px 1fr;
        }

        .responsive-card .card-body {
            padding: 24px;
        }

        .responsive-card .card-title {
            font-size: 1.5rem;
            margin-bottom: 12px;
        }

        .responsive-card .card-text {
            font-size: 1rem;
        }

        .responsive-card .card-meta {
            display: flex;
            gap: 16px;
            margin-top: 16px;
            font-size: 0.875rem;
            color: #999;
        }
    }
</style>

<!-- هذه البطاقة تتكيف مع أي عرض حاوية -->
<div class="card-container">
    <article class="responsive-card">
        <div class="card-image">
            <img src="photo.jpg" alt="صورة المقال">
        </div>
        <div class="card-body">
            <h3 class="card-title">بناء المكونات المتجاوبة</h3>
            <p class="card-text">تسمح استعلامات الحاوية للمكونات
            بالاستجابة لمساحتها المتاحة بدلا من نافذة العرض.</p>
            <div class="card-meta">
                <span>5 دقائق قراءة</span>
                <span>نُشر اليوم</span>
            </div>
        </div>
    </article>
</div>

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

مثال عملي: عنصر واجهة شريط جانبي متكيف

دعنا نبني عنصر واجهة شريط جانبي يكيف تخطيطه بناء على عرض الشريط الجانبي. هذا حالة استخدام مثالية لأن الأشرطة الجانبية غالبا ما تغير عرضها أو تنهار بالكامل على أحجام شاشات مختلفة.

مثال: عنصر واجهة شريط جانبي متكيف

<style>
    .sidebar {
        container: sidebar / inline-size;
        width: 100%;
    }

    .widget {
        background: #f8f9fa;
        border-radius: 8px;
        padding: 3cqi;
    }

    .widget-title {
        font-size: clamp(0.875rem, 3cqi, 1.25rem);
        font-weight: 700;
        margin-bottom: 12px;
        border-bottom: 2px solid #e9ecef;
        padding-bottom: 8px;
    }

    .widget-list {
        list-style: none;
        padding: 0;
        margin: 0;
    }

    .widget-list li {
        padding: 8px 0;
        border-bottom: 1px solid #e9ecef;
        display: flex;
        align-items: center;
        gap: 8px;
    }

    .widget-list .item-icon {
        width: 32px;
        height: 32px;
        border-radius: 50%;
        background: #dee2e6;
        flex-shrink: 0;
    }

    .widget-list .item-details {
        flex: 1;
        min-width: 0;
    }

    .widget-list .item-name {
        font-weight: 600;
        font-size: 0.875rem;
    }

    .widget-list .item-meta {
        font-size: 0.75rem;
        color: #6c757d;
        display: none;
    }

    /* عندما يكون الشريط الجانبي عريضا بما يكفي، أظهر البيانات الوصفية */
    @container sidebar (min-width: 250px) {
        .widget-list .item-meta {
            display: block;
        }
    }

    /* عندما يكون الشريط الجانبي عريضا جدا، انتقل لتخطيط الشبكة */
    @container sidebar (min-width: 400px) {
        .widget-list {
            display: grid;
            grid-template-columns: repeat(2, 1fr);
            gap: 12px;
        }

        .widget-list li {
            flex-direction: column;
            text-align: center;
            padding: 12px;
            border-bottom: none;
            background: white;
            border-radius: 8px;
            box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
        }

        .widget-list .item-icon {
            width: 48px;
            height: 48px;
        }
    }
</style>

<aside class="sidebar">
    <div class="widget">
        <h3 class="widget-title">المؤلفون المشهورون</h3>
        <ul class="widget-list">
            <li>
                <div class="item-icon"></div>
                <div class="item-details">
                    <div class="item-name">جين سميث</div>
                    <div class="item-meta">42 مقالة</div>
                </div>
            </li>
            <li>
                <div class="item-icon"></div>
                <div class="item-details">
                    <div class="item-name">جون دو</div>
                    <div class="item-meta">38 مقالة</div>
                </div>
            </li>
        </ul>
    </div>
</aside>

استعلامات الحاوية مقابل استعلامات الوسائط: متى تستخدم كلا منهما

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

استخدم استعلامات الوسائط عندما:

  • تتخذ قرارات تخطيط على مستوى الصفحة (عدد الأعمدة في الشبكة الرئيسية، نمط التنقل، هيكل الصفحة العام).
  • تحتاج للاستجابة لخصائص نافذة العرض خارج نطاق الحجم، مثل prefers-color-scheme، prefers-reduced-motion، orientation، أو إمكانيات hover.
  • تعيين مقاييس الخطوط العامة أو أنظمة التباعد بناء على حجم الشاشة.
  • تحتاج لاستهداف فئات أجهزة محددة (أنماط الطباعة، أنماط الشاشة).
  • تعمل مع متصفحات قديمة لا تدعم استعلامات الحاوية.

استخدم استعلامات الحاوية عندما:

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

الجمع بين استعلامات الوسائط واستعلامات الحاوية

/* استعلام الوسائط لتخطيط مستوى الصفحة */
@media (min-width: 768px) {
    .page-layout {
        display: grid;
        grid-template-columns: 300px 1fr;
        gap: 24px;
    }
}

@media (min-width: 1200px) {
    .page-layout {
        grid-template-columns: 350px 1fr 300px;
    }
}

/* استعلامات الحاوية لاستجابة مستوى المكون */
.content-area {
    container: content / inline-size;
}

.sidebar {
    container: sidebar / inline-size;
}

/* نفس مكون البطاقة يتكيف مع أي حاوية يوجد فيها */
@container (min-width: 400px) {
    .article-card {
        display: grid;
        grid-template-columns: 150px 1fr;
        gap: 16px;
    }
}

@container (min-width: 600px) {
    .article-card {
        grid-template-columns: 250px 1fr;
    }
    .article-card .card-excerpt {
        display: block;
    }
}

دعم المتصفحات والتحسين التدريجي

تتمتع استعلامات الحاوية بدعم ممتاز في جميع المتصفحات الحديثة. Chrome وEdge وFirefox وSafari جميعها تدعم استعلامات الحاوية من إصداراتها لعام 2023 فصاعدا. ومع ذلك، إذا كنت تحتاج لدعم إصدارات متصفحات أقدم، يجب عليك تنفيذ استعلامات الحاوية كتحسين تدريجي.

يمكن لقاعدة @supports اكتشاف دعم استعلامات الحاوية:

التحسين التدريجي مع @supports

/* أنماط أساسية تعمل في كل مكان */
.card {
    display: flex;
    flex-direction: column;
}

/* استعلام وسائط احتياطي للمتصفحات القديمة */
@media (min-width: 600px) {
    .card {
        flex-direction: row;
    }
}

/* أنماط استعلامات حاوية محسنة للمتصفحات الحديثة */
@supports (container-type: inline-size) {
    .card-wrapper {
        container: card / inline-size;
    }

    /* إعادة تعيين تجاوز استعلام الوسائط */
    .card {
        flex-direction: column;
    }

    /* استخدم استعلامات الحاوية بدلا من ذلك */
    @container card (min-width: 400px) {
        .card {
            flex-direction: row;
        }
    }
}

/* يمكنك أيضا التحقق من دعم @container مباشرة */
@supports (container-name: test) {
    /* ميزات استعلامات الحاوية مدعومة */
}
نصيحة: استراتيجية التحسين التدريجي العملية هي كتابة أنماطك المتجاوبة القائمة على استعلامات الوسائط أولا (تعمل في كل مكان)، ثم وضع تحسينات استعلامات الحاوية فوقها باستخدام @supports. في المتصفحات الحديثة، تتولى استعلامات الحاوية وتوفر استجابة أكثر دقة. في المتصفحات القديمة، لا تزال الاحتياطيات القائمة على استعلامات الوسائط توفر تجربة متجاوبة جيدة.

الحاويات المتداخلة

يمكنك تداخل الحاويات داخل حاويات أخرى. عندما يكون لعنصر ابن استعلام @container بدون اسم، يُحل مقابل أقرب حاوية سلف. عندما يكون له استعلام مسمى، يُحل مقابل أقرب سلف بذلك الاسم المحدد.

العمل مع الحاويات المتداخلة

<style>
    .outer {
        container: outer / inline-size;
        padding: 20px;
        background: #f0f0f0;
    }

    .inner {
        container: inner / inline-size;
        padding: 16px;
        background: #e0e0e0;
    }

    /* يستهدف أقرب حاوية (inner) */
    @container (min-width: 300px) {
        .content {
            font-size: 1.125rem;
        }
    }

    /* يستهدف تحديدا الحاوية الخارجية */
    @container outer (min-width: 600px) {
        .content {
            color: darkblue;
        }
    }

    /* يستهدف تحديدا الحاوية الداخلية */
    @container inner (min-width: 250px) {
        .content {
            font-weight: bold;
        }
    }
</style>

<div class="outer">
    <div class="inner">
        <p class="content">هذا النص يستجيب لكلتا الحاويتين.</p>
    </div>
</div>

الأنماط الشائعة وأفضل الممارسات

مع انتشار استعلامات الحاوية بشكل أوسع، ظهرت عدة أنماط وأفضل ممارسات تساعدك على استخدامها بفعالية.

1. لف المكونات في عناصر حاوية: بدلا من جعل المكون نفسه حاوية (مما قد يسبب مشاكل لأن العنصر لا يمكنه الاستعلام عن حجمه الخاص)، لفه في عنصر حاوية مخصص.

نمط غلاف الحاوية

/* صحيح: فصل الغلاف والمكون */
.card-container {
    container: card / inline-size;
}
.card {
    /* أنماط المكون */
}
@container card (min-width: 400px) {
    .card { /* ... */ }
}

/* خطأ: العنصر يستعلم عن حجمه الخاص */
/* .card {
    container-type: inline-size;
}
@container (min-width: 400px) {
    .card { ... }  -- هذا يستعلم عن الحاوية الأم، وليس .card نفسها
} */

2. استخدم وحدات استعلامات الحاوية للخطوط المتدفقة: وحدات استعلامات الحاوية ممتازة لإنشاء خطوط تتدرج بسلاسة مع حجم الحاوية.

الخطوط المتدفقة مع وحدات الحاوية

.text-wrapper {
    container: text / inline-size;
}

.headline {
    /* حجم خط متدفق بين 1.25rem و3rem بناء على عرض الحاوية */
    font-size: clamp(1.25rem, 5cqi, 3rem);
    line-height: 1.2;
}

.body-text {
    /* حجم خط متدفق بين 0.875rem و1.125rem */
    font-size: clamp(0.875rem, 2cqi, 1.125rem);
    line-height: 1.6;
}

.caption {
    font-size: clamp(0.75rem, 1.5cqi, 0.875rem);
}

3. إنشاء تباعد واعٍ بالحاوية: استخدم وحدات استعلامات الحاوية للحشوة والهوامش التي تتكيف مع عرض الحاوية.

التباعد المتجاوب مع وحدات الحاوية

.section-wrapper {
    container: section / inline-size;
}

.section-content {
    padding: clamp(16px, 4cqi, 48px);
}

.section-content h2 {
    margin-bottom: clamp(12px, 2cqi, 32px);
}

.section-content .grid {
    gap: clamp(8px, 2cqi, 24px);
}

مستقبل التصميم المتجاوب القائم على المكونات

تمثل استعلامات الحاوية تحولا جذريا في كيفية تفكيرنا في التصميم المتجاوب. بدلا من نهج من أعلى لأسفل حيث يملي تخطيط الصفحة سلوك المكون، لدينا الآن نهج من أسفل لأعلى حيث تكون المكونات واعية بذاتها ومتكيفة ذاتيا. هذا يتوافق تماما مع البنية القائمة على المكونات المستخدمة في الأطر الحديثة مثل React وVue وAngular وWeb Components.

بالنظر إلى المستقبل، تتوسع مواصفات CSS في استعلامات الحاوية لتشمل استعلامات الأنماط. ستسمح لك استعلامات الأنماط بالاستعلام عن القيمة المحسوبة للخصائص المخصصة (متغيرات CSS) على الحاوية، مما يمكّن أنماط تنسيق شرطية أكثر قوة. على سبيل المثال، قد تستعلم عما إذا كان للحاوية سمة داكنة أو فاتحة مطبقة وتنسق الأبناء وفقا لذلك، دون الاعتماد على أسماء الفئات أو سمات البيانات.

المستقبل: استعلامات الأنماط (تجريبية)

/* استعلامات الأنماط -- قادمة قريبا للمتصفحات */
.theme-container {
    --theme: dark;
}

/* الاستعلام عن قيمة خاصية مخصصة على الحاوية */
@container style(--theme: dark) {
    .card {
        background: #1a1a2e;
        color: #eee;
    }
}

@container style(--theme: light) {
    .card {
        background: #ffffff;
        color: #333;
    }
}

استعلامات الحاوية، جنبا إلى جنب مع ميزات CSS الحديثة مثل :has() وطبقات التتابع والشبكة الفرعية، تنقل CSS نحو مستقبل حيث تكون المكونات مستقلة بذاتها حقا وقابلة للنقل ومتكيفة. أيام الصراع مع نقاط التوقف القائمة على نافذة العرض لاستجابة مستوى المكون تقترب من نهايتها.

التمرين 1: معرض بطاقات متجاوب

أنشئ معرض بطاقات يستخدم استعلامات الحاوية لتكييف تخطيط كل بطاقة. ابنِ صفحة بمنطقة محتوى رئيسية وشريط جانبي. استخدم CSS Grid أو Flexbox مع استعلامات الوسائط لتخطيط مستوى الصفحة (الشريط الجانبي على اليسار، المحتوى الرئيسي على اليمين، التراكم عموديا على الشاشات الصغيرة). أنشئ مكون بطاقة قابل لإعادة الاستخدام يعرض تخطيطا عموديا (الصورة في الأعلى، المحتوى في الأسفل) عندما تكون حاويته ضيقة، وينتقل إلى تخطيط أفقي (الصورة على اليسار، المحتوى على اليمين) عندما تكون الحاوية بعرض 400 بكسل على الأقل، ويتوسع لإظهار بيانات وصفية إضافية (المؤلف، التاريخ، وقت القراءة) عندما تكون الحاوية بعرض 600 بكسل على الأقل. ضع نفس مكون البطاقة في كل من منطقة المحتوى الرئيسية والشريط الجانبي. تحقق من أن البطاقات تتكيف بشكل مستقل مع حاوياتها المعنية بدلا من نافذة العرض. استخدم وحدات استعلامات الحاوية للتباعد الداخلي وأحجام الخطوط في البطاقة حتى تتدرج بسلاسة. اختبر بتغيير حجم نافذة المتصفح ولاحظ كيف تستجيب البطاقات في حاويات مختلفة بشكل مختلف عند نفس عرض نافذة العرض.

التمرين 2: لوحة تحكم مع عناصر واجهة واعية بالحاوية

ابنِ تخطيط لوحة تحكم بلوحات متعددة قابلة لتغيير الحجم، كل منها يحتوي على عناصر واجهة تتكيف مع حجم لوحتها باستخدام استعلامات الحاوية. أنشئ شبكة لوحة تحكم بأربع لوحات على الأقل. استخدم CSS Grid لتخطيط لوحة التحكم واسمح بتغيير حجم الأعمدة (يمكنك محاكاة أحجام مختلفة بتغيير قيم grid-template-columns أو بوضع اللوحات في أعمدة بعروض مختلفة). داخل كل لوحة، أنشئ عنصر واجهة إحصائيات يعرض كتخطيط مضغوط على سطر واحد عندما تكون اللوحة ضيقة (أقل من 200 بكسل)، ويتوسع لإظهار عنصر نائب للرسم البياني ومؤشر الاتجاه عندما تكون اللوحة بعرض 300 بكسل على الأقل، ويعرض جدول بيانات كامل أسفل الرسم البياني عندما تكون اللوحة بعرض 500 بكسل على الأقل. استخدم حاويات مسماة للوحات واكتب استعلامات حاوية تستهدفها بالاسم. أضف وحدات استعلامات الحاوية للخطوط المتجاوبة داخل عناصر الواجهة. نفذ استراتيجية تحسين تدريجي باستخدام @supports بحيث تظل المتصفحات التي لا تدعم استعلامات الحاوية تعرض تخطيطا معقولا باستخدام احتياطيات استعلامات الوسائط. أضف مثالا واحدا على الأقل للحاويات المتداخلة حيث يكون عنصر واجهة داخل لوحة هو نفسه حاوية لمكونات فرعية.