دوال CSS: calc() و min() و max() و clamp()
مقدمة في دوال CSS
دوال CSS هي قيم خاصة تقوم بإجراء العمليات الحسابية والمقارنات والتحويلات مباشرة داخل ملفات التنسيق الخاصة بك. على عكس الخصائص التي تقبل قيما ثابتة مثل width: 200px أو font-size: 16px، تتيح لك دوال CSS وصف العلاقات الديناميكية بين القيم. فهي تسمح لك بمزج وحدات مختلفة والاختيار بين قيم متنافسة وإنشاء تخطيطات مرنة تتكيف بسلاسة عبر أحجام الشاشات المختلفة -- كل ذلك بدون سطر واحد من JavaScript.
الدوال الأربع التي سنغطيها في هذا الدرس -- calc() وmin() وmax() وclamp() -- هي الدوال الرياضية الأساسية في CSS. معا، تشكل مجموعة أدوات قوية للتصميم المتجاوب. تقوم دالة calc() بإجراء العمليات الحسابية مع وحدات مختلطة. وتقارن دالتا min() وmax() القيم وتختاران الأصغر أو الأكبر. وتقيد دالة clamp() القيمة بين حد أدنى وأقصى مما ينشئ نطاقا متجاوبا. بمجرد إتقان هذه الدوال، ستجد نفسك تلجأ إلى استعلامات الوسائط بشكل أقل بكثير، لأن CSS نفسه يمكنه التكيف مع بيئته رياضيا.
دالة calc()
تتيح لك دالة calc() إجراء عمليات الجمع والطرح والضرب والقسمة داخل أي خاصية CSS تقبل قيمة رقمية. قوتها الأعظم هي أنها تستطيع مزج وحدات مختلفة في تعبير واحد. يمكنك طرح البكسل من النسب المئوية وإضافة rem إلى وحدات إطار العرض أو دمج أي وحدات يمكن للمتصفح حلها. يحسب المتصفح القيمة النهائية في وقت العرض لذا تنتج تعبيرات calc() دائما نتيجة دقيقة بغض النظر عن حجم الشاشة أو إعدادات الخط.
صيغة calc() الأساسية
الصيغة بسيطة ومباشرة: غلف تعبيرا رياضيا داخل calc(). يمكنك استخدام عوامل الحساب الأربعة: + (الجمع) و- (الطرح) و* (الضرب) و/ (القسمة). هناك قاعدة حرجة واحدة يجب أن تتذكرها: يجب أن يكون عاملا + و- محاطين بمسافة بيضاء على كلا الجانبين وإلا سيفشل التعبير بصمت. لا يتطلب عاملا * و/ مسافة بيضاء لكن إضافتها تحسن قابلية القراءة.
الاستخدام الأساسي لـ calc()
/* طرح عرض شريط جانبي ثابت من العرض الكامل */
.main-content {
width: calc(100% - 250px);
}
/* إضافة إزاحة بوحدة rem إلى نسبة مئوية */
.container {
padding-left: calc(5% + 1rem);
}
/* تقسيم ارتفاع إطار العرض لأقسام متساوية */
.section {
height: calc(100vh / 3);
}
/* ضرب قيمة أساسية */
.large-spacing {
margin-bottom: calc(1.5rem * 2);
}
/* خطأ: مسافة بيضاء مفقودة حول عاملي + و - */
.broken {
width: calc(100%-250px); /* هذا لن يعمل */
width: calc(100% - 250px); /* هذا سيعمل */
}
+ و- داخل calc(). كتابة calc(100%-250px) بدون مسافات ستؤدي إلى تجاهل التصريح بالكامل من قبل المتصفح. لا يشترط عاملا * و/ هذا المتطلب لكن التباعد المتسق يجعل الكود أكثر قابلية للقراءة.مزج الوحدات مع calc()
تكمن القوة الحقيقية لـ calc() في مزج أنواع مختلفة من الوحدات. في CSS العادي لا يمكنك كتابة width: 100% - 250px لأن المتصفح لا يعرف كيف يحل هذا التعبير. مع calc() يؤجل المتصفح الحساب حتى وقت التخطيط عندما يعرف القيم الفعلية بالبكسل لكل من النسب المئوية والوحدات الثابتة. هذا يعني أنه يمكنك دمج النسب المئوية والبكسل وrem وem ووحدات إطار العرض وأي وحدات طول CSS أخرى في تعبير واحد.
مزج أنواع الوحدات المختلفة
/* نسبة مئوية ناقص بكسل: تخطيط شريط جانبي كلاسيكي */
.main-content {
width: calc(100% - 300px);
margin-left: 300px;
}
/* وحدات إطار العرض ناقص rem: ارتفاع كامل ناقص الرأس */
.page-body {
min-height: calc(100vh - 4rem);
}
/* نسبة مئوية زائد rem: حشوة متجاوبة مع حد أدنى */
.card {
padding: calc(2% + 0.5rem);
}
/* عرض إطار العرض ناقص حشوة ثابتة */
.hero-text {
max-width: calc(100vw - 4rem);
}
/* em مدمج مع البكسل */
.input-field {
width: calc(20em + 40px);
}
تداخل تعبيرات calc()
يمكنك تداخل calc() داخل calc() أخرى لحسابات أكثر تعقيدا. بينما يكون calc() الخارجي مطلوبا دائما، يمكن استخدام استدعاءات calc() الداخلية لتجميع التعبيرات الفرعية من أجل الوضوح. تسمح المتصفحات الحديثة أيضا باستخدام الأقواس داخل calc() بدون الكلمة المفتاحية calc() الداخلية، لكن التداخل الصريح لـ calc() صالح تماما وأحيانا يحسن قابلية القراءة للصيغ المعقدة.
تداخل دوال calc()
/* تداخل calc لحسابات تخطيط معقدة */
.sidebar-content {
width: calc(100% - calc(250px + 2rem));
}
/* مكافئ باستخدام الأقواس (المتصفحات الحديثة) */
.sidebar-content {
width: calc(100% - (250px + 2rem));
}
/* حساب متعدد الخطوات معقد */
.grid-item {
/* العرض الإجمالي ناقص الفجوات مقسوم على عدد الأعمدة */
width: calc((100% - (3 * 20px)) / 4);
}
/* تحجيم خط متجاوب مع calc */
.dynamic-heading {
font-size: calc(1rem + calc(2vw - 0.25rem));
}
calc() مع الخصائص المخصصة
أحد أقوى الأنماط في CSS الحديث هو دمج calc() مع خصائص CSS المخصصة (المتغيرات). تتيح لك الخصائص المخصصة تعريف قيم قابلة لإعادة الاستخدام وتتيح لك calc() اشتقاق قيم جديدة منها رياضيا. هذا ينشئ نظام تصميم حيث يؤدي تغيير متغير واحد إلى تغييرات متناسبة في جميع أنحاء التخطيط. يمكنك تعريف وحدة تباعد أساسية واشتقاق جميع التباعدات الأخرى منها أو تعيين متغير عدد الأعمدة وحساب العروض ديناميكيا.
calc() مع الخصائص المخصصة
:root {
--sidebar-width: 280px;
--header-height: 64px;
--gap: 1.5rem;
--columns: 3;
--base-spacing: 8px;
}
/* اشتقاق أبعاد التخطيط من المتغيرات */
.main-content {
width: calc(100% - var(--sidebar-width));
min-height: calc(100vh - var(--header-height));
}
/* حساب عرض عنصر الشبكة من عدد الأعمدة */
.grid-item {
width: calc((100% - (var(--columns) - 1) * var(--gap)) / var(--columns));
}
/* مقياس تباعد متناسب */
.spacing-sm { margin: calc(var(--base-spacing) * 1); } /* 8px */
.spacing-md { margin: calc(var(--base-spacing) * 2); } /* 16px */
.spacing-lg { margin: calc(var(--base-spacing) * 3); } /* 24px */
.spacing-xl { margin: calc(var(--base-spacing) * 5); } /* 40px */
/* تجاوز متغير وتتحدث جميع الحسابات تلقائيا */
@media (max-width: 768px) {
:root {
--columns: 2;
--sidebar-width: 200px;
}
}
calc() مع الخصائص المخصصة، تذكر أن عاملي * و/ يتطلبان أن يكون أحد المعاملات على الأقل رقما عاديا (بدون وحدة). لا يمكنك ضرب قيمتين لكل منهما وحدة. على سبيل المثال calc(10px * 2) يعمل، لكن calc(10px * 2px) لا يعمل. هذا مهم عند استخدام الخصائص المخصصة -- إذا كان متغيرك يحتوي على وحدة، يجب أن يكون المضاعف بدون وحدة.دالة min()
تقبل دالة min() قيمتين أو أكثر مفصولة بفواصل وتعيد الأصغر. يقيم المتصفح كل قيمة ويقارنها ويستخدم أيهما يحل إلى القيمة المحسوبة الأصغر. هذا مفيد للغاية لتعيين حدود عليا على الأحجام بدون الحاجة إلى استعلامات الوسائط. يمكنك التفكير في min() على أنها تقول "استخدم الأصغر من هذه الخيارات" -- فهي تحد القيمة بشكل طبيعي عندما تنمو بشكل كبير جدا.
صيغة min() الأساسية واستخدامها
مرر قيمتين أو أكثر مفصولة بفواصل. يختار المتصفح أيهما يحل إلى أصغر طول محسوب. يمكن أن يكون كل وسيط قيمة ثابتة أو نسبة مئوية أو وحدة إطار عرض أو تعبير calc() أو أي طول CSS صالح آخر.
استخدام min() للتحجيم المتجاوب
/* الحاوية 90% من إطار العرض لكن لا تتجاوز 1200px */
.container {
width: min(90%, 1200px);
}
/* حجم الخط ينمو مع إطار العرض لكن يتوقف عند 24px */
.heading {
font-size: min(5vw, 24px);
}
/* الحشوة متجاوبة لكن لها حد أقصى */
.section {
padding: min(5vw, 60px);
}
/* الصورة لا تتجاوز حاويتها أو 600px */
.responsive-image {
max-width: min(100%, 600px);
}
/* min() مع ثلاث قيم أو أكثر */
.flexible-box {
width: min(100%, 800px, 90vw);
}
حالة الاستخدام الكلاسيكية لـ min() هي نمط الحاوية المتجاوبة. قبل min() كنت عادة تكتب width: 90% مدمجة مع max-width: 1200px. مع min() تعبر عن هذا في تصريح واحد: width: min(90%, 1200px). النتيجة متطابقة -- الحاوية تأخذ 90% من العنصر الأب حتى تتجاوز 1200px وعندها تبقى عند 1200px. هذا النمط يلغي الحاجة إلى تصريحات max-width منفصلة في العديد من الحالات.
min() بدون استعلامات الوسائط
إحدى أعظم مزايا min() هي أنها توفر سلوكا متجاوبا بدون استعلامات وسائط. تقيم الدالة باستمرار عند كل حجم إطار عرض مما ينشئ انتقالات سلسة بدلا من القفزات المفاجئة التي تنتجها نقاط توقف استعلامات الوسائط. يسمى هذا أحيانا "التصميم الجوهري" -- CSS نفسه يحتوي على المنطق للتكيف بدلا من الاعتماد على شروط نقاط التوقف الخارجية.
استبدال استعلامات الوسائط بـ min()
/* النهج القديم: استعلامات وسائط للحشوة المتجاوبة */
.card {
padding: 16px;
}
@media (min-width: 768px) {
.card {
padding: 32px;
}
}
@media (min-width: 1200px) {
.card {
padding: 48px;
}
}
/* النهج الجديد: min() تتعامل معها في سطر واحد */
.card {
padding: min(5vw, 48px);
}
/* فجوة متجاوبة بدون نقاط توقف */
.grid {
display: grid;
gap: min(3vw, 32px);
grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
}
دالة max()
دالة max() هي نظيرة min(). تقبل قيمتين أو أكثر مفصولة بفواصل وتعيد الأكبر. بينما تضع min() حدا أعلى، تضع max() حدا أدنى -- فهي تضمن ألا تنخفض القيمة أبدا تحت عتبة معينة. فكر في max() على أنها تقول "استخدم الأكبر من هذه الخيارات" -- فهي توفر أرضية للقيم التي قد تتقلص بشكل كبير جدا.
صيغة max() الأساسية واستخدامها
استخدام max() للأحجام الدنيا
/* حجم الخط على الأقل 16px حتى لو كان 2vw أصغر */
.body-text {
font-size: max(16px, 2vw);
}
/* العنصر على الأقل 300px عرضا أو 50% من الأب */
.sidebar {
width: max(300px, 50%);
}
/* الحشوة لا تنخفض أبدا تحت 1rem */
.container {
padding: max(1rem, 3vw);
}
/* الهامش على الأقل 20px */
.spaced-section {
margin-top: max(20px, 5vh);
}
/* ضمان حد أدنى لحجم هدف اللمس على المحمول */
.button {
min-height: max(44px, 2.75rem);
min-width: max(44px, 2.75rem);
}
دالة max() ذات قيمة خاصة لإمكانية الوصول. يجب أن تكون أهداف اللمس على الأجهزة المحمولة على الأقل 44 في 44 بكسل وفقا لإرشادات WCAG. استخدام max(44px, 2.75rem) يضمن أن الزر كبير بما يكفي دائما للنقر المريح حتى لو حاول التخطيط المحيط تصغيره. وبالمثل max() مثالية لفرض أحجام خطوط دنيا للحفاظ على قابلية القراءة عبر الأجهزة.
دمج min() و max()
يمكنك تداخل min() وmax() لإنشاء نطاق -- قيمة تنمو أو تتقلص ضمن حدود محددة. هذا الدمج ينشئ فعليا نطاقا "مقيدا" حتى قبل أن نناقش دالة clamp(). النمط min(max-value, max(min-value, preferred-value)) يضمن أن النتيجة المحسوبة لا تكون أبدا أصغر من الحد الأدنى ولا أكبر من الحد الأقصى.
تداخل min() و max()
/* حجم الخط: على الأقل 16px وعلى الأكثر 24px ويفضل 3vw */
.text {
font-size: min(24px, max(16px, 3vw));
}
/* العرض: على الأقل 200px وعلى الأكثر 800px ويفضل 60% */
.card {
width: min(800px, max(200px, 60%));
}
/* الحشوة: بين 1rem و 4rem تتدرج مع إطار العرض */
.section {
padding: min(4rem, max(1rem, 5vw));
}
min(MAX, max(MIN, preferred)) هو بالضبط ما تفعله clamp(MIN, preferred, MAX). تم تقديم دالة clamp() تحديدا لاستبدال نمط التداخل هذا بصيغة أنظف وأكثر قابلية للقراءة. سنغطي clamp() بالتفصيل في القسم التالي.دالة clamp()
تأخذ دالة clamp() ثلاث وسائط بالضبط: قيمة دنيا وقيمة مفضلة وقيمة قصوى. يستخدم المتصفح القيمة المفضلة طالما أنها تقع بين الحد الأدنى والأقصى. إذا كانت القيمة المفضلة المحسوبة أقل من الحد الأدنى فيستخدم الحد الأدنى. وإذا كانت أكثر من الحد الأقصى فيستخدم الحد الأقصى. النتيجة هي قيمة تتدرج بمرونة ضمن نطاق محدد -- مثالية للطباعة المتجاوبة والتباعد والتحجيم.
صيغة clamp()
الصيغة هي clamp(minimum, preferred, maximum). يمكن لكل وسيط استخدام أي وحدة CSS صالحة أو تعبير. عادة ما تكون القيمة المفضلة وحدة مرنة مثل vw أو تعبير calc() بينما يكون الحد الأدنى والأقصى عادة وحدات ثابتة مثل rem أو px.
صيغة clamp() الأساسية
/* clamp(الحد الأدنى, المفضل, الحد الأقصى) */
/* حجم الخط: على الأقل 1rem ويفضل 2.5vw وعلى الأكثر 2rem */
.heading {
font-size: clamp(1rem, 2.5vw, 2rem);
}
/* العرض: على الأقل 200px ويفضل 50% وعلى الأكثر 600px */
.card {
width: clamp(200px, 50%, 600px);
}
/* الحشوة: على الأقل 1rem ويفضل 4vw وعلى الأكثر 3rem */
.section {
padding: clamp(1rem, 4vw, 3rem);
}
/* ارتفاع السطر: مرن بين قيمتين */
.paragraph {
line-height: clamp(1.4, 1.2 + 0.5vw, 1.8);
}
الطباعة المرنة مع clamp()
الاستخدام الأكثر شيوعا لـ clamp() هو الطباعة المرنة -- أحجام خطوط تتدرج بسلاسة مع عرض إطار العرض بين حجم أدنى وأقصى. قبل clamp() كان تحقيق الطباعة المرنة يتطلب صيغ calc() معقدة أو استعلامات وسائط متعددة. مع clamp() سطر واحد من CSS ينشئ نصا مرنا تماما لا يكون أبدا صغيرا جدا على المحمول ولا كبيرا جدا على سطح المكتب.
نظام الطباعة المرنة
/* مقياس نوع مرن باستخدام clamp() */
:root {
--font-sm: clamp(0.875rem, 0.8rem + 0.25vw, 1rem);
--font-base: clamp(1rem, 0.9rem + 0.5vw, 1.125rem);
--font-lg: clamp(1.25rem, 1rem + 1vw, 1.75rem);
--font-xl: clamp(1.5rem, 1rem + 2vw, 2.5rem);
--font-2xl: clamp(2rem, 1.5rem + 2.5vw, 3.5rem);
--font-3xl: clamp(2.5rem, 1.5rem + 4vw, 5rem);
}
body { font-size: var(--font-base); }
h1 { font-size: var(--font-3xl); }
h2 { font-size: var(--font-2xl); }
h3 { font-size: var(--font-xl); }
h4 { font-size: var(--font-lg); }
small { font-size: var(--font-sm); }
/* نمط الصيغة: clamp(min, preferred, max) */
/* preferred = min + (max - min) * viewport-factor */
/* مثال: لـ min 1rem و max 2rem على 320px-1200px */
/* preferred = 1rem + (2 - 1) * ((100vw - 320px) / (1200 - 320)) */
.hero-title {
font-size: clamp(1rem, calc(1rem + (2 - 1) * ((100vw - 20rem) / (75 - 20))), 2rem);
}
clamp(min-rem, calc-expression-with-vw, max-rem). للقيمة المفضلة الوسطى، إضافة مكون vw صغير إلى قاعدة rem يعمل جيدا. على سبيل المثال clamp(1rem, 0.9rem + 0.5vw, 1.25rem) ينشئ تدرجا لطيفا لنص الجسم. للعناوين التي تحتاج تدرجا أكثر دراماتيكية، زد مكون vw: clamp(2rem, 1rem + 3vw, 4rem).التباعد المرن مع clamp()
نفس التدرج المرن الذي يعمل للطباعة يعمل بشكل جميل للتباعد. بدلا من تعريف حشوة وهوامش وفجوات ثابتة تقفز بين نقاط التوقف، يمكنك استخدام clamp() لإنشاء تباعد سلس ومستمر يتكيف مع إطار العرض. هذا النهج ينتج تجربة مستخدم أكثر صقلا لأن التخطيط يتغير تدريجيا بدلا من خطوات مفاجئة.
نظام التباعد المرن
:root {
/* مقياس تباعد مرن */
--space-xs: clamp(0.25rem, 0.2rem + 0.25vw, 0.5rem);
--space-sm: clamp(0.5rem, 0.4rem + 0.5vw, 1rem);
--space-md: clamp(1rem, 0.75rem + 1vw, 1.5rem);
--space-lg: clamp(1.5rem, 1rem + 2vw, 3rem);
--space-xl: clamp(2rem, 1rem + 3vw, 5rem);
--space-2xl: clamp(3rem, 1.5rem + 5vw, 8rem);
}
/* تطبيق التباعد المرن في جميع أنحاء التخطيط */
.section {
padding-block: var(--space-xl);
padding-inline: var(--space-lg);
}
.card {
padding: var(--space-md);
margin-bottom: var(--space-lg);
}
.grid {
gap: var(--space-md);
}
.stack > * + * {
margin-top: var(--space-sm);
}
دالة var() والقيم البديلة
بينما ترتبط var() بشكل أساسي بالخصائص المخصصة، فإنها تلعب دورا مهما عند دمجها مع الدوال الرياضية. تقبل دالة var() وسيطا ثانيا اختياريا: قيمة بديلة تستخدم إذا لم تكن الخاصية المخصصة معرفة. آلية القيم البديلة هذه تجعل مكوناتك أكثر متانة وقابلية للنقل -- فهي تعمل حتى عند استخدامها خارج سياق يعرف المتغيرات المتوقعة.
var() مع القيم البديلة
/* var(--property, fallback) */
.card {
/* تعود إلى 1.5rem إذا لم تكن --card-padding معرفة */
padding: var(--card-padding, 1.5rem);
/* تعود إلى الأبيض إذا لم تكن --card-bg معرفة */
background: var(--card-bg, #ffffff);
/* القيمة البديلة يمكن أن تكون var() أخرى */
color: var(--card-text, var(--text-color, #333333));
}
/* دمج القيم البديلة لـ var() مع calc() */
.layout {
--sidebar: 250px;
/* المحتوى الرئيسي يستخدم عرض الشريط الجانبي مع بديل */
width: calc(100% - var(--sidebar, 200px));
}
/* var() داخل clamp() لقيم مرنة قابلة للتكوين */
.heading {
font-size: clamp(
var(--heading-min, 1.5rem),
var(--heading-preferred, 3vw),
var(--heading-max, 3rem)
);
}
دالة env() للمناطق الآمنة
توفر دالة env() الوصول إلى متغيرات البيئة المعرفة من قبل وكيل المستخدم. الاستخدام الأكثر شيوعا هو التعامل مع "المناطق الآمنة" على الأجهزة ذات الشاشات غير المستطيلة مثل هواتف iPhone ذات الثقب أو الجزيرة الديناميكية. متغيرات البيئة safe-area-inset-top وsafe-area-inset-right وsafe-area-inset-bottom وsafe-area-inset-left تخبرك بمقدار المساحة التي تشغلها أجزاء الجهاز.
استخدام env() للمناطق الآمنة على الأجهزة
/* مكن هوامش المنطقة الآمنة في علامة viewport أولا: */
/* <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> */
/* مراعاة الثقب في الهواتف الحديثة */
.header {
padding-top: env(safe-area-inset-top, 0px);
padding-left: env(safe-area-inset-left, 0px);
padding-right: env(safe-area-inset-right, 0px);
}
/* شريط التنقل السفلي الثابت يحترم مؤشر الصفحة الرئيسية */
.bottom-nav {
padding-bottom: env(safe-area-inset-bottom, 0px);
position: fixed;
bottom: 0;
}
/* دمج env() مع calc() لحشوة إضافية */
.bottom-nav {
padding-bottom: calc(env(safe-area-inset-bottom, 0px) + 1rem);
}
/* استخدم max() لضمان حشوة دنيا على جميع الأجهزة */
.safe-container {
padding-left: max(1rem, env(safe-area-inset-left, 0px));
padding-right: max(1rem, env(safe-area-inset-right, 0px));
}
دمج دوال متعددة
تظهر القوة الحقيقية لدوال CSS عند دمجها. يمكنك تداخل calc() داخل min() واستخدام var() داخل clamp() ودمج max() مع env() أو إنشاء أي تركيب يتطلبه تخطيطك. يحل المتصفح هذه التعبيرات المتداخلة من الداخل إلى الخارج لذا يمكنك بناء منطق متجاوب معقد في تصريح CSS واحد.
دمج الدوال لتخطيطات معقدة
/* حاوية متجاوبة مع دعم المنطقة الآمنة */
.container {
width: min(calc(100% - 2 * max(1rem, env(safe-area-inset-left, 0px))), 1200px);
margin-inline: auto;
}
/* شبكة مرنة تحترم حدا أدنى قابلا للتكوين */
.grid {
display: grid;
gap: clamp(var(--gap-min, 0.75rem), 2vw, var(--gap-max, 2rem));
grid-template-columns: repeat(
auto-fit,
minmax(min(100%, var(--col-min, 280px)), 1fr)
);
}
/* تخطيط شريط جانبي مع منطقة رئيسية مرنة */
.layout {
--sidebar-w: clamp(200px, 25vw, 350px);
display: grid;
grid-template-columns: var(--sidebar-w) calc(100% - var(--sidebar-w) - var(--gap, 1.5rem));
gap: var(--gap, 1.5rem);
}
/* بطاقة بتباعد داخلي مرن بالكامل */
.card {
padding: clamp(1rem, calc(1rem + 1vw), 2.5rem);
border-radius: min(1rem, 3vw);
font-size: clamp(0.9rem, 0.85rem + 0.25vw, 1.05rem);
}
/* قسم البطل مع تحجيم مرن معقد */
.hero {
min-height: clamp(400px, calc(100vh - var(--header-height, 64px)), 800px);
padding: max(2rem, env(safe-area-inset-top, 0px) + 1rem)
clamp(1rem, 5vw, 4rem)
max(2rem, env(safe-area-inset-bottom, 0px) + 1rem);
}
أمثلة عملية من العالم الحقيقي
دعونا نلقي نظرة على أنماط كاملة من العالم الحقيقي تجمع كل هذه الدوال معا. هذه الأمثلة توضح كيف تحل دوال CSS تحديات التخطيط اليومية بأناقة واستجابة.
شبكة بطاقات متجاوبة بدون استعلامات وسائط
شبكة بطاقات متجاوبة كاملة
:root {
--card-min: 280px;
--card-gap: clamp(1rem, 2vw, 2rem);
--card-padding: clamp(1rem, 1rem + 1vw, 2rem);
--card-radius: min(1rem, 2vw);
}
.card-grid {
display: grid;
grid-template-columns: repeat(
auto-fill,
minmax(min(100%, var(--card-min)), 1fr)
);
gap: var(--card-gap);
padding: var(--card-gap);
max-width: min(1400px, calc(100% - 2rem));
margin-inline: auto;
}
.card {
padding: var(--card-padding);
border-radius: var(--card-radius);
background: var(--bg-white, #ffffff);
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
.card__title {
font-size: clamp(1.1rem, 1rem + 0.5vw, 1.4rem);
margin-bottom: clamp(0.5rem, 0.4rem + 0.25vw, 0.75rem);
}
.card__text {
font-size: clamp(0.875rem, 0.85rem + 0.15vw, 1rem);
line-height: clamp(1.5, 1.4 + 0.2vw, 1.7);
}
تخطيط لوحة معلومات مرنة
لوحة معلومات مع شريط جانبي مرن
:root {
--sidebar-min: 200px;
--sidebar-max: 320px;
--header-h: clamp(48px, 8vh, 72px);
}
.dashboard {
display: grid;
grid-template-rows: var(--header-h) 1fr;
grid-template-columns: clamp(var(--sidebar-min), 20vw, var(--sidebar-max)) 1fr;
min-height: 100vh;
}
.dashboard__header {
grid-column: 1 / -1;
padding-inline: clamp(1rem, 3vw, 2rem);
display: flex;
align-items: center;
}
.dashboard__sidebar {
padding: clamp(0.75rem, 1.5vw, 1.5rem);
overflow-y: auto;
max-height: calc(100vh - var(--header-h));
}
.dashboard__main {
padding: clamp(1rem, 2vw, 2.5rem);
overflow-y: auto;
max-height: calc(100vh - var(--header-h));
}
دعم المتصفحات والاعتبارات
تتمتع جميع الدوال الرياضية الأربع بدعم ممتاز من المتصفحات في عام 2025. دالة calc() مدعومة منذ حوالي عام 2012 وتعمل في كل متصفح قيد الاستخدام فعليا اليوم. دوال min() وmax() وclamp() مدعومة في جميع المتصفحات الحديثة بما في ذلك Chrome 79+ و Firefox 75+ و Safari 13.1+ و Edge 79+. دالة env() مدعومة في جميع المتصفحات الحديثة أيضا على الرغم من أن متغيرات البيئة المتاحة تعتمد على الجهاز ونظام التشغيل.
clamp() لأحجام الخطوط، كن على دراية بأنها قد تنشئ مشاكل في إمكانية الوصول إذا لم يتمكن المستخدمون من تجاوز الحد الأدنى أو الأقصى بتكبير المتصفح. اختبر دائما طباعتك المرنة مع تكبير المتصفح بنسبة 200% و400% لضمان تدرج النص بشكل مناسب. استخدام وحدات rem لقيمك الدنيا والقصوى (بدلا من px) يساعد في ضمان التدرج المناسب مع تفضيلات حجم خط المستخدم.تمرين عملي
ابنِ تخطيط صفحة معرض أعمال متجاوبة باستخدام دوال CSS فقط -- بدون استعلامات وسائط. أنشئ ملف CSS بالمتطلبات التالية: (1) عرف نظام خصائص مخصصة مع خمسة متغيرات تباعد على الأقل وثلاثة متغيرات حجم خط، كلها تستخدم clamp() للتدرج المرن. (2) أنشئ رأسا متجاوبا مع منطقة شعار وتنقل. استخدم max() لضمان ألا تنخفض حشوة الرأس تحت 1rem وmin() لتحديد عرض الشعار بـ 200px. (3) ابنِ شبكة بطاقات باستخدام CSS Grid مع auto-fill وminmax(min(100%, 300px), 1fr) حتى تكون البطاقات متجاوبة بدون نقاط توقف. استخدم متغيرات التباعد للفجوة والحشوة. (4) أنشئ تخطيط شريط جانبي حيث يستخدم عرض الشريط الجانبي clamp(180px, 20vw, 300px) والمحتوى الرئيسي يملأ المساحة المتبقية باستخدام calc(100% - sidebar - gap). (5) أضف قسم بطل مع min-height: clamp(300px, 50vh, 600px) وطباعة مرنة باستخدام متغيرات حجم الخط. (6) استخدم هوامش المنطقة الآمنة env() على حشوة الحاوية الخارجية. (7) تأكد من أن جميع أحجام الخطوط تستخدم rem في القيم الدنيا والقصوى لاحترام إعدادات تكبير المستخدم. اختبر بتغيير حجم نافذة المتصفح من 320px إلى 1920px وتحقق من أن كل عنصر يتدرج بسلاسة بدون قفزات.