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

الخصائص المنطقية وأنماط الكتابة

25 دقيقة الدرس 53 من 60

فهم الخصائص الفيزيائية مقابل المنطقية

لعقود من الزمن، استخدم CSS خصائص فيزيائية مثل margin-left وpadding-right وwidth وheight للتحكم في التخطيط. هذه الخصائص مرتبطة بالأبعاد الفيزيائية للشاشة: يسار، يمين، أعلى، وأسفل. تعمل بشكل مثالي إذا كان محتواك يتدفق دائما من اليسار إلى اليمين ومن الأعلى إلى الأسفل، كما في الإنجليزية. لكن الويب عالمي. العربية والعبرية تتدفق من اليمين إلى اليسار. الصينية واليابانية التقليدية يمكن أن تتدفق عموديا. عندما تكتب اتجاهات فيزيائية ثابتة في CSS الخاص بك، تنكسر تخطيطاتك في اللحظة التي يتغير فيها اتجاه النص.

الخصائص المنطقية في CSS تحل هذه المشكلة باستبدال الاتجاهات الفيزيائية بأخرى منطقية تعتمد على نمط الكتابة واتجاه النص في المستند. بدلا من التفكير بـ "يسار" و"يمين"، تفكر بـ "بداية" و"نهاية". بدلا من "أعلى" و"أسفل"، تفكر بـ "بداية الكتلة" و"نهاية الكتلة". هذا التجريد يعني أن مجموعة واحدة من قواعد CSS يمكن أن تتكيف تلقائيا مع أي اتجاه كتابة -- من اليسار لليمين، من اليمين لليسار، أو عمودي -- بدون أي كود إضافي. الخصائص المنطقية ليست مجرد راحة؛ إنها أساس تخطيطات الويب المُدَوَّلة حقا.

أنماط الكتابة: الأساس

قبل الغوص في الخصائص المنطقية، تحتاج لفهم أنماط الكتابة. خاصية writing-mode تحدد الاتجاه الذي يتم فيه وضع كتل المحتوى واتجاه تدفق المحتوى السطري داخل الكتلة. إنها تغير بشكل جذري كيف يفسر المتصفح اتجاهي "الكتلة" و"السطر".

خاصية writing-mode

تقبل خاصية writing-mode ثلاث قيم رئيسية، كل منها تحدد تدفقا مختلفا للمحتوى:

قيم writing-mode في CSS

/* الافتراضي: نص أفقي، تدفق كتلي من الأعلى للأسفل */
.horizontal {
    writing-mode: horizontal-tb;
    /* السطري يتدفق من اليسار لليمين (في LTR) أو من اليمين لليسار (في RTL) */
    /* الكتل تتراكم من الأعلى للأسفل */
}

/* نص عمودي، يتدفق من اليمين لليسار */
.vertical-rl {
    writing-mode: vertical-rl;
    /* السطري يتدفق من الأعلى للأسفل */
    /* الكتل تتراكم من اليمين لليسار */
    /* تخطيط الصينية واليابانية والكورية التقليدي */
}

/* نص عمودي، يتدفق من اليسار لليمين */
.vertical-lr {
    writing-mode: vertical-lr;
    /* السطري يتدفق من الأعلى للأسفل */
    /* الكتل تتراكم من اليسار لليمين */
    /* تخطيط الخط المنغولي التقليدي */
}

في horizontal-tb (الافتراضي للإنجليزية والعربية ومعظم اللغات)، يعمل النص أفقيا والكتل تتراكم من الأعلى للأسفل. في vertical-rl، يعمل النص عموديا والكتل تتراكم من اليمين لليسار -- هكذا يُنضَّد النص الياباني والصيني التقليدي عادة. في vertical-lr، يعمل النص أيضا عموديا لكن الكتل تتراكم من اليسار لليمين.

أمثلة عملية لأنماط الكتابة

/* تخطيط النص الياباني العمودي */
.japanese-vertical {
    writing-mode: vertical-rl;
    font-family: "Noto Sans JP", sans-serif;
    line-height: 1.8;
    /* النص يُقرأ من الأعلى للأسفل، الأعمدة تتدفق من اليمين لليسار */
}

/* شريط جانبي بنص عمودي مدوَّر */
.sidebar-label {
    writing-mode: vertical-rl;
    text-orientation: mixed;
    padding: 1rem;
    background: #2c3e50;
    color: white;
    font-size: 0.875rem;
    letter-spacing: 0.1em;
    text-transform: uppercase;
}

