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

الوحدات والقيم: px و em و rem و % و vw و vh

45 دقيقة الدرس 18 من 60

لماذا تهم الوحدات في CSS

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

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

الوحدات المطلقة

الوحدات المطلقة لها حجم ثابت لا يتغير بناءً على أي عنصر أو إعداد آخر. تُسمى "مطلقة" لأنها تتوافق مع قياسات العالم الحقيقي (مع استثناء واحد: البكسل).

  • px (بكسل) -- الوحدة المطلقة الأكثر شيوعاً. في CSS، البكسل ليس بالضرورة بكسل شاشة فعلي. إنه "بكسل مرجعي" يُعرَّف على أنه 1/96 من البوصة. على الشاشات عالية الكثافة (Retina)، قد يتوافق بكسل CSS واحد مع 2 أو أكثر من البكسلات الفعلية. رغم كونه مطلقاً، يتدرج البكسل مع تكبير المتصفح.
  • cm (سنتيمتر) -- سنتيمتر واحد. نادراً ما يُستخدم في تصميم الويب لكنه مفيد لأنماط الطباعة.
  • mm (مليمتر) -- مليمتر واحد. مثل cm، يُستخدم أساساً للطباعة.
  • in (بوصة) -- بوصة واحدة، تساوي 96 بكسل أو 2.54 سم. يُستخدم لأنماط الطباعة.
  • pt (نقطة) -- نقطة واحدة، تساوي 1/72 من البوصة. وحدة طباعية تقليدية، شائعة في الطباعة لكنها نادراً ما تُستخدم على الويب.
  • pc (بايكا) -- بايكا واحدة، تساوي 12 نقطة أو 1/6 من البوصة. وحدة طباعة تقليدية أخرى.

مثال: الوحدات المطلقة في التطبيق العملي

/* px -- الوحدة المطلقة الأساسية */
.border-example {
    border: 1px solid #333;
    border-radius: 4px;
    padding: 16px;
}

/* الوحدات الفيزيائية لأنماط الطباعة */
@media print {
    .page {
        width: 21cm;       /* عرض A4 */
        height: 29.7cm;    /* ارتفاع A4 */
        margin: 2cm;
        font-size: 12pt;   /* حجم خط الطباعة القياسي */
    }

    h1 {
        font-size: 24pt;
    }

    .sidebar {
        width: 2in;
    }
}

/* مقارنة الوحدات المطلقة */
.absolute-comparison {
    /* كل هذه متساوية */
    width: 96px;    /* 96 بكسل */
    width: 1in;     /* 1 بوصة = 96 بكسل */
    width: 2.54cm;  /* 2.54 سم = 1 بوصة */
    width: 25.4mm;  /* 25.4 مم = 1 بوصة */
    width: 72pt;    /* 72 نقطة = 1 بوصة */
    width: 6pc;     /* 6 بايكا = 1 بوصة */
}
ملاحظة: على شاشات العرض، لا يتم عرض الوحدات الفيزيائية مثل cm و mm و in بدقة. يحسبها المتصفح بناءً على افتراض أن 1 بوصة تساوي 96 بكسل CSS، وهو ليس دقيقاً فعلياً على معظم الشاشات. استخدم الوحدات الفيزيائية فقط في أنماط @media print حيث تتوافق مع الأبعاد المطبوعة الفعلية.

الوحدات النسبية: em

وحدة em نسبية لـ حجم خط العنصر نفسه (أو عنصره الأب، لخاصية font-size). هذا يجعلها وحدة قوية لإنشاء مكونات تتدرج بشكل متناسب. ومع ذلك، فإن الطبيعة التراكمية لـ em يمكن أن تجعل التعامل معها صعباً في الهياكل المتداخلة بعمق.

كيف تعمل em مع font-size

عند استخدامها لخاصية font-size، تكون em نسبية لـ حجم خط العنصر الأب. إذا كان للأب حجم خط 16 بكسل وعيّنت الابن إلى 1.5em، فسيكون حجم خط الابن 24 بكسل (16 * 1.5).

كيف تعمل em مع الخصائص الأخرى

عند استخدامها لأي خاصية غير font-size -- مثل padding أو margin أو width أو line-height -- تكون em نسبية لـ حجم الخط المحسوب للعنصر نفسه.

مثال: كيف تتصرف em

/* الأب لديه حجم خط 16 بكسل (افتراضي المتصفح) */
.parent {
    font-size: 16px;
}

/* حجم خط الابن: 1.5em = 16px * 1.5 = 24px */
/* حشوة الابن: 1em = 24px (نسبية لحجم خط العنصر نفسه) */
.child {
    font-size: 1.5em;   /* 24 بكسل */
    padding: 1em;        /* 24 بكسل -- نسبية لحجم خط العنصر نفسه */
    margin-bottom: 0.5em; /* 12 بكسل */
}

