Skip to main content

Chapitre 45 : Arbitrage : Propriétés physiques vs Propriétés logiques

Comparaison des cas d'usage pour maintenir la maintenabilité dans les projets multilingues

L'un des plus grands défis de l'intégration front-end moderne est la gestion de l'internationalisation (i18n). Historiquement, nous avons conçu le web sur un modèle "gauche-à-droite" (LTR), utilisant des propriétés physiques comme margin-left ou padding-right. Cependant, pour des langues comme l'arabe ou l'hébreu (RTL - Right-to-Left), ou même des écritures verticales (est asiatiques), ce modèle s'effondre.

L'arbitrage entre propriétés physiques et logiques ne consiste pas à "remplacer" l'une par l'autre, mais à choisir l'outil adapté à l'intention sémantique du design.

L'Arbitrage Sémantique

1. Quoi

L'arbitrage consiste à choisir entre :

  • Les propriétés physiques : Elles se réfèrent aux directions absolues de l'écran (Top, Bottom, Left, Right). Elles sont immuables, peu importe la langue ou le mode d'écriture.
  • Les propriétés logiques : Elles se réfèrent aux axes de flux du contenu (Block et Inline). Elles sont dynamiques et s'adaptent automatiquement à la direction du texte définie par l'attribut dir (LTR/RTL) ou la propriété writing-mode.

2. Pourquoi

Dans un projet professionnel, utiliser systématiquement des propriétés physiques pour le layout crée une "dette d'internationalisation". Si vous devez supporter le RTL, vous devrez soit :

  1. Écrire un second fichier CSS spécifique au RTL (ex: style-rtl.css) où vous inversez manuellement chaque left en right.
  2. Utiliser des plugins de post-processing (comme rtlcss) qui automatisent l'inversion, mais complexifient la chaîne de build et le débogage.

L'adoption des propriétés logiques permet d'écrire un seul code source qui s'adapte nativement à toutes les directions de lecture, réduisant ainsi drastiquement la surface de maintenance et les risques de régression visuelle.

3. Comment

A. Syntaxe de base : Le mapping mental

Pour réussir l'arbitrage, il faut mapper les concepts physiques vers les concepts logiques :

Physique (Absolu)Logique (Relatif au flux)Concept
widthinline-sizeDimension suivant la ligne de texte
heightblock-sizeDimension perpendiculaire à la ligne
margin-left / rightmargin-inline-start / endMarges horizontales (en LTR)
margin-top / bottommargin-block-start / endMarges verticales (en LTR)
border-leftborder-inline-startBordure au début du flux
text-align: lefttext-align: startAlignement au début du flux

B. Cas concret : Composant de Carte Multilingue

Imaginons une carte de profil avec une image à gauche et du texte à droite. En LTR, l'image est à gauche. En RTL, l'image doit passer à droite sans que nous ayons à modifier le CSS.

/* ❌ Approche Physique (Rigide) */
.profile-card {
display: flex;
padding-left: 20px;
border-left: 5px solid blue;
}

.profile-card img {
margin-right: 15px;
}

/*
Problème : En RTL, le padding reste à gauche,
la bordure reste à gauche et l'image pousse
le texte vers la gauche (incorrect).
*/

/* ✅ Approche Logique (Flexible) */
.profile-card {
display: flex;
/* S'adapte : gauche en LTR, droite en RTL */
padding-inline-start: 20px;
border-inline-start: 5px solid blue;
}

.profile-card img {
/* S'adapte : droite en LTR, gauche en RTL */
margin-inline-end: 15px;
}

C. Limitations

Bien que puissantes, les propriétés logiques ne sont pas une solution universelle :

  • Positionnement Absolu : top, bottom, left, right sont toujours physiques. Bien que inset-inline-start existe, le positionnement complexe (ex: overlays) nécessite parfois encore des coordonnées physiques pour un contrôle pixel-perfect.
  • Assets Graphiques : Une propriété logique ne retournera pas une image. Si vous avez une icône de "flèche vers la droite" pour indiquer "Suivant", vous devrez utiliser transform: scaleX(-1) en RTL via un sélecteur [dir="rtl"].
  • Anciens Navigateurs : Bien que le support soit excellent aujourd'hui (95%+), certains très vieux navigateurs d'entreprise peuvent nécessiter des fallbacks.