/* عنوان عمودي إبداعي */
.vertical-headline {
    writing-mode: vertical-lr;
    transform: rotate(180deg);
    /* هذا ينشئ نصا عموديا يُقرأ من اليمين لليسار */
    font-size: 3rem;
    font-weight: 700;
}
ملاحظة: خاصية writing-mode تُورَث بواسطة العناصر الأبناء. تعيينها على حاوية أب يؤثر على جميع الأبناء ما لم يتجاوزوها صراحة. هذا مهم عند إنشاء تخطيطات متعددة الاتجاهات حيث تحتاج بعض العناصر للبقاء أفقية داخل حاوية عمودية.

خاصية direction

تتحكم خاصية direction في الاتجاه الأساسي السطري للنص: من اليسار لليمين (ltr) أو من اليمين لليسار (rtl). بينما تحدد writing-mode ما إذا كان النص أفقيا أو عموديا، تحدد direction أي طرف من السطر هو "البداية".

تعيين اتجاه النص

/* من اليسار لليمين (الإنجليزية، الفرنسية، إلخ.) */
.ltr-content {
    direction: ltr;
    /* بداية السطر = يسار، نهاية السطر = يمين */
}

/* من اليمين لليسار (العربية، العبرية، إلخ.) */
.rtl-content {
    direction: rtl;
    /* بداية السطر = يمين، نهاية السطر = يسار */
}

/* إعداد صفحة عربية كاملة */
html[lang="ar"] {
    direction: rtl;
}

/* بديل: استخدام سمة dir في HTML (مُفضَّل) */
/* <html lang="ar" dir="rtl"> */
نصيحة: من أفضل الممارسات تعيين اتجاه النص باستخدام سمة dir في HTML على عنصر <html> بدلا من خاصية CSS direction. سمة dir دلالية وتؤثر على كيفية تعامل المتصفحات مع خوارزميات النص ثنائي الاتجاه ومدخلات النماذج وسلوكيات أخرى غير CSS. استخدم CSS direction فقط للتجاوزات المرئية عندما لا تكون سمة HTML مناسبة.

محور الكتلة مقابل محور السطر

المفهوم الأساسي وراء الخصائص المنطقية هو التمييز بين محور الكتلة ومحور السطر. هذان المحوران يتغير معناهما حسب نمط الكتابة:

في horizontal-tb (الافتراضي): محور السطر أفقي (من اليسار لليمين أو من اليمين لليسار)، ومحور الكتلة عمودي (من الأعلى للأسفل). في vertical-rl أو vertical-lr: محور السطر عمودي (من الأعلى للأسفل)، ومحور الكتلة أفقي (من اليمين لليسار أو من اليسار لليمين).

تصور محوري الكتلة والسطر

/*
   horizontal-tb (الإنجليزية، العربية):
   ┌──────────────────────────────┐
   │  محور السطر ──────────►     │  محور
   │  (أو ◄────── في RTL)        │  الكتلة
   │                              │  │
   │  النص يتدفق على طول السطر  │  │
   │  الكتل تتراكم على طول الكتلة│  ▼
   └──────────────────────────────┘

   vertical-rl (CJK التقليدي):
   ┌──────────────────────────────┐
   │  ◄── محور الكتلة             │
   │                              │
   │  │  النص يتدفق على طول      │
   │  │  محور السطر               │
   │  │  (من الأعلى للأسفل)       │
   │  ▼                           │
   └──────────────────────────────┘

   الفكرة الأساسية: "الكتلة" و"السطر" نسبيتان
   لنمط الكتابة، وليست ثابتة على حواف الشاشة الفيزيائية.
*/

خصائص الهامش المنطقية

خصائص الهامش المنطقية تستبدل margin-top وmargin-right وmargin-bottom وmargin-left الفيزيائية بمكافئات مستقلة عن الاتجاه. اتفاقية التسمية تستخدم block لمحور الكتلة وinline لمحور السطر، مع start وend.

خصائص الهامش المنطقية

/* الهوامش الفيزيائية (تجنبها لتخطيطات التدويل) */
.physical {
    margin-top: 1rem;
    margin-right: 2rem;
    margin-bottom: 1rem;
    margin-left: 2rem;
}