/* مشكلة التراكم مع em المتداخلة */
.level-1 { font-size: 1.2em; }   /* 16 * 1.2 = 19.2 بكسل */
.level-2 { font-size: 1.2em; }   /* 19.2 * 1.2 = 23.04 بكسل */
.level-3 { font-size: 1.2em; }   /* 23.04 * 1.2 = 27.65 بكسل */
.level-4 { font-size: 1.2em; }   /* 27.65 * 1.2 = 33.18 بكسل */

/* كل مستوى يصبح أكبر وأكبر -- هذه مشكلة تراكم em */
تحذير: سلوك التراكم لـ em في أحجام الخطوط هو أحد أكثر الأخطاء شيوعاً في CSS. عندما تُداخل عناصر يحدد كل منها حجم خطه بـ em، تتضاعف الأحجام في كل مستوى. يمكن أن يؤدي هذا إلى نص كبير أو صغير بشكل غير متوقع في الهياكل المتداخلة بعمق. استخدم rem لأحجام الخطوط لتجنب هذه المشكلة.

متى تكون em مفيدة

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

مثال: em للمكونات القابلة للتدرج

/* زر يتدرج بشكل متناسب مع حجم خطه */
.button {
    font-size: 1rem;     /* الحجم الأساسي من الجذر */
    padding: 0.5em 1em;  /* يتدرج مع حجم خط هذا الزر */
    border-radius: 0.25em;
    border: 0.0625em solid currentColor;
}

/* متغير صغير -- فقط غيّر font-size والمسافات تتكيف */
.button--small {
    font-size: 0.875rem;
    /* الحشوة ونصف قطر الحد والحد كلها تتقلص تلقائياً */
}

/* متغير كبير */
.button--large {
    font-size: 1.25rem;
    /* الحشوة ونصف قطر الحد والحد كلها تتوسع تلقائياً */
}

/* شارة تتدرج مع النص */
.badge {
    display: inline-block;
    font-size: 0.75rem;
    padding: 0.25em 0.5em;
    border-radius: 1em;
    background: #6366f1;
    color: white;
}

الوحدات النسبية: rem

وحدة rem تعني "em الجذر" وهي دائماً نسبية لـ حجم خط العنصر الجذري (عنصر <html>). على عكس em، لا تتراكم rem -- بغض النظر عن مدى عمق تداخل العنصر، 1rem تساوي دائماً نفس القيمة.

افتراضياً، تحدد معظم المتصفحات حجم الخط الجذري إلى 16 بكسل. إذن 1rem = 16px و 0.5rem = 8px و 2rem = 32px. يمكن تغيير هذا الافتراضي بتعيين font-size على عنصر html.

مثال: rem دائماً نسبية للجذر

/* افتراضي: حجم خط html هو 16 بكسل */
html {
    font-size: 16px;
}

/* بغض النظر عن عمق التداخل، rem تعتمد دائماً على 16 بكسل */
.level-1 { font-size: 1.2rem; }   /* 16 * 1.2 = 19.2 بكسل */
.level-2 { font-size: 1.2rem; }   /* 16 * 1.2 = 19.2 بكسل -- نفسها! */
.level-3 { font-size: 1.2rem; }   /* 16 * 1.2 = 19.2 بكسل -- نفسها! */

/* أحجام يمكن التنبؤ بها في كل المستند */
h1 { font-size: 2.5rem; }     /* 40 بكسل */
h2 { font-size: 2rem; }       /* 32 بكسل */
h3 { font-size: 1.5rem; }     /* 24 بكسل */
p  { font-size: 1rem; }       /* 16 بكسل */
small { font-size: 0.875rem; } /* 14 بكسل */

/* المسافات بـ rem */
.section {
    padding: 2rem;        /* 32 بكسل */
    margin-bottom: 3rem;  /* 48 بكسل */
}

.card {
    padding: 1.5rem;      /* 24 بكسل */
    gap: 1rem;            /* 16 بكسل */
}

حيلة حجم الخط 62.5%

تقنية شائعة هي تعيين حجم الخط الجذري إلى 62.5% من القيمة الافتراضية للمتصفح. بما أن القيمة الافتراضية هي 16 بكسل، فإن 62.5% تساوي 10 بكسل. هذا يجعل حسابات rem أسهل بكثير لأن 1rem = 10px، إذن 1.6rem = 16px و 2.4rem = 24px وهكذا.

مثال: حيلة 62.5%

/* تعيين حجم الخط الجذري إلى 10 بكسل (62.5% من 16 بكسل) */
html {
    font-size: 62.5%;
}

/* الآن قيم rem تتوافق مباشرة مع قيم البكسل / 10 */
body {
    font-size: 1.6rem;    /* 16 بكسل */
    line-height: 1.5;
}

