كتب "كريس كويير" مؤخرًا مشاركة مدونة طرحت السؤال التالي:
والآن بعد أن أصبحت طلبات البحث في الحاوية متاحة في جميع محركات المتصفحات، فلماذا لا يستخدمها المزيد من مطوّري البرامج؟
تسرد مشاركة "كريس" عددًا من الأسباب المحتملة (على سبيل المثال، قلة الوعي والعادات القديمة تمر بصعوبة)، ولكن هناك سبب خاص بارز.
يقول بعض مطوّري البرامج إنهم يريدون استخدام طلبات بحث الحاويات الآن لكنهم يعتقدون أنّ ذلك لن يُتاح لأنّه ما زال عليهم دعم المتصفحات القديمة.
كما خمنت في العنوان، نعتقد أنه من الممكن لمعظم المطورين استخدام الاستعلامات المخصصة للحاويات الآن - في الإنتاج - حتى إذا كان ينبغي لك التوافق مع المتصفحات القديمة. وستساعدك هذه المشاركة على اتّباع النهج الذي ننصح به.
نهج عملي
إذا كنت تريد استخدام طلبات بحث الحاويات في الرمز الخاص بك الآن، ولكنّك تريد أن تبدو التجربة متشابهة في جميع المتصفّحات، يمكنك تنفيذ إجراء احتياطي مستنِد إلى JavaScript للمتصفّحات التي لا تتيح طلبات بحث الحاويات.
بعد ذلك يصبح السؤال: ما مدى شمولية الإجراء الاحتياطي؟
كما هو الحال مع أي إجراء احتياطي، يكمن التحدي في تحقيق توازن جيد بين الفائدة والأداء. بالنسبة إلى ميزات CSS، يكون من المستحيل غالبًا إتاحة واجهة برمجة التطبيقات الكاملة (راجِع سبب عدم استخدام رمز polyfill). ومع ذلك، يمكنك تحقيق تقدم كبير من خلال تحديد المجموعة الأساسية من الوظائف التي يرغب معظم المطورين في استخدامها، ثم تحسين الإجراء الاحتياطي لهذه الميزات فقط.
ولكن ما "المجموعة الأساسية للوظائف"؟ التي يريدها معظم المطورين لطلبات البحث في الحاويات؟ للإجابة عن هذا السؤال، فكِّر في الطريقة التي ينشئ بها معظم المطوّرين حاليًا مواقع إلكترونية سريعة الاستجابة باستخدام الاستعلامات عن الوسائط.
وقد وحَّدت جميع أنظمة التصميم الحديثة ومكتبات المكوّنات تقريبًا مبادئ تعطي أولوية للأجهزة الجوّالة، ويتم تنفيذها باستخدام مجموعة من نقاط الإيقاف المحدَّدة مسبقًا (مثل SM
وMD
وLG
وXL
). تم تحسين المكونات للعرض جيدًا على الشاشات الصغيرة افتراضيًا، ثم يتم وضع الأنماط بطبقات شرطية لدعم مجموعة ثابتة من عرض الشاشة الأكبر. (يُرجى الاطّلاع على مستندات التمهيد وTailwind للحصول على أمثلة عن ذلك.)
هذا النهج تمامًا كما هو الحال مع أنظمة التصميم المستندة إلى الحاويات كما هو الحال مع أنظمة التصميم المستندة إلى إطار العرض، لأنه في معظم الحالات، ما يهم المصممين ليس حجم الشاشة أو إطار العرض، بل مقدار المساحة المتاحة للمكون في سياق تم وضعه فيه. بمعنى آخر، بدلاً من أن تكون نقاط التوقف نسبية إلى إطار العرض بالكامل (وتنطبق على الصفحة بأكملها)، ستسري نقاط التوقف على مناطق محتوى محددة، مثل الأشرطة الجانبية أو مربعات الحوار المشروطة أو نصوص المشاركات.
إذا كان بإمكانك العمل ضمن قيود هذا الأسلوب القائم على نقاط الإيقاف والذي يعتمد على الأجهزة الجوّالة أولاً (وهو ما يفعله معظم المطوِّرين حاليًا)، سيكون تنفيذ إجراء احتياطي مستند إلى الحاوية لهذا الأسلوب أسهل بكثير من تنفيذ الدعم الكامل لكل ميزة من ميزات طلبات البحث في الحاوية.
يوضح القسم التالي كيفية تنفيذ كل هذه الإجراءات بالضبط، بالإضافة إلى دليل مفصَّل يعرض كيفية تنفيذ هذه الخطوات على موقع حالي.
آلية العمل
الخطوة 1: تعديل أنماط المكوّنات لاستخدام قواعد @container
بدلاً من قواعد @media
في هذه الخطوة الأولى، حدد أي مكونات على موقعك تعتقد أنها ستستفيد من التحجيم المستند إلى الحاوية بدلاً من الحجم المستند إلى إطار العرض.
من الجيد أن تبدأ بمكون واحد أو مكونين فقط لمعرفة كيفية عمل هذه الإستراتيجية، ولكن إذا كنت تريد تحويل 100% من مكوناتك إلى تصميم مستند إلى الحاوية، فلا بأس أيضًا! يكمن الشيء العظيم في هذه الإستراتيجية في أنه يمكنك اعتمادها بشكل تدريجي إذا لزم الأمر.
بعد تحديد المكوّنات التي تريد تعديلها، ستحتاج إلى تغيير كل قاعدة "@media
" في تلك المكوّنات. CSS إلى قاعدة @container
.
في ما يلي مثال على الشكل الذي قد يظهر به ذلك في مكوّن .photo-gallery
يكون في شكل عمود واحد تلقائيًا، ثم يستخدم قواعد @media
لتعديل تنسيقه ليصبح عمودين وثلاثة أعمدة في نقطتَي الإيقاف MD وXL (على التوالي):
.photo-gallery {
display: grid;
grid-template-columns: 1fr;
}
/* Styles for the `MD` breakpoint */
@media (min-width: 800px) {
.photo-gallery {
grid-template-columns: 1fr 1fr;
}
}
/* Styles for the `XL` breakpoint */
@media (min-width: 1200px) {
.photo-gallery {
grid-template-columns: 1fr 1fr 1fr;
}
}
لتعديل المكوِّن .photo-gallery
من أجل استخدام قواعد @container
، استبدِل أولاً السلسلة @media
بالسلسلة @container
في CSS. تتشابه القواعد النحوية لهاتين القاعدتين بدرجة كافية بحيث، في كثير من الحالات، قد يكون هذا هو كل ما تحتاج إلى تغييره.
استنادًا إلى تصميم موقعك الإلكتروني، قد تحتاج أيضًا إلى تعديل شرط الحجم، خاصةً إذا كانت قواعد @media
على موقعك الإلكتروني تضع افتراضات معيّنة حول مقدار المساحة التي ستتوفر لمكونات معيّنة بأحجام مختلفة لإطار العرض.
على سبيل المثال، إذا كانت أنماط CSS .photo-gallery
في MD
وXL
في المثال السابق تفترض أنه سيتم عرض شريط جانبي يبلغ عرضه 200 بكسل عند نقاط التوقف هذه، يجب أن تكون شروط الحجم لقواعد @container
أقل بمقدار 200 بكسل تقريبًا، على افتراض أنّ "الحاوية" لن يشتمل العنصر .photo-gallery
على الشريط الجانبي.
معًا، لتحويل CSS .photo-gallery
من قواعد @media
إلى قواعد @container
، تكون مجموعة التغييرات الكاملة على النحو التالي:
/* Before, using the original breakpoint sizes: */
@media (min-width: 800px) { /* ... */ }
@media (min-width: 1200px) { /* ... */ }
/* After, with the breakpoint sizes reduced by 200px: */
@container (min-width: 600px) { /* ... */ }
@container (min-width: 1000px) { /* ... */ }
وتجدر الإشارة إلى أنّه لا داعي لتغيير أيٍّ من الأنماط داخل حزمة التعريف، لأنّ هذه الأنماط تعكس شكل المكوِّن بدلاً من متى يجب تطبيق أنماط معيّنة.
بعد تعديل أنماط المكوّنات من قواعد @media
إلى قواعد @container
، تكون الخطوة التالية هي إعداد عناصر الحاوية.
الخطوة 2: إضافة عناصر الحاوية إلى رمز HTML
حددت الخطوة السابقة أنماط المكوّنات التي تستند إلى حجم عنصر الحاوية. الخطوة التالية هي تحديد العناصر في صفحتك التي يجب أن تكون عناصر الحاوية التي سيكون حجمها متناسبًا مع قواعد @container
.
يمكنك تعريف أي عنصر ليكون عنصر حاوية في CSS من خلال ضبط السمة container-type
على size
أو inline-size
. إذا كانت قواعد الحاوية تعتمد على العرض، ستكون السمة inline-size
هي الخيار الذي تريد استخدامه بشكل عام.
فكّر في موقع ببنية HTML الأساسية التالية:
<body>
<div class="sidebar">...</div>
<div class="content">...</div>
</body>
لإنشاء عنصرَي .sidebar
و.content
على حاوية الموقع الإلكتروني هذه، أضِف هذه القاعدة إلى CSS:
.content, .sidebar {
container-type: inline-size;
}
بالنسبة إلى المتصفحات التي تتيح استخدام طلبات البحث في الحاويات، لن تحتاج إلى CSS سوى لإنشاء أنماط المكوّنات المحددة في الخطوة السابقة وتكون مرتبطة بمنطقة المحتوى الرئيسية أو الشريط الجانبي، بناءً على العنصر الذي توجد به.
ومع ذلك، هناك بعض الإجراءات الإضافية التي يجب تنفيذها بالنسبة إلى المتصفّحات التي لا تتيح استخدام طلبات البحث في الحاويات.
عليك إضافة بعض الرموز البرمجية التي ترصد تغيُّر حجم عناصر الحاوية، ثم تعدِّل نموذج العناصر في المستند (DOM) استنادًا إلى هذه التغييرات بطريقة يمكن لخدمة CSS جذبها.
ولحسن الحظّ، فإنّ الرمز المطلوب لتنفيذ ذلك بسيط جدًا، إذ يمكن استبعاده تمامًا إلى مكوِّن مشترك يمكنك استخدامه في أيّ موقع إلكتروني وأيّ منطقة محتوى.
يحدّد الرمز البرمجي التالي عنصر <responsive-container>
قابلاً لإعادة الاستخدام يستجيب تلقائيًا لتغييرات الحجم ويضيف فئات نقاط الإيقاف التي يمكن لخدمة CSS ضبط نمطها استنادًا إلى ما يلي:
// A mapping of default breakpoint class names and min-width sizes.
// Redefine these (or add more) as needed based on your site's design.
const defaultBreakpoints = {SM: 400, MD: 600 LG: 800, XL: 1000};
// A resize observer that monitors size changes to all <responsive-container>
// elements and calls their `updateBreakpoints()` method with the updated size.
const ro = new ResizeObserver((entries) => {
entries.forEach((e) => e.target.updateBreakpoints(e.contentRect));
});
class ResponsiveContainer extends HTMLElement {
connectedCallback() {
const bps = this.getAttribute('breakpoints');
this.breakpoints = bps ? JSON.parse(bps) : defaultBreakpoints;
this.name = this.getAttribute('name') || '';
ro.observe(this);
}
disconnectedCallback() {
ro.unobserve(this);
}
updateBreakpoints(contentRect) {
for (const bp of Object.keys(this.breakpoints)) {
const minWidth = this.breakpoints[bp];
const className = this.name ? `${this.name}-${bp}` : bp;
this.classList.toggle(className, contentRect.width >= minWidth);
}
}
}
self.customElements.define('responsive-container', ResponsiveContainer);
يعمل هذا الرمز من خلال إنشاء عنصر ResizeObserver يستجيب تلقائيًا لتغييرات الحجم لأي عناصر <responsive-container>
في نموذج العناصر في المستند (DOM). إذا تطابق تغيير الحجم مع أحد أحجام نقاط الإيقاف المحددة، تتم إضافة فئة باسم نقطة التوقف هذه إلى العنصر (وإزالتها إذا لم يعد الشرط متطابقًا).
على سبيل المثال، إذا كان width
للعنصر <responsive-container>
بين 600 و800 بكسل (استنادًا إلى قيم نقاط الإيقاف التلقائية المحدّدة في الرمز)، ستتم إضافة الفئتَين SM
وMD
على النحو التالي:
<responsive-container class="SM MD">...</responsive-container>
تتيح لك هذه الفئات تحديد أنماط احتياطية للمتصفّحات التي لا تتيح استخدام طلبات البحث في الحاويات (اطّلِع على الخطوة 3: إضافة أنماط احتياطية إلى CSS).
لتعديل رمز HTML السابق لاستخدام عنصر الحاوية هذا، غيِّر الشريط الجانبي وعناصر <div>
للمحتوى الرئيسي لتصبح عناصر <responsive-container>
بدلاً من ذلك:
<body>
<responsive-container class="sidebar">...</responsive-container>
<responsive-container class="content">...</responsive-container>
</body>
في معظم الحالات، يمكنك استخدام العنصر <responsive-container>
فقط بدون أيّ تخصيص، ولكن إذا أردت تخصيصه، تتوفّر لك الخيارات التالية:
- أحجام نقاط الإيقاف المخصصة: يستخدم هذا الرمز مجموعة من أسماء فئات نقاط التوقف التلقائية وأحجام الحد الأدنى للعرض، ولكن يمكنك تغيير هذه الإعدادات التلقائية إلى ما تريده. يمكنك أيضًا إلغاء هذه القيم على أساس كل عنصر باستخدام السمة
breakpoints
. - الحاويات المُعنونة: يتيح هذا الرمز أيضًا استخدام الحاويات المُسمّاة من خلال تمرير السمة
name
. قد يكون هذا مهمًا إذا كنت بحاجة إلى دمج عناصر الحاوية. راجِع قسم القيود للتعرّف على مزيد من التفاصيل.
في ما يلي مثال يحدّد كلا خيارَي الضبط هذين:
<responsive-container
name='sidebar'
breakpoints='{"bp4":400,"bp5":500,"bp6":600,"bp7":700,"bp8":800,"bp9":900,"bp10":1000}'>
</responsive-container>
أخيرًا، عند تجميع هذا الرمز، تأكّد من استخدام اكتشاف الميزات وimport()
الديناميكي لتحميله فقط إذا لم يكن المتصفّح متوافقًا مع طلبات الحاوية.
if (!CSS.supports('container-type: inline-size')) {
import('./path/to/responsive-container.js');
}
الخطوة 3: إضافة أنماط احتياطية إلى CSS
الخطوة الأخيرة في هذه الاستراتيجية هي إضافة أنماط احتياطية للمتصفّحات التي لا تتعرّف على الأنماط المحدّدة في قواعد @container
. يمكنك إجراء ذلك من خلال تكرار هذه القواعد باستخدام فئات نقاط الإيقاف التي يتم ضبطها على عناصر <responsive-container>
.
استكمالاً للمثال .photo-gallery
السابق، قد تظهر الأنماط الاحتياطية لقاعدتَي @container
على النحو التالي:
/* Container query styles for the `MD` breakpoint. */
@container (min-width: 600px) {
.photo-gallery {
grid-template-columns: 1fr 1fr;
}
}
/* Fallback styles for the `MD` breakpoint. */
@supports not (container-type: inline-size) {
:where(responsive-container.MD) .photo-gallery {
grid-template-columns: 1fr 1fr;
}
}
/* Container query styles for the `XL` breakpoint. */
@container (min-width: 1000px) {
.photo-gallery {
grid-template-columns: 1fr 1fr 1fr;
}
}
/* Fallback styles for the `XL` breakpoint. */
@supports not (container-type: inline-size) {
:where(responsive-container.XL) .photo-gallery {
grid-template-columns: 1fr 1fr 1fr;
}
}
في هذا الرمز، تتوفر لكل قاعدة @container
قاعدة مكافئة تتطابق بشكل مشروط مع العنصر <responsive-container>
في حال توفّر فئة نقطة الإيقاف المقابلة.
يتم ربط الجزء من أداة الاختيار المتطابق مع عنصر <responsive-container>
في أداة اختيار من الفئة الصورية :where() للحفاظ على خصوصية أداة الاختيار الاحتياطية مكافئة لخصوصية أداة الاختيار الأصلية ضمن القاعدة @container
.
ويتم أيضًا التفاف كل قاعدة احتياطية في بيان @supports
. على الرغم من أنّ هذا الإجراء ليس ضروريًا تمامًا للعمل الاحتياطي، يعني ذلك أنّ المتصفّح يتجاهل هذه القواعد تمامًا إذا كان يتوافق مع طلبات البحث في الحاوية، ما قد يؤدي إلى تحسين أداء مطابقة الأنماط بشكل عام. ومن المحتمل أيضًا أن يسمح لأدوات إنشاء أو شبكات توصيل المحتوى (CDN) بإزالة هذه التعريفات إذا كانوا يعلمون أن المتصفح يدعم استعلامات الحاوية ولا يحتاج إلى هذه الأنماط الاحتياطية.
يتمثل الجانب السلبي الرئيسي لهذه الاستراتيجية الاحتياطية في أنها تتطلب منك تكرار تعريف النمط مرتين، الأمر الذي يكون عملاً مملاً ويعرّض للخطأ. في المقابل، إذا كنت تستخدم معالجًا مسبقًا في CSS، يمكنك استخراجه في تشكيلة تُنشئ لك القاعدة @container
والرمز الاحتياطي على حد سواء. إليك مثال على استخدام Sass:
@use 'sass:map';
$breakpoints: (
'SM': 400px,
'MD': 600px,
'LG': 800px,
'XL': 1000px,
);
@mixin breakpoint($breakpoint) {
@container (min-width: #{map.get($breakpoints, $breakpoint)}) {
@content();
}
@supports not (container-type: inline-size) {
:where(responsive-container.#{$breakpoint}) & {
@content();
}
}
}
بعد الحصول على هذا المزيج، يمكنك تعديل أنماط مكوِّن .photo-gallery
الأصلية إلى نمط مشابه، ما سيزيل التكرار تمامًا:
.photo-gallery {
display: grid;
grid-template-columns: 1fr;
@include breakpoint('MD') {
grid-template-columns: 1fr 1fr;
}
@include breakpoint('XL') {
grid-template-columns: 1fr 1fr 1fr;
}
}
وهذا كل ما في الأمر!
ملخّص
إذًا، لنلخص ما سبق، إليك كيفية تحديث التعليمات البرمجية لاستخدام استعلامات الحاويات الآن باستخدام إجراء احتياطي متداخل المتصفحات.
- مكوّنات الهوية التي تريد تغيير نمطها بما يتوافق مع حاويتها، وتعديل قواعد
@media
في لغة CSS لاستخدام قواعد@container
ويمكنك أيضًا توحيد مجموعة من أسماء نقاط التوقف (إذا لم يسبق لك ذلك) لتتطابق مع شروط الحجم في قواعد الحاوية. - أضِف رمز JavaScript الذي يتيح استخدام عنصر
<responsive-container>
المخصّص، ثم أضِف العنصر<responsive-container>
إلى أي مناطق محتوى في صفحتك تريد ربط المكوّنات بها. - للتوافق مع المتصفحات القديمة، يمكنك إضافة أنماط احتياطية إلى CSS تتطابق مع فئات نقاط الإيقاف التي تتم إضافتها تلقائيًا إلى عناصر
<responsive-container>
في HTML. يُفضَّل استخدام مزيج من المعالجات المسبقة لـ CSS لتجنب الاضطرار إلى كتابة الأنماط نفسها مرتين.
الأمر الجيد في هذه الاستراتيجية هو وجود تكلفة إعداد تُدفع لمرة واحدة، ولكن بعد ذلك لن يلزم أي جهد إضافي لإضافة مكونات جديدة وتحديد الأنماط النسبية للحاوية لها.
أمثلة واقعية
قد تكون أفضل طريقة لفهم طبيعة جميع هذه الخطوات هي الاطّلاع على عرض توضيحي عملي لهذه الخطوات.
هذا العرض التوضيحي هو إصدار معدَّل من موقع إلكتروني تم إنشاؤه في عام 2019 (قبل توفُّر طلبات البحث في الحاوية) للمساعدة في توضيح سبب أهمية طلبات البحث في الحاوية لإنشاء مكتبات مكوّنات متجاوبة حقًا.
وبما أنّ هذا الموقع الإلكتروني يتضمّن أنماطًا محددة لمجموعة من "المكوّنات السريعة الاستجابة"، كان مرشحًا مثاليًا لاختبار الاستراتيجية التي تم تقديمها هنا على موقع بسيط. في الواقع، كان التعديل بسيطًا جدًا ولم يتطلب أي تغييرات تقريبًا على أنماط الموقع الإلكتروني الأصلية.
يمكنك مراجعة رمز المصدر التجريبي الكامل على GitHub، والتأكّد من إلقاء نظرة محدّدة على CSS الخاصة بالمكوّن التجريبي لمعرفة كيفية تحديد الأنماط الاحتياطية. إذا كنت تريد اختبار السلوك الاحتياطي فقط، هناك عرض توضيحي احتياطي فقط يشتمل على تلك الصيغة فقط، حتى في المتصفّحات التي تتيح طلبات البحث في الحاويات.
القيود والتحسينات المحتملة
كما ذكرنا في بداية هذه المشاركة، تعمل الاستراتيجية الموضّحة هنا بشكل جيد مع معظم حالات الاستخدام التي يهتم بها المطوّرون فعليًا عند الوصول إلى طلبات الحاوية.
ومع ذلك، هناك بعض حالات الاستخدام الأكثر تقدّمًا التي لا تحاول هذه الاستراتيجية دعمها عمدًا، وسنتناولها تاليًا:
وحدات طلب الحاوية
تحدد مواصفات طلبات البحث في الحاوية عددًا من الوحدات الجديدة التي تتعلق جميعها بحجم الحاوية. على الرغم من أنها قد تكون مفيدة في بعض الحالات، فمن المحتمل أن يتم تحقيق غالبية التصميمات سريعة الاستجابة من خلال الوسائل الحالية، مثل النسب المئوية أو استخدام تخطيطات الشبكة أو المرنة.
مع ذلك، إذا كنت بحاجة إلى استخدام وحدات طلبات البحث في الحاوية، يمكنك بسهولة إضافة دعم لها باستخدام الخصائص المخصَّصة. على وجه التحديد، من خلال تحديد خاصية مخصصة لكل وحدة مستخدمة في عنصر الحاوية، كما يلي:
responsive-container {
--cqw: 1cqw;
--cqh: 1cqh;
}
وبعد ذلك، عندما تحتاج إلى الوصول إلى وحدات طلب الحاوية، استخدِم هذه السمات بدلاً من استخدام الوحدة نفسها:
.photo-gallery {
font-size: calc(10 * var(--cqw));
}
بعد ذلك، لإتاحة المتصفحات القديمة، اضبط قيم هذه السمات المخصّصة في عنصر الحاوية ضمن استدعاء ResizeObserver
.
class ResponsiveContainer extends HTMLElement {
// ...
updateBreakpoints(contentRect) {
this.style.setProperty('--cqw', `${contentRect.width / 100}px`);
this.style.setProperty('--cqh', `${contentRect.height / 100}px`);
// ...
}
}
يتيح لك ذلك "اجتياز" هذه القيم من JavaScript إلى CSS، وبعد ذلك ستتوفر لك إمكانات CSS الكاملة (على سبيل المثال، calc()
وmin()
وmax()
وclamp()
) للتعامل معها حسب الحاجة.
توافُق الخصائص المنطقية ووضع الكتابة
ربما لاحظت استخدام inline-size
بدلاً من width
في تعريفات @container
في بعض أمثلة CSS هذه. ربما لاحظت أيضًا الوحدتَين cqi
وcqb
الجديدتَين (لأحجام الوحدات المضمّنة وأحجام الكتل، على التوالي). تعكس هذه الميزات الجديدة تحول CSS إلى الخصائص والقيم المنطقية بدلاً من السمات المادية أو المستندة إلى الاتجاهات.
للأسف، لا تزال واجهات برمجة التطبيقات مثل Resize Observer تعرض القيم في width
وheight
، وبالتالي إذا كانت تصميماتك تحتاج إلى مرونة في الخصائص المنطقية، عليك معرفة ذلك بنفسك.
يمكن استخدام وضع الكتابة باستخدام عنصر مثل getComputedStyle()
لإدخال عنصر الحاوية، إلا أنّ ذلك يترتّب عليه تكلفة ولا يمكن رصد أي تغييرات في وضع الكتابة.
لهذا السبب، فإنّ أفضل طريقة هي أن يقبل العنصر <responsive-container>
نفسه سمة وضع الكتابة التي يمكن لمالك الموقع الإلكتروني ضبطها (وتعديلها) حسب الحاجة. لتنفيذ ذلك، يجب اتّباع الطريقة نفسها الموضّحة في القسم السابق، وتبديل width
وheight
حسب الحاجة.
الحاويات المتداخلة
تسمح لك السمة container-name
بمنح الحاوية اسمًا، يمكنك بعد ذلك الإشارة إليه في قاعدة @container
. تكون الحاويات المُعنوَنة مفيدة إذا كانت لديك حاويات مضمَّنة في حاويات وكنت بحاجة إلى قواعد معيّنة لمطابقة حاويات معيّنة فقط (وليس فقط حاوية الأصل الأقرب).
تستخدم الاستراتيجية الاحتياطية الموضحة هنا المكمِّلات التابعة لتصميم العناصر التي تتطابق مع فئات نقاط توقف معيّنة. يمكن أن يتوقف هذا الأمر إذا كان لديك حاويات مضمَّنة، لأنّ أي عدد من فئات نقاط الإيقاف من كيانات عناصر الحاوية المتعددة يمكن أن يتطابق مع مكون معيّن في الوقت نفسه.
على سبيل المثال، يوجد هنا عنصران <responsive-container>
يلتفان حول المكوِّن .photo-gallery
، ولكن نظرًا لأن الحاوية الخارجية أكبر من الحاوية الداخلية، تمت إضافة فئات نقاط توقف مختلفة.
<responsive-container class="SM MD LG">
...
<responsive-container class="SM">
...
<div class="photo-gallery">...</div class="photo-gallery">
</responsive-container>
</responsive-container>
في هذا المثال، ستؤثّر الفئتان MD
وLG
الموجودة في الحاوية الخارجية في قواعد النمط المطابِقة للمكوّن .photo-gallery
، والتي لا تتطابق مع سلوك طلبات الحاوية (لأنّها تتطابق فقط مع حاوية الأصل الأقرب).
للتعامل مع هذه المشكلة، عليك اتّخاذ أحد الإجراءَين التاليَين:
- احرص دائمًا على تسمية أي حاويات تدمجها، ثم تأكَّد من أنّ فئات نقاط التوقف بادئة باسم الحاوية لتجنُّب حدوث أي تعارضات.
- يمكنك استخدام المكمِّل الثانوي بدلاً من أداة التجميع الفرعية في أدوات الاختيار الاحتياطية (التي تفرض قيودًا أكثر قليلاً).
يتضمن قسم الحاويات المتداخلة في الموقع الإلكتروني التجريبي مثالاً على هذه العملية باستخدام الحاويات المُسمّاة، إلى جانب مجموعة مزيج Sass التي تستخدمها في الرمز لإنشاء الأنماط الاحتياطية لكل من قواعد @container
المسماة وغير المُسمّاة.
ماذا عن المتصفّحات التي لا تتوافق مع :where()
أو العناصر المخصّصة أو تغيير حجم المراقب؟
على الرغم من أنّ واجهات برمجة التطبيقات هذه قد تبدو جديدة نسبيًا، فإنّها جميعًا أصبحت متوافقة مع جميع المتصفّحات منذ أكثر من ثلاث سنوات، وجميعها تشكّل جزءًا من Baseline المتاح على نطاق واسع.
لذلك، ما لم تكن لديك بيانات تشير إلى أنّ جزءًا كبيرًا من زوّار موقعك الإلكتروني يستخدمون متصفحات لا تتوافق مع إحدى هذه الميزات، ليس هناك مبرّر لعدم السماح باستخدامها بحرية بدون اتّخاذ إجراء احتياطي.
وحتى في هذه الحالة، فإن أسوأ ما يمكن أن يحدث هو أن الإجراء الاحتياطي لن ينجح مع نسبة صغيرة جدًا من المستخدمين، ما يعني أنهم سيرون طريقة العرض التلقائية بدلاً من طريقة عرض محسَّنة لحجم الحاوية.
من المفترض أن تظل وظائف الموقع الإلكتروني تعمل، وهذا هو المهم حقًا.
لماذا لا يتم استخدام polyfill لطلب بحث الحاوية فقط؟
من المعروف أنّ إضافة ميزات CSS صعبة جدًّا وتتطلب بشكل عام إعادة تنفيذ محلّل CSS بالكامل ومنطق التتابع التدريجي في JavaScript. نتيجةً لذلك، على مؤلّفي رموز polyfill CSS إجراء العديد من المُفاضلات التي تكون غالبًا مع العديد من القيود المفروضة على الميزات، بالإضافة إلى النفقات العامة المرتبطة بالأداء.
لهذه الأسباب، لا ننصح عمومًا باستخدام رموز polyfill CSS في الإنتاج، بما في ذلك container-query-polyfill من ميزات Google Chrome الاختبارية التي لم تعد تخضع للصيانة (وكانت مصمّمة في المقام الأول لأغراض تجريبية).
إنّ الاستراتيجية الاحتياطية التي تمت مناقشتها هنا تتضمّن عددًا أقل من القيود، وتتطلّب رمزًا أقل بكثير، وستعمل بشكل أفضل بكثير من أيٍ من رموز polyfill لطلب البحث في الحاوية.
هل تحتاج حتى إلى تنفيذ إجراء احتياطي للمتصفّحات القديمة؟
إذا كنت قلقًا بشأن أي من القيود المذكورة هنا، فمن الأفضل أن تسأل نفسك ما إذا كنت بحاجة بالفعل إلى تنفيذ إجراء احتياطي في المقام الأول. بعد كل شيء، فإن أسهل طريقة لتجنب هذه القيود هي استخدام الميزة فقط دون أي إجراءات احتياطية. بصراحة، في كثير من الحالات، قد يكون هذا خيارًا معقولاً تمامًا.
وفقًا للموقع الإلكتروني caniuse.com، يساهم استخدام طلبات البحث في الحاويات في 90% من مستخدمي الإنترنت على مستوى العالم، وبالنسبة إلى الكثير من الأشخاص الذين يقرؤون هذه المشاركة، من المرجّح أن يكون العدد أعلى قليلاً بالنسبة إلى قاعدة مستخدميهم. لذا من المهم أن تضع في اعتبارك أن معظم المستخدمين سيرون إصدار طلب بحث الحاوية لواجهة المستخدم في تطبيقك. وبالنسبة إلى الـ 10٪ من المستخدمين الذين لن يفعلوا ذلك، لا يبدو الأمر وكأنهم سيتعرضون لتجربة سيئة. عند اتّباع هذه الاستراتيجية، سيرى هؤلاء المستخدمون في أسوأ الأحوال القيمة التلقائية أو "الجهاز الجوّال". التخطيط لبعض المكونات، والتي ليست نهاية العالم.
عند إجراء المفاضلات، من الممارسات الجيدة إجراء تحسين لغالبية المستخدمين - بدلاً من التخلف عن نهج أدنى قاسم مشترك يمنح جميع المستخدمين تجربة متسقة، ولكن دون المستوى نفسه.
لذا، قبل أن تفترض أنّه لا يمكنك استخدام طلبات البحث في الحاوية بسبب عدم توافق المتصفّح، يجب تخصيص بعض الوقت للتفكير في طبيعة التجربة إذا اخترت اعتمادها. قد تكون المقايضة تستحق ذلك، حتى بدون أي إجراءات احتياطية.
التطلّع إلى المستقبل
نأمل أن تكون هذه المشاركة قد أقنعتك بأنه من الممكن استخدام طلبات بحث الحاويات في مرحلة الإنتاج الآن، وأنّك لست بحاجة إلى الانتظار لسنوات حتى تختفي جميع المتصفحات غير المتوافقة تمامًا.
على الرغم من أنّ الاستراتيجية الموضّحة هنا تتطلب بذل مجهود إضافي، يجب أن تكون بسيطة ومباشرة لدرجة أنّ معظم المستخدمين يمكنهم اعتمادها على مواقعهم الإلكترونية. ومع ذلك، هناك بالتأكيد مجال لتسهيل اعتماده. تتمثل إحدى الأفكار في دمج الكثير من الأجزاء المختلفة في مكون واحد - محسّن لإطار عمل أو حزمة محددة - يعالج كل أعمال الغراء نيابة عنك. إذا أنشأت محتوًى كهذا، يُرجى إعلامنا بذلك وسنساعدك في الترويج له.
أخيرًا، بالإضافة إلى طلبات البحث في الحاويات، هناك الكثير من ميزات CSS وواجهة المستخدم الرائعة التي يمكن الآن تشغيلها التفاعلي على جميع محركات المتصفحات الرئيسية. وكمنتدى، فلنكتشف كيف يمكننا استخدام هذه الميزات الآن فعليًا، حتى يستفيد المستخدمون.
تعديل (25 يوليو 2024): في الأساس، تم تقديم الإرشادات الواردة في "الخطوة 1" أن الاستعلامات عن الوسائط واستعلامات الحاوية يمكن أن تستخدم نفس شروط الحجم. غالبًا ما يكون هذا صحيحًا ولكن ليس دائمًا (كما وضّحت بعض الأسباب بشكل صحيح). توضّح الإرشادات المعدّلة الآن هذا الأمر وتقدّم أمثلة على الحالات التي قد تحتاج فيها إلى تغيير شروط الحجم.
تعديل (2 يوليو 2024): استخدمت جميع أمثلة رموز CSS في الأصل Sass (لتحقيق الاتساق مع الاقتراح النهائي). استنادًا إلى ملاحظات القرّاء، تم تعديل أول عدد قليل من CSS إلى CSS العادي، ولم يتم استخدام Sass إلا في عيّنات التعليمات البرمجية التي تتطلّب استخدام عناصر التشكيل.