/* المكافئات المنطقية للهامش (مُفضَّلة) */
.logical {
    margin-block-start: 1rem;   /* أعلى في horizontal-tb */
    margin-inline-end: 2rem;    /* يمين في LTR، يسار في RTL */
    margin-block-end: 1rem;     /* أسفل في horizontal-tb */
    margin-inline-start: 2rem;  /* يسار في LTR، يمين في RTL */
}

/* اختصار لكل من البداية والنهاية على نفس المحور */
.logical-shorthand {
    margin-block: 1rem;         /* بداية الكتلة ونهايتها */
    margin-inline: 2rem;        /* بداية السطر ونهايته */
}

/* اختصار بقيمتين: البداية والنهاية بشكل منفصل */
.logical-two-value {
    margin-block: 1rem 2rem;    /* بداية الكتلة: 1rem، نهاية الكتلة: 2rem */
    margin-inline: 0.5rem 1rem; /* بداية السطر: 0.5rem، نهاية السطر: 1rem */
}

/* مثال عملي: مسافة أيقونة التنقل من النص */
.nav-icon {
    margin-inline-end: 0.5rem;
    /* في LTR: الأيقونة لها هامش يمين (أيقونة ثم نص) */
    /* في RTL: الأيقونة لها هامش يسار (نص ثم أيقونة) */
}

التعيين بين الخصائص الفيزيائية والمنطقية في سياق horizontal-tb مع LTR هو: margin-block-start يساوي margin-top، وmargin-block-end يساوي margin-bottom، وmargin-inline-start يساوي margin-left، وmargin-inline-end يساوي margin-right. في سياق RTL، يصبح margin-inline-start مساويا لـ margin-right وmargin-inline-end يصبح margin-left.

خصائص الحشو المنطقية

خصائص الحشو المنطقية تتبع نفس نمط التسمية بالضبط مثل الهوامش. تستبدل padding-top وpadding-right وpadding-bottom وpadding-left بمكافئات نسبية للتدفق.

خصائص الحشو المنطقية

/* الحشو الفيزيائي */
.card-physical {
    padding-top: 1.5rem;
    padding-right: 2rem;
    padding-bottom: 1.5rem;
    padding-left: 2rem;
}

/* مكافئات الحشو المنطقية */
.card-logical {
    padding-block-start: 1.5rem;
    padding-inline-end: 2rem;
    padding-block-end: 1.5rem;
    padding-inline-start: 2rem;
}

/* اختصار */
.card-shorthand {
    padding-block: 1.5rem;        /* أعلى وأسفل */
    padding-inline: 2rem;         /* يسار ويمين (في LTR) */
}

/* اختصار بقيمتين */
.card-asymmetric {
    padding-block: 1rem 2rem;     /* بداية الكتلة: 1rem، نهايتها: 2rem */
    padding-inline: 1.5rem 3rem;  /* بداية السطر: 1.5rem، نهايته: 3rem */
}

/* عملي: عنصر قائمة مع مسافة بادئة */
.list-item {
    padding-inline-start: 2rem;
    /* في LTR: padding-left يزيح من الحافة اليسرى */
    /* في RTL: padding-right يزيح من الحافة اليمنى */
}

/* عملي: تنقل الشريط الجانبي */
.nav-link {
    padding-block: 0.75rem;
    padding-inline: 1rem 1.5rem;
    border-inline-start: 3px solid transparent;
}

.nav-link.active {
    border-inline-start-color: #3498db;
    background: rgba(52, 152, 219, 0.1);
}

خصائص الحدود المنطقية

توفر خصائص الحدود المنطقية نفس المرونة الاتجاهية للحدود. يمكنك تعيين أطراف حدود فردية، أو استخدام خصائص الاختصار لمحوري الكتلة والسطر.

خصائص الحدود المنطقية

/* الحدود الفيزيائية */
.physical-border {
    border-left: 3px solid #3498db;
    border-bottom: 1px solid #eee;
}

/* مكافئات الحدود المنطقية */
.logical-border {
    border-inline-start: 3px solid #3498db;
    border-block-end: 1px solid #eee;
}

/* خصائص حدود منطقية فردية */
.detailed-borders {
    border-block-start-width: 2px;
    border-block-start-style: solid;
    border-block-start-color: #333;

    border-inline-end-width: 1px;
    border-inline-end-style: dashed;
    border-inline-end-color: #ccc;
}

/* اختصار للمحور بالكامل */
.axis-borders {
    border-block: 1px solid #eee;     /* أعلى وأسفل */
    border-inline: 2px solid #333;    /* يسار ويمين (LTR) */
}

