Kodax

Container Queries والتخطيطات الذاتية — CSS المتقدم

Container Queries والتخطيطات الذاتية

تعلمت Media Queries في دورة تصميم CSS: تسأل عن حجم الشاشة. لكن البطاقة نفسها قد تظهر في عمود عريض في صفحة، وفي شريط جانبي ضيق في صفحة أخرى — على نفس الشاشة. السؤال الصحيح للمكوّن: "كم المساحة المتاحة لي؟"

Container Queries

.card-wrapper {
    container-type: inline-size;   /* هذا العنصر "حاوية" يمكن الاستعلام عن عرضها */
    container-name: card;          /* اختياري */
}

.card {
    display: grid;
    gap: 12px;
}

@container card (min-width: 420px) {
    .card {
        grid-template-columns: 160px 1fr;   /* صورة بجانب النص عندما تتسع الحاوية */
    }
}
<main class="card-wrapper"><article class="card">...</article></main>
<aside class="card-wrapper"><article class="card">...</article></aside>

نفس البطاقة: أفقية في المحتوى الرئيسي، رأسية في الجانبية — تلقائياً، دون أصناف إضافية.

- container-type: inline-size: الاستعلام عن العرض (الأكثر استخداماً).

- الحاوية لا يمكنها الاستعلام عن نفسها؛ القواعد تنطبق على أبنائها.

- مدعومة في كل المتصفحات الحديثة منذ 2023.

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

cqi = 1% من عرض الحاوية (inline size):

.card h3 { font-size: clamp(1rem, 4cqi, 1.5rem); }   /* العنوان يتناسب مع البطاقة لا الشاشة */

Media أم Container؟

| السؤال | الأداة |

|---|---|

| تخطيط الصفحة العام (عدد الأعمدة، إظهار الجانبية) | Media Query |

| شكل مكوّن قابل لإعادة الاستخدام | Container Query |

| تفضيلات المستخدم (حركة، ألوان، طباعة) | Media Query |

aspect-ratio: نسبة ثابتة

.video-frame { aspect-ratio: 16 / 9; width: 100%; }
.avatar { aspect-ratio: 1; width: 64px; border-radius: 50%; }

كان يتطلب حيلة padding-top: 56.25%؛ الآن سطر واحد.

object-fit: الصورة داخل إطارها

.thumb {
    width: 100%;
    aspect-ratio: 4 / 3;
    object-fit: cover;          /* تملأ الإطار وتُقص الزيادة دون تشويه */
    object-position: center;
}

| القيمة | النتيجة |

|---|---|

| fill | تمدد (تشويه) — الافتراضي |

| contain | تظهر كاملة مع فراغات |

| cover | تملأ وتُقص |

subgrid: محاذاة عبر البطاقات

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

.cards {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: 20px;
}
.cards > .card {
    display: grid;
    grid-row: span 3;
    grid-template-rows: subgrid;   /* صفوف البطاقة تتبع صفوف الشبكة الأم */
}

كل بطاقات الصف الواحد تتشارك ارتفاع الصورة والعنوان والزر.

التخطيطات "الذاتية" (Intrinsic)

الفكرة: دع المحتوى والمساحة يقرران بدل نقاط توقف كثيرة: auto-fit و minmax و clamp و min() و flex-wrap و container queries معاً تقلل media queries إلى الحد الأدنى.

تمرين

اجعل بطاقة المشروع مكوّناً بـ container query: رأسية تحت 420px وأفقية فوقها. ضعها في المحتوى الرئيسي وفي الشريط الجانبي وشاهد الشكلين معاً. أضف للصور aspect-ratio و object-fit: cover.

/* مكوّن بطاقة يتكيف مع حاويته */

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

.card {
    display: grid;
    gap: 12px;
    padding: 16px;
    border: 1px solid #e5e7eb;
    border-radius: 12px;
    background: white;
}

.card img {
    width: 100%;
    aspect-ratio: 4 / 3;
    object-fit: cover;
    border-radius: 8px;
}

.card h3 {
    margin: 0;
    font-size: clamp(1rem, 4cqi, 1.5rem);
}

/* حاوية عريضة: الصورة بجانب النص */
@container card (min-width: 420px) {
    .card {
        grid-template-columns: 160px 1fr;
        align-items: start;
    }
}

/* شبكة تتحاذى فيها أجزاء البطاقات */
.cards {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(240px, 100%), 1fr));
    gap: 20px;
}

.cards > .card {
    grid-row: span 3;
    grid-template-rows: subgrid;
}

/* إطار فيديو بنسبة ثابتة */
.video-frame {
    width: 100%;
    aspect-ratio: 16 / 9;
}
اختبر فهمك