4. Zone de Danger

L'erreur du "Tout Logique" : Vouloir utiliser margin-block-start pour créer un espace fixe en haut d'une page, même si cet espace ne doit jamais bouger, peu importe la langue.

La Bonne Pratique :

  • Utilisez le Logique pour tout ce qui concerne la structure du contenu (espacements entre éléments, alignements de texte, dimensions de conteneurs).
  • Utilisez le Physique pour tout ce qui concerne le décor pur ou les éléments dont la position est liée à l'écran et non au sens de lecture (ex: un bouton "Fermer" toujours en haut à droite d'une modale, quel que soit le pays).

Arbre de décision : Physique vs Logique

Questions clés

1. Quelle est la différence fondamentale entre width et inline-size ?

Découvrir la réponse

width définit toujours la dimension horizontale (axe X). inline-size définit la dimension dans la direction du flux du texte. En mode LTR, inline-size équivaut à width. En mode d'écriture vertical (ex: japonais traditionnel), inline-size équivaut à la height.

2. Pourquoi text-align: start est-il préférable à text-align: left ?

Découvrir la réponse

Parce que start est relatif. En anglais (LTR), start est la gauche. En arabe (RTL), start est la droite. Utiliser start permet au texte de s'aligner naturellement selon la langue de l'utilisateur sans CSS additionnel.

3. Quand dois-je absolument continuer d'utiliser margin-left ?

Découvrir la réponse

Lorsque l'espacement est dicté par une contrainte visuelle absolue qui ne doit pas changer. Par exemple, si vous avez un design où un élément doit être collé au bord gauche de l'écran pour des raisons d'identité visuelle (branding), indépendamment de la langue.

4. Comment gérer les icônes directionnelles avec les propriétés logiques ?

Découvrir la réponse

Les propriétés logiques gèrent l'espace et la position, pas le contenu. Pour une icône de flèche, vous devez combiner les propriétés logiques (pour sa position) et une transformation CSS (pour son orientation) :

[dir="rtl"] .arrow-icon {
transform: scaleX(-1);
}

5. Est-ce que l'utilisation des propriétés logiques impacte les performances ?

Découvrir la réponse

Non. Le calcul des propriétés logiques est effectué par le moteur de rendu du navigateur lors de la phase de layout. L'impact est négligeable et largement compensé par la réduction de la quantité de CSS à charger (plus besoin de fichiers CSS RTL séparés).

Mise en pratique

Exercice 1 : Reproduction guidée

Convertissez le CSS suivant (propriétés physiques) pour qu'il fonctionne correctement en LTR et en RTL, en remplaçant chaque propriété physique par son équivalent logique.

HTML de départ :

<!-- Testez les deux contextes -->
<div dir="ltr">
<div class="alert-box">⚠️ Attention : votre session expire dans 5 minutes.</div>
</div>

<div dir="rtl">
<div class="alert-box">⚠️ تنبيه: ستنتهي جلستك خلال 5 دقائق.</div>
</div>

CSS à convertir :

.alert-box {
padding-left: 1rem;
padding-right: 1rem;
border-left: 4px solid red;
margin-bottom: 2rem;
text-align: left;
}
Découvrir la solution commentée
.alert-box {
/* padding-left et right deviennent padding-inline */
padding-inline: 1rem;

/* border-left devient border-inline-start pour s'adapter au début du flux */
border-inline-start: 4px solid red;

/* margin-bottom reste margin-block-end (le flux vertical est généralement constant) */
margin-block-end: 2rem;

/* text-align: left devient start */
text-align: start;
}

Exercice 2 : Adaptation

Vous avez un menu de navigation où les liens sont séparés par une bordure et un espacement. Modifiez le CSS pour qu'il fonctionne parfaitement en LTR et RTL sans dupliquer les règles.