/* نصف قطر حد منطقي */
.logical-radius {
    border-start-start-radius: 8px; /* أعلى-يسار في LTR، أعلى-يمين في RTL */
    border-start-end-radius: 8px;   /* أعلى-يمين في LTR، أعلى-يسار في RTL */
    border-end-start-radius: 0;     /* أسفل-يسار في LTR، أسفل-يمين في RTL */
    border-end-end-radius: 0;       /* أسفل-يمين في LTR، أسفل-يسار في RTL */
}

/* عملي: صندوق تنبيه بلهجة على جانب البداية */
.callout {
    border-inline-start: 4px solid #e74c3c;
    padding-block: 1rem;
    padding-inline: 1.5rem;
    background: #fef2f2;
    border-start-start-radius: 4px;
    border-end-start-radius: 4px;
}
ملاحظة: خصائص نصف قطر الحد المنطقية تستخدم اتفاقية تسمية من جزأين: border-{موقع-الكتلة}-{موقع-السطر}-radius. فإن border-start-start-radius تعني "زاوية بداية-الكتلة، بداية-السطر"، والتي تُعيَّن إلى أعلى-يسار في سياق أفقي LTR. قد تبدو التسمية مربكة في البداية، لكنها تتبع نمطا متسقا بمجرد استيعابك لمفهوم محوري الكتلة/السطر.

التحجيم المنطقي: inline-size و block-size

width وheight الفيزيائيتان تشيران دائما إلى الأبعاد الأفقية والعمودية على التوالي. خصائص التحجيم المنطقية تستبدلهما بمكافئات نسبية للتدفق: inline-size تستبدل width (في أنماط الكتابة الأفقية) وblock-size تستبدل height.

خصائص التحجيم المنطقية

/* التحجيم الفيزيائي */
.physical-box {
    width: 300px;
    height: 200px;
    min-width: 200px;
    max-width: 600px;
    min-height: 100px;
    max-height: 400px;
}

/* مكافئات التحجيم المنطقية */
.logical-box {
    inline-size: 300px;       /* width في horizontal-tb */
    block-size: 200px;        /* height في horizontal-tb */
    min-inline-size: 200px;   /* min-width في horizontal-tb */
    max-inline-size: 600px;   /* max-width في horizontal-tb */
    min-block-size: 100px;    /* min-height في horizontal-tb */
    max-block-size: 400px;    /* max-height في horizontal-tb */
}

/* لماذا هذا مهم: نمط الكتابة العمودي */
.vertical-container {
    writing-mode: vertical-rl;
}

.vertical-container .box {
    inline-size: 300px;
    /* في vertical-rl، هذا يعيِّن الارتفاع (وليس العرض) */
    /* لأن محور السطر أصبح عموديا الآن */

    block-size: 200px;
    /* في vertical-rl، هذا يعيِّن العرض (وليس الارتفاع) */
    /* لأن محور الكتلة أصبح أفقيا الآن */
}

/* حاوية متجاوبة بتحجيم منطقي */
.responsive-card {
    inline-size: 100%;
    max-inline-size: 40rem;
    min-block-size: 15rem;
    margin-inline: auto;
}

التموضع المنطقي مع خصائص inset

خصائص inset هي المكافئات المنطقية لـ top وright وbottom وleft المستخدمة مع العناصر الموضَّعة. تسمح للعناصر المُموضعة بشكل مطلق أو ثابت بالاستجابة لاتجاه الكتابة تلقائيا.

خصائص inset المنطقية

/* التموضع الفيزيائي */
.physical-positioned {
    position: absolute;
    top: 0;
    right: 1rem;
    bottom: auto;
    left: auto;
}

/* مكافئات التموضع المنطقية */
.logical-positioned {
    position: absolute;
    inset-block-start: 0;      /* أعلى في horizontal-tb */
    inset-inline-end: 1rem;    /* يمين في LTR، يسار في RTL */
    inset-block-end: auto;     /* أسفل في horizontal-tb */
    inset-inline-start: auto;  /* يسار في LTR، يمين في RTL */
}

/* اختصار: inset-block و inset-inline */
.shorthand-positioned {
    position: absolute;
    inset-block: 0;            /* top: 0; bottom: 0; */
    inset-inline: 1rem 2rem;   /* بداية: 1rem، نهاية: 2rem */
}