h1 { font-size: 3.2rem; }     /* 32 بكسل */
h2 { font-size: 2.4rem; }     /* 24 بكسل */
h3 { font-size: 2rem; }       /* 20 بكسل */
h4 { font-size: 1.8rem; }     /* 18 بكسل */
p  { font-size: 1.6rem; }     /* 16 بكسل */
small { font-size: 1.4rem; }  /* 14 بكسل */

.container {
    max-width: 120rem;   /* 1200 بكسل */
    padding: 2rem;       /* 20 بكسل */
}

.card {
    padding: 2.4rem;     /* 24 بكسل */
    border-radius: 0.8rem; /* 8 بكسل */
    margin-bottom: 1.6rem; /* 16 بكسل */
}
نصيحة: حيلة 62.5% تجعل الحساب الذهني أسهل بكثير، لكنها تتطلب منك تعيين font-size صراحة على عنصر body (عادةً 1.6rem) لاستعادة أحجام النص المقروءة. بعض المطورين لا يحبون هذا النهج لأنه يعني أن كل تعريف font-size يجب أن يستخدم rem. البديل هو الاحتفاظ بالقاعدة الافتراضية 16 بكسل واستخدام مرجع تحويل (مثلاً، 1rem = 16px و 0.875rem = 14px).
تحذير: لا تعيّن أبداً حجم الخط الجذري إلى قيمة بكسل ثابتة مثل html { font-size: 10px; }. هذا يتجاوز تفضيل حجم خط متصفح المستخدم، وهو مشكلة في إمكانية الوصول. المستخدمون الذين زادوا حجم الخط الافتراضي في متصفحهم (لأسباب تتعلق بالقراءة) سيتم تجاهل تفضيلهم. استخدم دائماً نسبة مئوية مثل 62.5% أو 100% ليحترم الحجم الأساسي إعداد المستخدم.

وحدات النسبة المئوية

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

  • width و max-width: نسبية لـ عرض العنصر الأب.
  • height و max-height: نسبية لـ ارتفاع العنصر الأب. مهم: يجب أن يكون للأب ارتفاع محدد لكي يعمل هذا.
  • padding و margin: دائماً نسبية لـ عرض العنصر الأب -- حتى للحشوة والهامش العلوي والسفلي. هذا مصدر شائع للارتباك.
  • font-size: نسبية لـ حجم خط العنصر الأب.
  • line-height: نسبية لـ حجم خط العنصر نفسه.
  • transform: translate(): نسبية لـ أبعاد العنصر نفسه.
  • top و right و bottom و left (العناصر المتموضعة): نسبية لـ أبعاد الكتلة الحاوية.

مثال: ما هي النسب المئوية نسبية له

/* الأب عرضه 800 بكسل */
.parent {
    width: 800px;
    height: 600px;
}

/* width: 50% = 400 بكسل (50% من عرض الأب) */
/* height: 50% = 300 بكسل (50% من ارتفاع الأب) */
/* padding: 5% = 40 بكسل على كل الجوانب (5% من عرض الأب وليس ارتفاعه!) */
.child {
    width: 50%;
    height: 50%;
    padding: 5%;    /* 40 بكسل على كل الجوانب الأربعة */
}

/* إنشاء مربع مثالي بحيلة الحشوة */
/* بما أن padding-top/bottom تستخدم عرض الأب، يمكننا إنشاء
   نسب أبعاد بدون خاصية aspect-ratio */
.square {
    width: 50%;
    padding-bottom: 50%;  /* نفس العرض، مما ينشئ مربعاً */
    height: 0;
}

/* حاوية بنسبة أبعاد 16:9 */
.widescreen {
    width: 100%;
    padding-bottom: 56.25%;  /* 9/16 = 0.5625 = 56.25% */
    height: 0;
    position: relative;
}

.widescreen-content {
    position: absolute;
    inset: 0;
}

/* النهج الحديث: استخدم aspect-ratio بدلاً من ذلك */
.modern-widescreen {
    width: 100%;
    aspect-ratio: 16 / 9;
}
ملاحظة: حقيقة أن الحشوة والهامش العمودي نسبية لـ عرض الأب (وليس ارتفاعه) مقصودة في مواصفات CSS. إنها تضمن حشوة متسقة حول العنصر بغض النظر عن البُعد. استُخدم هذا السلوك تاريخياً أيضاً لإنشاء صناديق نسب الأبعاد قبل وجود خاصية aspect-ratio.

وحدات إطار العرض

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

وحدات إطار العرض الكلاسيكية

  • vw (عرض إطار العرض) -- 1vw تساوي 1% من عرض إطار العرض. 100vw تمتد على كامل عرض إطار العرض.
  • vh (ارتفاع إطار العرض) -- 1vh تساوي 1% من ارتفاع إطار العرض. 100vh تمتد على كامل ارتفاع إطار العرض.
  • vmin -- 1vmin تساوي 1% من البُعد الأصغر لإطار العرض (العرض أو الارتفاع، أيهما أقل).
  • vmax -- 1vmax تساوي 1% من البُعد الأكبر لإطار العرض (العرض أو الارتفاع، أيهما أكبر).