HTML de départ :

<!-- Testez en changeant dir="ltr" en dir="rtl" -->
<nav dir="ltr">
<ul class="nav-list">
<li class="nav-item"><a href="#">Accueil</a></li>
<li class="nav-item"><a href="#">Produits</a></li>
<li class="nav-item"><a href="#">Services</a></li>
<li class="nav-item"><a href="#">Contact</a></li>
</ul>
</nav>

CSS à adapter :

.nav-list {
display: flex;
list-style: none;
padding: 0;
margin: 0;
}

/* ❌ Propriétés physiques à convertir */
.nav-item {
border-right: 1px solid #ccc;
padding-right: 15px;
margin-right: 10px;
}

.nav-item:last-child {
border-right: none;
}
Découvrir la solution commentée
.nav-item {
/* On remplace 'right' par 'inline-end' */
border-inline-end: 1px solid #ccc;
padding-inline-end: 15px;
margin-inline-end: 10px;
}

.nav-item:last-child {
/* On retire la bordure à la fin du flux */
border-inline-end: none;
}

Exercice 3 : Conception

Créez le CSS d'un composant "Chat Bubble" qui s'adapte automatiquement au LTR et au RTL.

HTML de départ :

<!-- Changez dir="ltr" en dir="rtl" pour tester l'inversion -->
<div class="chat" dir="ltr">
<div class="bubble user">Bonjour, comment puis-je vous aider ?</div>
<div class="bubble guest">J'ai une question sur ma commande.</div>
<div class="bubble user">Bien sûr, donnez-moi votre numéro de commande.</div>
<div class="bubble guest">C'est le numéro CMD-4892.</div>
</div>

Propriétés CSS attendues :

SélecteurPropriétéValeur
.chatdisplayflex
.chatflex-directioncolumn
.chatpadding1rem
.bubblemax-inline-size70%
.bubblepadding10px
.bubbleborder-radius12px
.bubblemargin-block-end10px
.bubble.userbackground#dcf8c6 (vert clair)
.bubble.useralignement vers la finmargin-inline-start: auto
.bubble.usercoin supprimé (LTR)border-bottom-right-radius: 0
.bubble.guestbackground#f0f0f0 (gris clair)
.bubble.guestalignement vers le débutmargin-inline-end: auto
.bubble.guestcoin supprimé (LTR)border-bottom-left-radius: 0
[dir="rtl"] .bubble.usercoins inversésborder-bottom-left-radius: 0 / border-bottom-right-radius: 12px
[dir="rtl"] .bubble.guestcoins inversésborder-bottom-right-radius: 0 / border-bottom-left-radius: 12px
Pourquoi margin-inline-start: auto ?

En flexbox, auto sur une marge logique absorbe tout l'espace disponible dans la direction correspondante. Sur .bubble.user, margin-inline-start: auto pousse la bulle vers la fin du flux (droite en LTR, gauche en RTL) — sans aucune règle :dir() supplémentaire.

Découvrir la solution commentée
/* Base commune */
.bubble {
max-inline-size: 70%;
padding: 10px;
border-radius: 12px;
margin-block-end: 10px;
}

/* Message Utilisateur (Aligné à la fin du flux) */
.bubble.user {
margin-inline-start: auto; /* Pousse l'élément vers la fin (droite en LTR) */
text-align: start;

/* On utilise des propriétés physiques pour les coins car
le border-radius logique est encore partiellement supporté.
L'astuce est d'utiliser le sélecteur [dir] pour l'inversion. */
border-bottom-right-radius: 0;
}

[dir="rtl"] .bubble.user {
border-bottom-left-radius: 0;
border-bottom-right-radius: 12px;
}

/* Message Destinataire (Aligné au début du flux) */
.bubble.guest {
margin-inline-end: auto; /* Pousse l'élément vers le début (gauche en LTR) */
text-align: start;
border-bottom-left-radius: 0;
}

[dir="rtl"] .bubble.guest {
border-bottom-right-radius: 0;
border-bottom-left-radius: 12px;
}