/* اختصار inset (يعيِّن الأربعة) */
.inset-all {
    position: absolute;
    inset: 0;
    /* مكافئ لـ top: 0; right: 0; bottom: 0; left: 0; */
}

/* عملي: زر إغلاق في الزاوية العلوية-النهائية */
.close-button {
    position: absolute;
    inset-block-start: 0.5rem;
    inset-inline-end: 0.5rem;
    /* LTR: الزاوية العلوية اليمنى */
    /* RTL: الزاوية العلوية اليسرى */
}

/* عملي: تموضع تلميح الأدوات */
.tooltip {
    position: absolute;
    inset-block-end: 100%;
    inset-inline-start: 50%;
    transform: translateX(-50%);
    margin-block-end: 0.5rem;
}

محاذاة النص المنطقية

محاذاة النص أيضا لها قيم منطقية. بدلا من text-align: left وtext-align: right، يمكنك استخدام text-align: start وtext-align: end. هذه تتكيف تلقائيا مع اتجاه النص.

محاذاة النص المنطقية

/* المحاذاة الفيزيائية (تجنبها للتدويل) */
.physical-align {
    text-align: left;
}

/* المحاذاة المنطقية (مُفضَّلة) */
.logical-align {
    text-align: start;
    /* يسار في لغات LTR */
    /* يمين في لغات RTL */
}

.end-aligned {
    text-align: end;
    /* يمين في لغات LTR */
    /* يسار في لغات RTL */
}

/* استخدام عملي */
.article-body {
    text-align: start;
}

.article-date {
    text-align: end;
    color: #666;
    font-size: 0.875rem;
}

/* عناصر التنقل مُحاذاة للبداية */
.nav-item {
    text-align: start;
    padding-inline-start: 1rem;
}

/* السعر مُحاذى للنهاية في بطاقة منتج */
.product-price {
    text-align: end;
    font-weight: 700;
    font-size: 1.25rem;
}

قيم Float و Clear و Resize المنطقية

خصائص Float و clear أيضا لها مكافئات منطقية باستخدام inline-start وinline-end بدلا من left وright. خاصية resize تدعم بالمثل قيمتي block وinline.

Float و Clear المنطقية

/* الطفو الفيزيائي */
.physical-float {
    float: left;
}

/* الطفو المنطقي */
.logical-float {
    float: inline-start;
    /* يطفو لليسار في LTR */
    /* يطفو لليمين في RTL */
}

.float-end {
    float: inline-end;
    /* يطفو لليمين في LTR */
    /* يطفو لليسار في RTL */
}

/* المسح المنطقي */
.clear-start {
    clear: inline-start;
}

.clear-end {
    clear: inline-end;
}

/* عملي: صورة تطفو بجانب النص */
.article-image {
    float: inline-start;
    margin-inline-end: 1.5rem;
    margin-block-end: 1rem;
    max-inline-size: 300px;
    /* في LTR: تطفو لليسار مع هامش يمين */
    /* في RTL: تطفو لليمين مع هامش يسار */
}

/* تغيير الحجم المنطقي */
.resizable-block {
    resize: block;
    /* يسمح بتغيير الحجم على طول محور الكتلة (عموديا في horizontal-tb) */
    overflow: auto;
}

.resizable-inline {
    resize: inline;
    /* يسمح بتغيير الحجم على طول محور السطر (أفقيا في horizontal-tb) */
    overflow: auto;
}

لماذا تهم الخصائص المنطقية للتدويل

تظهر القوة الحقيقية للخصائص المنطقية عندما تبني تخطيطات تحتاج لدعم اتجاهات كتابة متعددة. فكر في موقع ويب يجب أن يعمل بالإنجليزية (LTR) والعربية (RTL). بدون الخصائص المنطقية، ستحتاج لأوراق أنماط منفصلة أو تجاوزات واسعة لـ RTL. مع الخصائص المنطقية، ورقة أنماط واحدة تتعامل مع كلا الاتجاهين تلقائيا.

قبل الخصائص المنطقية: نهج تجاوز RTL

/* الأنماط الأساسية (LTR) */
.card {
    padding-left: 1.5rem;
    padding-right: 1rem;
    border-left: 4px solid #3498db;
    margin-right: 1rem;
    text-align: left;
}

.card-icon {
    float: left;
    margin-right: 0.75rem;
}