مثال: وحدات إطار العرض في العمل

/* قسم بطل بملء الشاشة */
.hero {
    width: 100vw;
    height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* حجم خط متجاوب يتدرج مع إطار العرض */
.hero-title {
    font-size: 5vw;  /* يصبح أكبر على الشاشات الأعرض */
}

/* vmin لعناصر مربعة تتناسب مع أي اتجاه */
.profile-photo {
    width: 30vmin;
    height: 30vmin;
    border-radius: 50%;
    /* على إطار عرض 1200x800: 30% من 800 = 240 بكسل */
    /* على إطار عرض 800x1200: 30% من 800 = 240 بكسل (نفسها!) */
}

/* vmax لعناصر تملأ البُعد الأكبر */
.background-decoration {
    width: 50vmax;
    height: 50vmax;
}

/* عنصر بعرض كامل يخرج من حاويته */
.full-width {
    width: 100vw;
    margin-left: calc(-50vw + 50%);
}

وحدات إطار العرض الديناميكية (dvh و svh و lvh)

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

  • svh و svw (إطار العرض الصغير) -- بناءً على حجم إطار العرض عندما تكون واجهة المتصفح (شريط العنوان، أشرطة الأدوات) موسعة ومرئية بالكامل. هذا أصغر حجم سيكون عليه إطار العرض.
  • lvh و lvw (إطار العرض الكبير) -- بناءً على حجم إطار العرض عندما تكون واجهة المتصفح مطوية ومخفية بالكامل. هذا أكبر حجم سيكون عليه إطار العرض.
  • dvh و dvw (إطار العرض الديناميكي) -- يتكيف ديناميكياً مع حجم إطار العرض الحالي، يتغير في الوقت الفعلي مع ظهور واختفاء واجهة المتصفح.

مثال: وحدات إطار العرض الديناميكية للهاتف المحمول

/* قسم بطل يملأ المنطقة المرئية بشكل مثالي على الهاتف */
.hero {
    min-height: 100dvh;  /* يتكيف ديناميكياً مع واجهة المتصفح */
}

/* احتياطي للمتصفحات التي لا تدعم dvh */
.hero-with-fallback {
    min-height: 100vh;   /* احتياطي */
    min-height: 100dvh;  /* تجاوز إذا كان مدعوماً */
}

/* إطار العرض الصغير -- مضمون ألا يُقص أبداً */
.sticky-footer {
    min-height: 100svh;
}

/* إطار العرض الكبير -- يستخدم أقصى مساحة متاحة */
.full-background {
    min-height: 100lvh;
}

/* استخدام وحدات إطار العرض الديناميكية لعنصر شبه ثابت */
.bottom-bar {
    position: fixed;
    bottom: 0;
    left: 0;
    width: 100dvw;
    padding: 1rem;
}
نصيحة: للتصاميم التي تبدأ بالهاتف المحمول، فضّل dvh على vh للأقسام بملء الشاشة. 100vh الكلاسيكية على Safari للهاتف تنشئ منطقة أطول من إطار العرض المرئي (لأنها تستخدم حجم إطار العرض الكبير)، مما يتسبب في إخفاء المحتوى خلف شريط العنوان. استخدام 100dvh يحل هذه المشكلة. أضف دائماً vh كاحتياطي للمتصفحات القديمة.

دالة calc()

دالة calc() تسمح لك بإجراء حسابات رياضية مع وحدات مختلطة. هذه واحدة من أقوى الميزات في CSS لأنها تتيح لك الجمع بين الوحدات المطلقة والنسبية في تعبير واحد.

مثال: calc() مع وحدات مختلطة

/* العرض الكامل ناقص شريط جانبي ثابت */
.main-content {
    width: calc(100% - 280px);
}

/* توسيط عنصر بعرض معروف */
.centered {
    width: 800px;
    margin-left: calc(50% - 400px);
}

/* حجم خط متجاوب مع حدود دنيا وقصوى */
.responsive-text {
    /* أساسي 16 بكسل + 1% من عرض إطار العرض */
    font-size: calc(1rem + 1vw);
}

/* تعبيرات calc متداخلة */
.complex-layout {
    padding: calc(2rem + 5%);
    width: calc(100vw - (2 * 2rem) - 280px);
    /* 100% إطار عرض - الحشوة اليسرى واليمنى - الشريط الجانبي */
}

/* شبكة بفجوات ثابتة وأعمدة مرنة */
.grid-3-col {
    display: grid;
    gap: 24px;
    grid-template-columns: repeat(3, calc((100% - 48px) / 3));
}

/* الجمع بين rem ووحدات إطار العرض للطباعة المرنة */
h1 {
    font-size: calc(1.5rem + 2vw);
    /* عند إطار عرض 320 بكسل: 1.5rem + 6.4 بكسل ~ 30.4 بكسل */
    /* عند إطار عرض 1200 بكسل: 1.5rem + 24 بكسل = 48 بكسل */
}

/* استخدام calc مع خصائص CSS المخصصة */
:root {
    --sidebar-width: 280px;
    --header-height: 64px;
    --padding: 2rem;
}

.content-area {
    width: calc(100% - var(--sidebar-width));
    height: calc(100vh - var(--header-height));
    padding: var(--padding);
}
ملاحظة: داخل calc()، يجب أن يكون لمعاملي + و - مسافات بيضاء على كلا الجانبين. calc(100% -20px) غير صالحة -- يجب أن تكون calc(100% - 20px). معاملا * و / لا يتطلبان مسافات بيضاء لكن إضافتها تحسن القراءة.

وحدتا ch و ex

يتضمن CSS وحدتين نسبيتين خاصتين بالطباعة أقل شيوعاً لكنهما قيمتان في حالات محددة:

  • ch (حرف) -- تساوي عرض حرف "0" (صفر) في الخط الحالي. مفيدة لتحديد العروض بناءً على عدد الأحرف، مثل تقييد طول السطر للقراءة.
  • ex -- تساوي ارتفاع x في الخط الحالي (تقريباً ارتفاع حرف "x" صغير). مفيدة للتعديلات الطباعية الدقيقة.

مثال: وحدتا ch و ex

/* طول السطر الأمثل للقراءة (45-75 حرفاً) */
.prose {
    max-width: 65ch;
    margin: 0 auto;
}

/* حقل إدخال نصي يتسع لحوالي 20 حرفاً */
.input-short {
    width: 20ch;
}

/* المسافة العمودية نسبية لارتفاع x */
.superscript {
    vertical-align: 1ex;
    font-size: 0.75em;
}

/* مسافة بادئة للفقرة بناءً على عرض الحرف */
.indented {
    text-indent: 4ch;
}

/* كتلة كود أحادية المسافة بعرض حرف ثابت */
.code-line {
    max-width: 80ch;   /* عرض الطرفية الكلاسيكي */
    font-family: monospace;
    overflow-x: auto;
}
نصيحة: وحدة ch مفيدة بشكل خاص لتحديد max-width لحاويات النص. تظهر الأبحاث أن أطوال الأسطر من 45 إلى 75 حرفاً هي المثلى للقراءة. تعيين max-width: 65ch ينشئ تجربة قراءة مثالية بغض النظر عن حجم الخط.

جدول مقارنة جميع وحدات CSS

إليك مقارنة شاملة لجميع وحدات CSS لمساعدتك في اختيار الوحدة الصحيحة لكل حالة:

  • px -- مطلقة. نسبية لـ: لا شيء (1/96 من البوصة). الأفضل لـ: الحدود والظلال والتفاصيل الدقيقة. متجاوبة: تتدرج مع التكبير فقط.
  • em -- نسبية. نسبية لـ: حجم خط الأب (لـ font-size) أو حجم الخط الخاص (للخصائص الأخرى). الأفضل لـ: مسافات المكونات والحشوة والهوامش التي يجب أن تتدرج مع النص. متجاوبة: نعم، لكنها تتراكم في العناصر المتداخلة.
  • rem -- نسبية. نسبية لـ: حجم خط العنصر الجذري. الأفضل لـ: أحجام الخطوط والمسافات العامة وأبعاد التخطيط. متجاوبة: نعم، يمكن التنبؤ بها، لا تراكم.
  • % -- نسبية. نسبية لـ: يعتمد على الخاصية (عادةً الأب). الأفضل لـ: العروض المرنة والتخطيطات المرنة. متجاوبة: نعم.
  • vw -- نسبية. نسبية لـ: 1% من عرض إطار العرض. الأفضل لـ: العناصر بالعرض الكامل والطباعة المتجاوبة. متجاوبة: نعم.
  • vh -- نسبية. نسبية لـ: 1% من ارتفاع إطار العرض. الأفضل لـ: الأقسام بالارتفاع الكامل ومناطق البطل. متجاوبة: نعم (استخدم dvh للهاتف).
  • dvh/dvw -- نسبية. نسبية لـ: أبعاد إطار العرض الديناميكية. الأفضل لـ: تخطيطات ملء الشاشة الصديقة للهاتف. متجاوبة: نعم، تتكيف مع واجهة المتصفح.
  • svh/svw -- نسبية. نسبية لـ: أبعاد إطار العرض الصغير. الأفضل لـ: ضمان عدم إخفاء المحتوى خلف واجهة متصفح الهاتف. متجاوبة: نعم.
  • lvh/lvw -- نسبية. نسبية لـ: أبعاد إطار العرض الكبير. الأفضل لـ: الخلفيات والعناصر غير الحرجة. متجاوبة: نعم.
  • vmin -- نسبية. نسبية لـ: البُعد الأصغر لإطار العرض. الأفضل لـ: العناصر التي يجب أن تتدرج مع المحور الأصغر. متجاوبة: نعم.
  • vmax -- نسبية. نسبية لـ: البُعد الأكبر لإطار العرض. الأفضل لـ: العناصر التي يجب أن تتدرج مع المحور الأكبر. متجاوبة: نعم.
  • ch -- نسبية. نسبية لـ: عرض حرف "0". الأفضل لـ: عروض حاويات النص وحقول الإدخال. متجاوبة: تتدرج مع الخط.
  • ex -- نسبية. نسبية لـ: ارتفاع x في الخط. الأفضل لـ: التعديلات الطباعية الدقيقة. متجاوبة: تتدرج مع الخط.
  • cm و mm و in و pt و pc -- مطلقة. نسبية لـ: القياسات الفيزيائية. الأفضل لـ: أنماط الطباعة فقط. متجاوبة: لا.

متى تستخدم أي وحدة

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

أحجام الخطوط: استخدم rem

استخدم دائماً rem لأحجام الخطوط. هذا يضمن أحجاماً متسقة عبر مستندك بالكامل ويحترم تفضيل حجم خط متصفح المستخدم. تجنب em لأحجام الخطوط بسبب مشكلة التراكم. تجنب px لأنه لا يحترم إعدادات إمكانية الوصول للمستخدم.

المسافات الداخلية للمكون: استخدم em

للحشوة والهامش ونصف قطر الحد داخل المكون (مثل زر أو بطاقة)، استخدم em. هذا يجعل المسافات تتدرج بشكل متناسب عندما تغير حجم خط المكون. الزر الكبير مع نص أكبر سيحصل تلقائياً على حشوة أكبر.

مسافات التخطيط: استخدم rem

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

العروض: استخدم % أو وحدات إطار العرض

للتخطيطات المرنة، استخدم النسب المئوية للعروض. للعناصر بملء إطار العرض، استخدم vw. للحاويات، استخدم max-width بقيمة rem أو px مع width: 100% للسلوك المرن حتى حد أقصى.

الارتفاعات: استخدم المبني على المحتوى أو dvh

تجنب تعيين ارتفاعات ثابتة عندما يكون ذلك ممكناً -- دع المحتوى يحدد الارتفاع. للأقسام بملء الشاشة، استخدم min-height: 100dvh (مع احتياطي vh). للحاويات القابلة للتمرير، الارتفاع الثابت بـ rem أو px مقبول.

الحدود والظلال: استخدم px

للحدود الرفيعة (1 بكسل، 2 بكسل) وظلال الصندوق وعروض الخطوط الخارجية، استخدم px. هذه التفاصيل الدقيقة لا تحتاج للتدرج مع حجم الخط -- حد 1 بكسل يجب أن يبقى 1 بكسل بغض النظر عن حجم النص.

مثال: أفضل الممارسات المطبقة

/* إعداد الجذر */
html {
    font-size: 100%;  /* يحترم تفضيل المستخدم (عادةً 16 بكسل) */
}

/* الطباعة -- كلها rem */
body { font-size: 1rem; }
h1 { font-size: 2.5rem; }
h2 { font-size: 2rem; }
h3 { font-size: 1.5rem; }
small { font-size: 0.875rem; }

/* مسافات التخطيط -- rem */
.section {
    padding: 4rem 0;
    margin-bottom: 2rem;
}

/* الحاوية -- max-width بـ rem والعرض بـ % */
.container {
    width: 100%;
    max-width: 75rem;   /* 1200 بكسل */
    margin: 0 auto;
    padding: 0 1.5rem;
}

/* المكون (زر) -- em للمسافات الداخلية */
.button {
    font-size: 1rem;
    padding: 0.625em 1.25em;
    border: 1px solid currentColor;  /* px للحدود */
    border-radius: 0.25em;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);  /* px للظلال */
}

