Mior Agency

Implémentation des propriétés CSS logiques dans les applications Web

La localisation est l’un des domaines les plus intéressants en termes d’interface utilisateur : la longueur du texte peut être différente selon la langue, les alignements de texte par défaut peuvent varier, le sens de lecture peut être en miroir ou vertical, et bien d’autres cas différents. . Bref, c’est un incroyable source de diversitéce qui rend nos interfaces et notre travail frontal beaucoup plus solides, plus fiables et plus stimulants.

Le besoin d’interfaces de droite à gauche

La plupart des langues, comme le français ou l’anglais, sont conçues pour être lues de gauche à droite (LTR). Cependant, dans ces cas, certaines langues comme le farsi (persan), l’arabe et l’hébreu ont un sens de lecture différent : de droite à gauche (RTL).

La question est Quoi Pouvons-nous adapter nos interfaces à ce grand changement ?

Avant les propriétés CSS logiques

Avant CSS Logical Properties, nous pouvions faire des adaptations RTL avec différentes méthodes :

  • Ajout d’un fichier CSS dédié uniquement pour le balisage/la mise en page RTL ;
  • Recharger uniquement les parties qui doivent être adaptées dans le même CSS, par exemple [dir="rtl"] .float-left { float: right; }.

Même si ces méthodes fonctionnent (j’ai utilisé la seconde pour créer une version arabe du site Stand Up for Human Rights il y a quelques années), elles sont toutes les deux assez sous-optimales :

  • Vous devez conserver un autre fichier pour le premier ;
  • Le fichier CSS du second est un peu plus lourd et il peut y avoir quelques problèmes à régler (spécificité, plus de propriétés à ajouter, etc.).

Bien sûr, nous pouvons créer une grosse machine avec Sass pour produire plusieurs builds et utiliser des outils comme UnCSS pour supprimer ce qui n’est pas nécessaire, mais soyons honnêtes : c’est ennuyeux et peut conduire à des morceaux de code « non naturels »comme dans l’exemple précédent.

Pourquoi les propriétés logiques CSS sont parfaites/prometteuses

C’est là qu’intervient le module de propriétés logiques CSS. L’idée principale de ce module CSS est d’avoir un abstraction logique qui nous permet de produire un dessin qui s’adaptera en fonction du sens du texte et du mode d’écriture (propriétés comme writing-mode, directionOui text-orientationSoit dir attribut en HTML). Cela nous donne des possibilités comme horizontal de droite à gauche ou de gauche à droite, RTL vertical, etc.

Mise en œuvre dans la pratique

Comment ça marche

Il y a quelques concepts à comprendre, déjà expliqués par Rachel Andrews ici dans « Understanding Logical Properties and Values »:

  • Nous ne pensons plus en termes de left/right mais start/end (De même pour top/bottom):
  • on ne dit plus width Soit height Mais plutôt inline Oui block – assez classique. (Vous avez probablement entendu parler du réglage par défaut inline Soit block éléments. ?)

cette idée de start/end pas nouveau. Vous l’utilisez probablement tous les jours avec des choses comme justify-content: start.

Félicitations, vous savez, presque, tout ! ? Voyons quelques exemples pratiques.

exemples

Commençons par les bases:

propriété classique propriété logique
width inline-size
height block-size
min-width min-inline-size
min-height min-block-size
max-width max-inline-size
max-height max-block-size

Les marges suivent la même logique :

propriété classique propriété logique
margin-top margin-block-start
margin-bottom margin-block-end
margin-left margin-inline-start
margin-right margin-inline-end

de même pour padding. Passons au positionnement :

propriété classique propriété logique
top inset-block-start
bottom inset-block-end
left inset-inline-start
right inset-inline-end

Simple, non ? float, text-alignOui border suivre le même chemin :

Propriété/Valeur classique propriété logique
float: left; float: inline-start;
float: right; float: inline-end;
text-align: left; text-align: start;
text-align: right; text-align: end;
border-top border-block-start
border-bottom border-block-end
border-left border-inline-start
border-right border-inline-end

Je ne détaillerai pas d’autres comme resize Soit scroll-margin-topmais examinons plutôt le cas particulier de border-radius:

propriété classique propriété logique
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

Un peu différent, mais facilement compréhensible tout de même.

Certaines possibilités avec des valeurs sont vraiment cool – vous pouvez simplifier certaines notations. Voici quelques exemples supplémentaires :

Propriété/Valeur classique propriété logique
margin-left: auto;
margin-right: auto;
margin-inline: auto;
margin-top: 0;
margin-bottom: 0;
margin-block: 0;
margin-top: 1em;
margin-bottom: 2em;
margin-block: 1em 2em;
top: 0;
left: 0;
bottom: 0;
right: 0;
inset: 0; ?
left: 10%;
right: 10%;
inset-inline: 10%;

C’est de l’or pur dans le meilleur des mondes, n’est-ce pas ? Moins de code pour une prise en charge parfaite du langage RTL ! ?