/* تجاوزات RTL -- يجب عكس كل خاصية اتجاهية */
[dir="rtl"] .card {
    padding-left: 1rem;
    padding-right: 1.5rem;
    border-left: none;
    border-right: 4px solid #3498db;
    margin-right: 0;
    margin-left: 1rem;
    text-align: right;
}

[dir="rtl"] .card-icon {
    float: right;
    margin-right: 0;
    margin-left: 0.75rem;
}
/* هذه 14 تصريحا إضافيا فقط لعكس مكون واحد! */

بعد الخصائص المنطقية: صفر تجاوزات RTL مطلوبة

/* مجموعة أنماط واحدة تعمل لكل من LTR وRTL */
.card {
    padding-inline-start: 1.5rem;
    padding-inline-end: 1rem;
    border-inline-start: 4px solid #3498db;
    margin-inline-end: 1rem;
    text-align: start;
}

.card-icon {
    float: inline-start;
    margin-inline-end: 0.75rem;
}
/* لا حاجة لتجاوزات RTL. صفر كود إضافي. */
/* في LTR: padding-left، border-left، margin-right، float left */
/* في RTL: padding-right، border-right، margin-left، float right */
نصيحة: حتى لو كان موقعك يدعم حاليا لغة واحدة فقط، فإن استخدام الخصائص المنطقية من البداية هو أفضل ممارسة. لا يكلف شيئا من حيث تعقيد الكود ويضمن أن قاعدة الكود جاهزة للتدويل. العديد من أطر عمل CSS وأنظمة التصميم تبنت بالفعل الخصائص المنطقية كافتراضها.

بناء تخطيطات ثنائية الاتجاه

دعنا نبني مكونا كاملا يعمل بسلاسة في كلا سياقي LTR وRTL. مكون بطاقة الوسائط هذا يوضح كيف تلغي الخصائص المنطقية الحاجة للتجاوزات الاتجاهية بالكامل.

بطاقة وسائط ثنائية الاتجاه كاملة

/* بطاقة وسائط: صورة على جانب البداية، محتوى على جانب النهاية */
.media-card {
    display: flex;
    gap: 1.5rem;
    padding: 1.5rem;
    border: 1px solid #e2e8f0;
    border-radius: 8px;
    background: #fff;
    max-inline-size: 600px;
}

.media-card__image {
    flex-shrink: 0;
    inline-size: 120px;
    block-size: 120px;
    border-radius: 8px;
    object-fit: cover;
}

.media-card__content {
    flex: 1;
    min-inline-size: 0;
}

.media-card__title {
    font-size: 1.25rem;
    font-weight: 600;
    margin-block-end: 0.5rem;
    text-align: start;
}

.media-card__description {
    color: #64748b;
    margin-block-end: 1rem;
    text-align: start;
    line-height: 1.6;
}

.media-card__meta {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding-block-start: 0.75rem;
    border-block-start: 1px solid #e2e8f0;
}

.media-card__badge {
    padding-block: 0.25rem;
    padding-inline: 0.75rem;
    background: #eff6ff;
    color: #3b82f6;
    border-radius: 999px;
    font-size: 0.75rem;
    font-weight: 500;
}

/* هذا المكون بأكمله يعمل بشكل مثالي في كلا اتجاهي LTR وRTL
   بدون أي تجاوز [dir="rtl"]. تخطيط flex ينعكس
   طبيعيا في RTL، وجميع الخصائص المنطقية
   تنقلب تلقائيا للأطراف الفيزيائية الصحيحة. */

مرجع التعيين الكامل

إليك جدول مرجعي شامل يعيِّن الخصائص الفيزيائية لمكافئاتها المنطقية. يفترض هذا المرجع نمط كتابة horizontal-tb مع اتجاه ltr للتعيينات الفيزيائية الموضحة.

تعيين الخصائص الفيزيائية إلى المنطقية

/* ===== الهوامش ===== */
/* margin-top         →  margin-block-start    */
/* margin-bottom      →  margin-block-end      */
/* margin-left        →  margin-inline-start   */
/* margin-right       →  margin-inline-end     */

/* ===== الحشو ===== */
/* padding-top        →  padding-block-start   */
/* padding-bottom     →  padding-block-end     */
/* padding-left       →  padding-inline-start  */
/* padding-right      →  padding-inline-end    */

/* ===== الحدود ===== */
/* border-top         →  border-block-start    */
/* border-bottom      →  border-block-end      */
/* border-left        →  border-inline-start   */
/* border-right       →  border-inline-end     */

