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;
}اختبر فهمك