/* تخطيط الشبكة -- % للأعمدة */
.grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr));
    gap: 1.5rem;
}

/* قسم البطل -- وحدات إطار العرض */
.hero {
    min-height: 100vh;
    min-height: 100dvh;
    display: flex;
    align-items: center;
    padding: 2rem;
}

/* طباعة مرنة مع clamp */
.hero-title {
    font-size: clamp(2rem, 5vw, 4rem);
    /* الحد الأدنى: 2rem (32 بكسل) */
    /* المفضل: 5vw (يتدرج مع إطار العرض) */
    /* الحد الأقصى: 4rem (64 بكسل) */
}

/* مكون البطاقة */
.card {
    padding: 1.5rem;
    border: 1px solid #e5e7eb;
    border-radius: 0.5rem;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}

/* عرض نص مقروء */
.prose {
    max-width: 65ch;
    line-height: 1.7;
}

الطباعة المرنة مع clamp()

دالة clamp() نقلة نوعية للطباعة المتجاوبة. تأخذ ثلاث قيم: حد أدنى وقيمة مفضلة وحد أقصى. يستخدم المتصفح القيمة المفضلة طالما بقيت بين الحد الأدنى والأقصى. هذا يزيل الحاجة لاستعلامات الوسائط فقط لتعديل أحجام الخطوط.