/* ===== نصف قطر الحد ===== */
/* border-top-left-radius     →  border-start-start-radius  */
/* border-top-right-radius    →  border-start-end-radius    */
/* border-bottom-left-radius  →  border-end-start-radius    */
/* border-bottom-right-radius →  border-end-end-radius      */

/* ===== التحجيم ===== */
/* width              →  inline-size           */
/* height             →  block-size            */
/* min-width          →  min-inline-size       */
/* max-width          →  max-inline-size       */
/* min-height         →  min-block-size        */
/* max-height         →  max-block-size        */

/* ===== التموضع ===== */
/* top                →  inset-block-start     */
/* bottom             →  inset-block-end       */
/* left               →  inset-inline-start    */
/* right              →  inset-inline-end      */

/* ===== النص والطفو ===== */
/* text-align: left   →  text-align: start     */
/* text-align: right  →  text-align: end       */
/* float: left        →  float: inline-start   */
/* float: right       →  float: inline-end     */
/* clear: left        →  clear: inline-start   */
/* clear: right       →  clear: inline-end     */

/* ===== تغيير الحجم ===== */
/* resize: horizontal →  resize: inline        */
/* resize: vertical   →  resize: block         */

دعم المتصفحات واستراتيجيات البديل

تتمتع الخصائص المنطقية في CSS بدعم ممتاز في جميع المتصفحات الحديثة. Chrome وFirefox وSafari وEdge جميعها تدعم الخصائص المنطقية الأساسية للهوامش والحشو والحدود والتحجيم والتموضع. ومع ذلك، بعض القيم المنطقية الأحدث مثل float: inline-start لديها دعم أقل اتساقا. إليك استراتيجيات للتعامل مع المتصفحات القديمة:

استراتيجيات البديل

/* الاستراتيجية 1: تحسين تدريجي مع بدائل فيزيائية */
.card {
    /* بديل فيزيائي للمتصفحات القديمة */
    padding-left: 1.5rem;
    padding-right: 1rem;

    /* الخصائص المنطقية تتجاوز في المتصفحات الداعمة */
    padding-inline-start: 1.5rem;
    padding-inline-end: 1rem;
}

/* الاستراتيجية 2: استعلام ميزة @supports */
.sidebar {
    /* خصائص فيزيائية افتراضية */
    margin-left: 2rem;
    border-left: 3px solid #3498db;
}

@supports (margin-inline-start: 1rem) {
    .sidebar {
        margin-left: unset;
        border-left: unset;
        margin-inline-start: 2rem;
        border-inline-start: 3px solid #3498db;
    }
}

/* الاستراتيجية 3: إضافة PostCSS (تحويل وقت البناء)
   إضافة postcss-logical يمكنها تلقائيا توليد
   بدائل فيزيائية من الخصائص المنطقية:

   المدخل:  margin-inline-start: 1rem;
   المخرج: margin-left: 1rem;
           margin-inline-start: 1rem;

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

أمثلة عملية من العالم الحقيقي

دعنا ننظر في عدة سيناريوهات عملية حيث تبسِّط الخصائص المنطقية CSS الخاص بك بشكل كبير.

مثال: مكون الإشعار

/* إشعار بأيقونة على جانب البداية */
.notification {
    display: flex;
    align-items: flex-start;
    gap: 1rem;
    padding-block: 1rem;
    padding-inline: 1.25rem;
    border-inline-start: 4px solid;
    border-radius: 0.5rem;
    margin-block-end: 1rem;
}

.notification--success {
    border-inline-start-color: #22c55e;
    background: #f0fdf4;
}

.notification--error {
    border-inline-start-color: #ef4444;
    background: #fef2f2;
}

.notification--warning {
    border-inline-start-color: #f59e0b;
    background: #fffbeb;
}

.notification__icon {
    flex-shrink: 0;
    inline-size: 24px;
    block-size: 24px;
    margin-block-start: 2px;
}

.notification__close {
    margin-inline-start: auto;
    padding: 0.25rem;
    border: none;
    background: none;
    cursor: pointer;
}

مثال: تخطيط النموذج

/* نموذج بعناوين ومدخلات */
.form-group {
    margin-block-end: 1.5rem;
}

.form-label {
    display: block;
    margin-block-end: 0.5rem;
    font-weight: 500;
    text-align: start;
}

.form-input {
    inline-size: 100%;
    padding-block: 0.75rem;
    padding-inline: 1rem;
    border: 1px solid #d1d5db;
    border-radius: 0.375rem;
    font-size: 1rem;
    text-align: start;
}