Maintenant, je suis désolé d’ôter certaines des étoiles de vos yeux; en fait, il y a certaines limites.

Plus après le saut! Continuez à lire ci-dessous ↓

certaines limites

syntaxe manquante

Les propriétés CSS logiques sont assez nouvelles, même si le support est bon dans les navigateurs récents. Cependant, le module CSS Logical Properties est un peu « jeune » et nécessite un niveau 2.

Pour donner un exemple simple : notre composant toggle utilise des transformations CSS entre différents états (chargement, actif, etc.), principalement parce que transform c’est un moyen fiable d’avoir des transitions ou des animations fluides.

Donc, nous avons quelque chose comme ça :

.element {
   transform: translateX(#{$toggle-width - $toggle-width-button});
}

Malheureusement, il n’y a pas de syntaxe relative au flux pour transform. Donc, nous devons faire quelque chose comme ceci :

[dir="rtl"] .element {
    transform: translateX(-#{$toggle-width - $toggle-width-button});
}

Si vous voulez avoir une idée des choses qui manquent comme celle-ci, vous pouvez vérifier les problèmes ouverts dans les accessoires CSS logiques.

Propriétés abrégées

Certaines notations abrégées ne sont actuellement pas prises en charge, telles que les valeurs 2, 3 ou 4 pour margin:

Propriété/Valeur classique propriété logique
margin: 1em 2em; margin-block: 1em; /* top and bottom */
margin-inline: 2em /* left and right */
margin: 1em 2em 3em; margin-block: 1em 3em; /* top, bottom */
margin-inline: 2em /* left, right */
margin: 1em 2em 3em 4em; margin-block: 1em 3em; /* top, bottom */
margin-inline: 4em 2em /* left, right */

N’utilisez pas ces exemples classiques avec des besoins logiques. Vous trouverez des problèmes car cela ne fonctionne pas réellement. Il vaut mieux être explicite. De plus, c’est plus lisible, à mon avis.

Montrant quelques vrais problèmes et quelques solutions

Images où le sens de lecture est important

Certaines images ont une signification directe. Prenons l’exemple des cartes à thème :

Thèmes de protons dans LTR
Thèmes Proton dans LTR ( Grand aperçu )

Dans ce cas, si nous appliquions simplement des éléments RTL à cela, nous obtiendrions ceci :

Thèmes Proton sur RTL, mal faits
Thèmes Proton sur RTL, mal faits. (Grand aperçu)

L’ordre est RTL, mais chaque image ne ressemble pas à une interface utilisateur RTL. C’est la version LTR ! Dans ce cas, c’est parce que le sens de lecture de l’image véhicule une information.

Thèmes Proton sur RTL
(Grand aperçu)

Nous avons un assistant de classe CSS qui facilite vraiment la réalisation de cette solution :

[dir="rtl"] .on-rtl-mirror {
  transform: rotateY(180deg);
}

Cela s’applique également à toute image avec un sens de lecture, comme une flèche ou une icône à double chevron qui montre ou pointe vers quelque chose.

Styles/valeurs calculées via JavaScript

Disons que vous avez un plugin qui calcule un certain positionnement en JavaScript et fournit la valeur que vous pouvez utiliser en JS ou CSS. La bibliothèque déroulante que nous utilisons fournit uniquement les left valeur dans les deux contextes RTL/LTR et transmettez-la à CSS à l’aide d’une propriété personnalisée CSS.

Donc, si nous utilisions cela avec des propriétés logiques, c’est-à-dire inset-inline-start: calc(var(--left) * 1px);nous obtiendrions ce qui suit en cliquant sur le menu déroulant de l’utilisateur :

La liste déroulante de l'utilisateur s'ouvre sur le côté opposé de l'interface, pas près de son bouton d'ouverture
(Grand aperçu)

La solution est simple ici. On garde la propriété non logique :

/* stylelint-disable */
top: calc(var(--top) * 1px);
left: calc(var(--left) * 1px); // JS provide left value only
/* stylelint-enable */
La liste déroulante des utilisateurs s'ouvre près de votre bouton d'ouverture
(Grand aperçu)

Et nous avons désactivé notre peluche pour ce cas particulier.

Mélanger le contenu RTL et LTR

Même avec les meilleurs modules CSS, tous ceux qui ont fait du portage RTL vous diront que mélanger du contenu RTL et LTR donne parfois (souvent) des choses folles.

Prenons un exemple sur Proton Drive avec un composant appelé MiddleEllipsis. Le but de ce composant est d’appliquer des points de suspension avant l’extension de fichier pour obtenir quelque chose comme my-filename-blahblahblah…blah.jpg.

Rien de fou : nous divisons le contenu en deux parties et appliquons text-overflow: ellipsis en premier. Vous pouvez vérifier la source de ceci MiddleEllipsis composant.

Appliquons du vieux RTL ; alors nous devrions obtenir ceci :

Affichage des fichiers sur Proton Drive, meilleure visualisation
(Grand aperçu)

Étrange, non ? C’est pourtant simple à expliquer :

  • MiddleEllipsis la structure est RTL ;
  • Et nous injectons du contenu LTR. (Rappelez-vous, nous avons coupé ce contenu LTR avec RTL.)

Le navigateur fait du mieux qu’il peut, et ce qui s’affiche n’est pas mal de son point de vue, mais cela n’a pas de sens pour une personne. Dans ce cas, nous choisissons de conserver l’affichage LTR pour conserver le but des noms de fichiers, mais en l’alignant à droite :

Affichage des fichiers sur Proton Drive, meilleure visualisation
(Grand aperçu)

Rechercher des modèles LTR natifs

Le MiddleEllipsis L’exemple a montré que si UGC est LTR, il est préférable de l’afficher en tant que LTR.

Mais on peut se demander s’il y a des motifs qui sont naturellement LTR. La reponse courte est oui. Vous trouverez ci-dessous un exemple.

Numéro de téléphone

Le numéro de téléphone pourrait être le cas le plus évident ici, car il utilise généralement des numéros occidentaux, qui doivent être lus LTR.

Si on lui applique directement des accessoires logiques, cela pourrait donner ceci :

Entrée téléphonique affichée en RTL, écran bizarre
(Grand aperçu)

Bien que techniquement pas faux, c’est un peu bizarre à montrer +33 6 12 34 56 78 J’aime ça. Dans ce cas, nous avons décidé de conserver la gamme LTR par défaut pour éviter ce résultat étrange.

Entrée téléphonique affichée en LTR
(Grand aperçu)

Nous avons le même cas pour une entrée 2FA utilisant des numéros occidentaux. Nous n’avons pas encore le cas, mais imaginez une entrée en 4 parties pour entrer une adresse IP. Cela n’aurait aucun sens de le montrer entièrement RTL comme les gens le comprendraient. 1.0.163.192 au lieu de 192.163.0.1.

Compatibilité

Le plus gros problème auquel nous avons été confrontés concernait principalement la compatibilité. Cela peut être vu dans Puis-je utiliser des tables pour les supports logiques ?

Puis-je utiliser des tableaux pour les supports logiques ?
Puis-je utiliser des tableaux pour les accessoires logiques (grand aperçu)

Si la cible n’est que les navigateurs modernes récents, pas de problème. Mais si des versions plus anciennes de Safari sont nécessaires, par exemple, le support est assez mauvais. Et dans ce cas, les propriétés CSS logiques ne sont pas dégradées correctement. Par conséquent, tout peut sembler cassé.

Plusieurs options sont possibles :

  • Il sert une version CSS pour les navigateurs modernes et une pour les navigateurs plus anciens ;
  • Tout transpiler pour chaque cas.

Dans le cas de Proton, comme nous n’étions pas tout à fait prêts à livrer un langage RTL lorsque nous l’avons fusionné, et pour d’autres raisons, la décision a été prise de tout transpiler vers les bonnes vieilles propriétés CSS. Nous avons récemment trouvé une solution pour un cas qui nécessitait le support RTL pour la langue farsi (compte VPN) :

  1. Nous avons créé deux fichiers CSS : un moderne avec des accessoires logiques et un hérité ;
  2. Nous chargeons le moderne;
  3. Nous avons testé le support correct de border-start-start-radius;
  4. S’il n’est pas pris en charge, nous revenons à l’héritage.

conclusion

Même si la perfection absolue est hors de ce monde, passer aux propriétés CSS logiques est un déménagement vraiment intéressant et un bon pari pour l’avenir: Nous écrivons moins de code avec ces plugins CSS logiques et réduisons la quantité de travail futur en les utilisant, donc ça va vraiment dans une direction passionnante.

En conclusion, et même si cela nécessitait plus de travail, nous avons testé un affichage RTL vertical pour tester des propriétés CSS plus logiques.

Affichage vertical de droite à gauche, en mode écriture
(Grand aperçu)

Cela semble assez intéressant, n’est-ce pas? ?

  • « Ressources W3C i18n », W3C.org
  • « Style RTL 101 », Ahmad Shadeed
  • « Quels langages utilisent les scripts RTL ? », Richard Ishida, W3C
  • « Problèmes ouverts dans les pièces jointes logiques CSS », W3C, GitHub
  • « Propriétés et valeurs logiques CSS », Docs Web MDN
  • « Principes fondamentaux de l’algorithme bidirectionnel Unicode », Richard Ishida, W3C
  • « Propriétés et valeurs logiques CSS de niveau 1 », ébauche de travail du W3C
  • « Publication assistée par ordinateur multilingue : Trucs et astuces #3 », Kirill Fedotov, InText
  • « Comprendre les valeurs et les propriétés logiques », Rachel Andrew
édito fracassant
(Oui oui)

Laissez un commentaire

Derniers Posts
Une Question ? Un Projet ?
Quel que soit votre projet, MIOR AGENCY vous écoute, analyse vos besoins et propose des pistes de travail en conséquence. Vous avancez avec sérénité et confiance.