مثال: نظام طباعة مرن

/* سلم خطوط مرن -- بدون استعلامات وسائط */
:root {
    --font-xs: clamp(0.75rem, 0.7rem + 0.25vw, 0.875rem);
    --font-sm: clamp(0.875rem, 0.8rem + 0.375vw, 1rem);
    --font-base: clamp(1rem, 0.9rem + 0.5vw, 1.125rem);
    --font-lg: clamp(1.125rem, 1rem + 0.625vw, 1.375rem);
    --font-xl: clamp(1.25rem, 1rem + 1.25vw, 2rem);
    --font-2xl: clamp(1.5rem, 1rem + 2.5vw, 3rem);
    --font-3xl: clamp(2rem, 1.5rem + 2.5vw, 4rem);
}

/* تطبيق سلم الخطوط المرن */
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); }
.caption { font-size: var(--font-xs); }

/* مسافات مرنة تتوافق مع سلم الخطوط */
:root {
    --space-xs: clamp(0.25rem, 0.2rem + 0.25vw, 0.5rem);
    --space-sm: clamp(0.5rem, 0.4rem + 0.5vw, 0.75rem);
    --space-md: clamp(1rem, 0.8rem + 1vw, 1.5rem);
    --space-lg: clamp(1.5rem, 1rem + 2.5vw, 3rem);
    --space-xl: clamp(2rem, 1.5rem + 2.5vw, 4rem);
    --space-2xl: clamp(3rem, 2rem + 5vw, 6rem);
}