.form-input:focus {
    border-color: #3b82f6;
    outline: none;
    box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
}

/* مدخل بأيقونة بداخله */
.input-with-icon {
    position: relative;
}

.input-with-icon .icon {
    position: absolute;
    inset-block-start: 50%;
    inset-inline-start: 1rem;
    transform: translateY(-50%);
    color: #9ca3af;
    pointer-events: none;
}

.input-with-icon .form-input {
    padding-inline-start: 2.75rem;
}

/* إجراءات النموذج مُحاذاة للنهاية */
.form-actions {
    display: flex;
    justify-content: flex-end;
    gap: 1rem;
    padding-block-start: 1.5rem;
    border-block-start: 1px solid #e5e7eb;
}

مثال: مسار التنقل

/* مسار تنقل ينعكس تلقائيا لـ RTL */
.breadcrumb {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    padding-block: 0.75rem;
    padding-inline: 0;
    list-style: none;
    margin: 0;
}

.breadcrumb__item {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    color: #64748b;
    font-size: 0.875rem;
}

.breadcrumb__item::after {
    content: "\203A"; /* زاوية يمنى مفردة (›) */
    color: #cbd5e1;
    font-size: 1.25rem;
}

[dir="rtl"] .breadcrumb__item::after {
    content: "\2039"; /* زاوية يسرى مفردة (‹) لـ RTL */
}

.breadcrumb__item:last-child::after {
    content: none;
}

.breadcrumb__item:last-child {
    color: #1e293b;
    font-weight: 500;
}

.breadcrumb__link {
    color: inherit;
    text-decoration: none;
    padding-block: 0.125rem;
    padding-inline: 0.25rem;
    border-radius: 0.25rem;
}

.breadcrumb__link:hover {
    background: #f1f5f9;
    color: #3b82f6;
}

التمرين 1: بطاقة ملف شخصي ثنائية الاتجاه

ابنِ مكون بطاقة ملف شخصي باستخدام خصائص منطقية فقط (صفر خصائص اتجاهية فيزيائية). يجب أن تحتوي البطاقة على صورة رمزية دائرية على جانب بداية السطر، واسم المستخدم ونص السيرة الذاتية في المنتصف، وزر متابعة على جانب نهاية السطر. أضف حد لهجة ملون على حافة بداية السطر. أسفل الصف الرئيسي، أضف شريط إحصائيات يعرض أعداد المتابعين والمتابَعين والمنشورات مفصولة بفواصل عمودية. استخدم margin-block وpadding-inline وborder-inline-start وtext-align: start وخصائص منطقية أخرى في كل مكان. اختبر بطاقتك بإضافة dir="rtl" للعنصر الأب وتحقق من أن كل شيء ينعكس بشكل صحيح بدون أي قواعد CSS إضافية. أضف فئة متغير writing-mode: vertical-rl تجعل البطاقة بالكامل تُعرض عموديا، وتحقق من أن جميع خصائصك المنطقية لا تزال تعمل بشكل صحيح في نمط الكتابة العمودي.

التمرين 2: تخطيط لوحة تحكم متجاوبة

أنشئ تخطيط لوحة تحكم مع شريط جانبي ثابت على جانب بداية السطر ومنطقة محتوى رئيسية. يجب أن يحتوي الشريط الجانبي على روابط تنقل بأيقونات على جانب بداية السطر ونص يتبعها، ومؤشر نشط بحد على جانب بداية السطر، وحشو باستخدام خصائص منطقية. يجب أن تحتوي منطقة المحتوى الرئيسية على رأس بعنوان صفحة مُحاذى للبداية وأزرار إجراءات مُحاذاة للنهاية، متبوعة بشبكة بطاقات إحصائيات. يجب أن تحتوي كل بطاقة إحصائيات على أيقونة وقيمة مقياس وعنوان باستخدام خصائص منطقية فقط لجميع المسافات والحدود. ابنِ التخطيط بالكامل بدون استخدام واحد لـ left أو right أو width أو height في أي سياق اتجاهي. استخدم فقط inline-size وblock-size وinset-inline-start وmargin-inline وpadding-block ومكافئات منطقية أخرى. أضف زر تبديل لغة يغير سمة dir بين ltr وrtl على عنصر HTML، وتحقق من أن لوحة التحكم بأكملها تنعكس بشكل صحيح.