em مقابل rem: مقارنة عملية

فهم متى تستخدم em مقابل rem مهارة حاسمة. إليك مقارنة عملية جنباً إلى جنب توضح لماذا يُفضل كل وحدة لخصائص مختلفة:

مثال: em مقابل rem جنباً إلى جنب

/* النهج 1: كله rem -- متسق لكن صلب */
.card-rem {
    font-size: 1rem;        /* 16 بكسل */
    padding: 1.5rem;        /* دائماً 24 بكسل بغض النظر عن حجم خط البطاقة */
    margin-bottom: 1rem;    /* دائماً 16 بكسل */
    border-radius: 0.5rem;  /* دائماً 8 بكسل */
}

/* إذا أنشأت بطاقة كبيرة، المسافات لا تتدرج */
.card-rem--large {
    font-size: 1.25rem;     /* 20 بكسل */
    padding: 1.5rem;        /* لا تزال 24 بكسل -- تشعر بالضيق نسبة للنص الأكبر */
    /* يجب زيادة الحشوة يدوياً أيضاً */
}

/* النهج 2: em لمسافات المكون -- يتدرج تلقائياً */
.card-em {
    font-size: 1rem;        /* 16 بكسل */
    padding: 1.5em;         /* 24 بكسل -- يتدرج مع حجم الخط */
    margin-bottom: 1em;     /* 16 بكسل -- يتدرج مع حجم الخط */
    border-radius: 0.5em;   /* 8 بكسل -- يتدرج مع حجم الخط */
}

/* البطاقة الكبيرة تحصل تلقائياً على مسافات متناسبة */
.card-em--large {
    font-size: 1.25rem;     /* 20 بكسل */
    /* الحشوة تصبح تلقائياً 30 بكسل (1.5 * 20) */
    /* الهامش يصبح تلقائياً 20 بكسل (1 * 20) */
    /* نصف قطر الحد يصبح تلقائياً 10 بكسل (0.5 * 20) */
}

/* أفضل نهج: rem لـ font-size و em لمسافات المكون */
.card-best {
    font-size: 1rem;           /* rem -- يمكن التنبؤ به، لا تراكم */
    padding: 1.5em;            /* em -- يتدرج مع حجم خط هذه البطاقة */
    margin-bottom: 1rem;       /* rem -- مسافات عامة متسقة */
    border-radius: 0.5em;      /* em -- يتدرج مع البطاقة */
    border: 1px solid #ccc;    /* px -- تفاصيل دقيقة */
}

.card-best--large {
    font-size: 1.25rem;        /* فقط غيّر font-size */
    /* المسافات الداخلية تتدرج تلقائياً عبر em */
    /* المسافات العامة تبقى متسقة عبر rem */
}

الأخطاء الشائعة وكيفية تجنبها

إليك أكثر الأخطاء شيوعاً التي يرتكبها المطورون مع وحدات CSS وكيفية تجنبها:

  • استخدام px لـ font-size: هذا يتجاهل تفضيلات إمكانية الوصول للمستخدم. المستخدمون الذين يعيّنون افتراضي متصفحهم إلى 20 بكسل أو 24 بكسل لن يروا نصك يتدرج. استخدم دائماً rem لأحجام الخطوط.
  • استخدام em لـ font-size في العناصر المتداخلة: تأثير التراكم يجعل النص غير قابل للتنبؤ. حجم خط 1.2em بعمق ثلاثة مستويات يصبح 1.728em نسبة للجذر (1.2 * 1.2 * 1.2). استخدم rem بدلاً من ذلك.
  • تعيين حجم خط html بـ px: html { font-size: 10px; } يكسر إمكانية الوصول. استخدم html { font-size: 62.5%; } بدلاً من ذلك، مما يحقق نفس قاعدة 10 بكسل مع احترام إعدادات المستخدم.
  • استخدام 100vh على الهاتف: على iOS Safari، 100vh أكبر من إطار العرض المرئي عندما يكون شريط العنوان ظاهراً. استخدم 100dvh مع احتياطي vh.
  • نسيان مسافات calc(): calc(100%-20px) غير صالحة. علامة - تحتاج مسافات: calc(100% - 20px).
  • استخدام vw لـ font-size بدون حدود: font-size: 5vw ستكون صغيرة جداً على الشاشات الصغيرة وضخمة على الشاشات الكبيرة. استخدم دائماً clamp() لتحديد الحدود.
  • افتراض أن 100vw تساوي العرض المرئي: 100vw تتضمن عرض شريط التمرير على متصفحات Windows. يمكن أن يتسبب هذا في ظهور شريط تمرير أفقي. استخدم width: 100% على body أو حاوية بدلاً من ذلك.

تمرين 1: بناء نظام طباعة متجاوب

أنشئ نظام طباعة متجاوب كامل لموقع ويب. ابدأ بتعيين حجم الخط الجذري إلى 100% لاحترام تفضيلات المستخدم. عرّف خصائص CSS مخصصة لسلم خطوط باستخدام clamp() بـ 6 أحجام على الأقل (من الصغير جداً إلى عنوان 1). كل حجم يجب أن يتدرج بسلاسة بين قيمة rem دنيا وقيمة rem قصوى، باستخدام vw كقيمة وسطى مفضلة. ثم أنشئ أصناف مساعدة لكل حجم (.text-xs و .text-sm و .text-base و .text-lg و .text-xl و .text-2xl). أنشئ أيضاً صنف حاوية يستخدم max-width بـ rem مع width: 100% وحشوة أفقية بـ rem. أخيراً، أنشئ صنف نثر مع max-width: 65ch لعرض قراءة مثالي. اختبر بتغيير حجم الخط الافتراضي للمتصفح والتحقق من أن كل النص يتدرج بشكل متناسب.

تمرين 2: مكون زر قابل للتدرج

ابنِ نظام مكون أزرار يوضح الاستخدام الصحيح لـ em و rem معاً. أنشئ صنف .btn أساسي مع font-size بـ rem و padding بـ em و border-radius بـ em و border بـ px. ثم أنشئ ثلاثة متغيرات حجم: .btn--sm و .btn--md و .btn--lg تغيّر فقط خاصية font-size. لأن المسافات تستخدم em، يجب أن تتدرج الحشوة ونصف قطر الحد والتناسب العام تلقائياً. أنشئ صفحة عرض توضيحي تعرض الأحجام الثلاثة جنباً إلى جنب. أضف متغير عرض كامل .btn--block يستخدم width: 100%. أضف أيضاً متغير زر أيقونة يستخدم وحدة ch لتحديد بُعد مربع. تحقق من أن الزر يتدرج بشكل صحيح عند تغيير تكبير المتصفح إلى 150% و 200%.

تمرين 3: قسم بطل بملء الشاشة مع طباعة مرنة

ابنِ قسم بطل يستخدم min-height: 100dvh (مع احتياطي 100vh) ويوسّط محتواه عمودياً وأفقياً. عنوان البطل يجب أن يستخدم clamp() مع rem و vw وقيمة rem قصوى للتحجيم المرن. أسفل العنوان، أضف عنواناً فرعياً بحجم خط مرن أصغر وزر دعوة للعمل. يجب أن يحتوي البطل على حاوية داخلية مع max-width: 75rem و width: 100% مع حشوة بـ rem. أسفل البطل، أنشئ شبكة من ثلاثة أعمدة باستخدام عروض مئوية وفجوات rem تنهار إلى عمود واحد على إطارات العرض الأصغر باستخدام نهج قائم على calc() مع min() و 100%. كل بطاقة في الشبكة يجب أن تستخدم em للمسافات الداخلية و rem لحجم خطها. هذا التمرين يجمع كل نوع وحدة تمت مناقشته في هذا الدرس.