David Madore's WebLog: J'essaie d'ajouter la possibilité de régler la taille du texte sur ce site

[Index of all entries / Index de toutes les entréesLatest entries / Dernières entréesXML (RSS 1.0) • Recent comments / Commentaires récents]

↓Entry #2777 [older| permalink|newer] / ↓Entrée #2777 [précédente| permalien|suivante] ↓

(lundi)

J'essaie d'ajouter la possibilité de régler la taille du texte sur ce site

Un des principes complètement stupides et insupportables du Web (j'en parlais notamment dans ce billet il y a quelques mois) est que c'est l'auteur d'une page (ou site) Web qui choisit tous les détails de l'apparence de celle-ci. L'habitude qu'on a de ce principe peut faire oublier son absurdité, mais je ne sais vraiment pas quel sens ça peut avoir que ce soit moi, auteur de ce blog, qui décide la couleur de fond de la page, ou la police de caractère avec laquelle vous lisez ces mots : ces choix stylistiques m'ont surtout valu des critiques pour mes goûts de merde, mais c'est tout le principe qui est idiot — si on va critiquer ces choix, autant que ce soit le lecteur lui-même qui les fasse. Ce n'est pas à moi de décider quelle police vous semble la plus agréable pour lire du texte, ni la couleur qui offre le meilleur contraste, ni la taille qui convient le mieux à vos yeux peut-être myopes ou presbytes ou que sais-je encore : indépendamment du fait que j'ai (paraît-il) mauvais goût, je n'ai tout simplement pas les informations nécessaires pour prendre ces décisions.

Alors certes il y a des éléments d'apparence qu'il est normal que l'auteur du site choisisse. Par exemple si j'écris un texte sur les foobars et que j'avertis pour aider le lecteur à s'y retrouver, je vais indiquer les noms des foobars en les soulignant deux fois, en bleu pour les foobars bleutés et en rouge pour les foobars orangés, il faut que je puisse souligner deux fois et choisir la couleur. On comprend que ça puisse poser des problèmes d'interaction si le lecteur peut faire des choix d'apparence et que l'auteur peut en faire d'autres, et qu'il faut donc gérer des conflits éventuels ou des dépendances (du style : si le lecteur a choisi un thème sombre je vais plutôt utiliser un bleu et un rouge sombres, tandis que si le lecteur a choisi un thème clair je vais prendre des couleurs vives).

Reste que la situation actuelle, malgré de bonnes intentions de divers bouts des standards Web (comme CSS) laisse fort peu de pouvoirs entre les mains de l'utilisateur. (Enfin, en principe il a tous les pouvoirs : il peut ouvrir l'outil « inspecteur » de son navigateur et s'en servir pour modifier comme il veut la page qu'il consulte, ajouter des éléments de style, changer les tailles, les polices, etc., et d'ailleurs même le texte lui-même si ça lui chante. Mais en pratique, l'utilisateur moyen ne sait pas se servir de l'inspecteur de son navigateur, et même l'utilisateur expérimenté trouvera pénible de refaire ça à chaque visite, ou de devoir écrire un script Greasemonkey pour le faire automatiquement.)

La seule chose que les navigateurs Web ont fini par se décider à proposer de façon vraiment accessible, c'est un moyen de changer la taille en zoomant (ça se fait typiquement avec les touches contrôle-plus et contrôle-moins) ; Firefox propose même deux types de zoom : un zoom qui change texte et images, et un zoom qui ne change que le texte (mais comme le second — qui me semble préférable a priori — est peu utilisé donc mal testé, il souffre de divers problèmes et bugs, par exemple ça casse les capture d'écran). Pour une raison que je ne comprends pas du tout[#], cette fonction de zoom n'est pas proposée sous Firefox mobile (on peut certes zoomer par gestures sur l'écran, mais c'est un zoom qui ne réajuste pas la longueur des lignes à la taille de l'écran/fenêtre comme sur fixe ; tout est compliqué parce qu'il y a au moins trois types de zoom différents qu'on peut vouloir : cf. ce commentaire pour une explication plutôt correcte). Quoi qu'il en soit, ces mécanismes de zoom sont complètement spéciaux, c'est-à-dire qu'ils ne passent pas par le contrôle normal des déclarations de style CSS (ou alors ils interagissent bizarrement avec elles).

[#] Il faut dire aussi que je ne comprends pas grand-chose à la manière dont interagissent les différentes tailles dans un navigateur mobile : voir ce billet passé à ce sujet, à propos de l'ajout de la déclaration <meta content="width=device-width, initial-scale=1" name="viewport" /> à mon HTML dont j'avoue que je ne comprends pas vraiment ce qu'elle fait.

Il commence aussi à y avoir des mécanismes de sélection de thèmes sombre/clair, parce que beaucoup de gens veulent ça pour leur webapplications. Mais ça passe par un mécanisme ad hoc qui ne permet que de choisir un « thème » (voire un thème parmi deux) et certainement pas plein de propriétés orthogonales (police, taille du texte, longueur des lignes, couleurs). Donc un deuxième mécanisme de personnalisation différent, extrêmement limité dans sa portée.

Pour n'importe quoi d'autre que le zoom spécial proposé par le navigateur et la sélection d'un thème sombre/clair, le site Web doit proposer son propre mécanisme de personnalisation, et évidemment rien n'est standardisé pour aider à ce que l'utilisateur s'y retrouve facilement entre les sites ou puisse facilement faire les mêmes choix partout (ou au moins, soit sûr de ce que ces choix recouvrent). Il n'y a même pas de « pratiques recommandées » sur la manière de nommer les préférences, de les présenter à l'utilisateur, de les ordonner, ce genre de choses.

Bref, c'est le bordel.

Ces râleries générales étant dites, on m'a demandé (dans un commentaire posté sur le tout premier billet de ce blog, ce qui est raisonnable vu que je n'offre pas de moyen de faire un commentaire sur l'ensemble du site) de proposer un moyen de régler la taille du texte.

J'ai donc essayé (en m'inspirant du code qu'on m'a proposé, et en l'empirant à ma sauce) de faire quelque chose de ce genre. Forcément, ça passe par du JavaScript, mais comme ça ne rend pas le site inutilisable sans JavaScript (on ne verra juste pas cette fonction et tout marchera comme avant) ça me semble un usage parfaitement légitime de JavaScript. Pour les >99.9% d'utilisateurs qui ont JavaScript activé dans leur navigateur, vous devriez donc voir en bas de la page, juste au-dessus de la signature finale, des boutons permettant choisir la taille du texte que vous préférez. [Modification () : Pour éviter de trop encombrer l'espace, il faut d'abord cliquer sur le bouton ‘⚙’ pour faire apparaître les autres boutons.] Ce réglage est censé être persistant et s'appliquer à l'ensemble des pages de ce site (enfin, sauf quelques pages antédiluviennes qui sont dans un style complètement différent).

Reste que je ne suis pas très content de ce que j'ai fait, pour diverses raisons. Certaines raisons de mon mécontentement sont de la faute de mon incompétence, d'autres sont de la faute de choix (possiblement malheureux) que j'ai faits par le passé, d'autres sont la faute des technologies du Web, et encore d'autres je ne sais pas bien.

Les technologies Web c'est toujours le même truc : tous les chemins sont jonchés de petites crottes de ragondin, et à chaque fois qu'on veut faire un truc on n'arrête pas de marcher dessus. Il y a toujours plein de choses qui font presque ou à peu près ce qu'on veut, mais à chaque fois on découvre des limitations à la con qui empêchent de s'en servir comme on voudrait.

D'abord, il y a une question toute bête d'interface utilisateur ; sous quelle forme proposer à l'utilisateur de changer la taille du texte ? J'ai choisi de mettre ça en bas de la page, avec des boutons à cliquer pour choisir diverses tailles entre 8 pixels et 20 pixels (enfin, j'écris pixels mais il faut considérer que c'est une unité un peu arbitraire, notamment sur mobile, donc je montre un échantillon de chaque taille après le bouton). Je ne sais pas si cette interface est terrible : peut-être qu'un menu déroulant aurait été mieux ? Peut-être vaudrait-il mieux mettre ça en tête de page ? (Je n'aime pas trop l'idée de mettre en tête de page quelque chose qu'on ne va pas toucher souvent, mais d'un autre côté si on veut essayer plusieurs tailles et que c'est en fin de page, on risque de devoir rescroller jusqu'à la fin.) Bref, concevoir des interfaces utilisateurs est un métier, ce n'est pas le mien, je suis profondément incompétent là-dessus, et ça devrait faire partie des standards du Web, pas quelque chose qu'on me demande d'improviser.

D'ailleurs est-ce que j'aurais dû proposer une liste de tailles espacées logarithmiquement plutôt que linéairement ? Je n'en sais rien. Mais bon, ça je pense que ça n'a vraiment pas d'importance.

Question interface, il y a aussi le choix de la langue : j'ai mis le texte invitant à changer la taille (change site font size) en anglais, par simplicité, mais si j'avais été motivé au point de l'écrire en plusieurs langues, je ne sais pas très bien comment j'aurais dû choisir la langue (en fonction de la langue préférée du navigateur ? en fonction de la langue de la page où le choix s'insère ?).

Ensuite, il y a un problème de ce que signifie la taille par défaut : parce que avant de rajouter ce réglage, j'avais déjà fait un choix par défaut, à savoir une taille de 12px si la largeur de fenêtre est ≤640px, 14px si elle est ≤720px, et 16px au-delà (cf. ce billet passé). En fait, je ne sais même pas bien ce que la taille de fenêtre signifie exactement ici, mais ce choix par défaut est le résultat d'un compromis laborieux. (Si on met une seule taille, il est juste impossible d'avoir un truc utilisable à la fois sur un navigateur mobile et sur un fixe.) Du coup, si la taille par défaut dépend de la largeur, ce n'est pas clair comment je dois présenter à l'utilisateur le choix de revenir à la taille par défaut ! Ce n'est même pas très clair pour moi comment je peux, en JavaScript, lire la taille par défaut[#2]. Bon, bref, j'ai mis un bouton pour revenir au défaut (c'est-à-dire à la taille choisie en fonction de fenêtre), mais ça peut sembler confus d'avoir un bouton reset en plus du bouton de la même taille.

[#2] Oui, rien que lire la taille par défaut n'est pas évident : si j'ai du CSS qui dit quelque chose comme @media (max-width: 640px) { body { font-size: 12px; } } @media (min-width: 641px) and (max-width: 780px) { body { font-size: 14px; } } @media (min-width: 781px) { body { font-size: 16px; } et que je veux récupérer la valeur de font-size de l'élément body, ben… ça n'a pas l'air facile. L'idée naturelle serait d'appeler getComputedStyle(), mais il s'avère que quand Firefox est en mode zoom où il ne zoome que le texte (et pas les images), la valeur de font-size renvoyée par getComputedStyle() tient compte de ce zoom (alors que si on cherche à modifier la propriété, ben le zoom s'applique dessus, donc si on lit et qu'on réécrit ce n'est pas idempotent !). C'est vraiment l'exemple de petite crotte de ragondin qui parsème n'importe quelle tentative de faire n'importe quoi avec CSS et JavaScript.

Encore un autre problème est de savoir comment stocker la préférence de l'utilisateur. Il y a la possibilité de positionner un cookie pour ça : je n'aime pas trop les cookies, parce que d'abord c'est plein de bizarreries incompréhensibles (notamment qu'on reçoit la chaîne de tous les cookies positionnés et qu'il faut ensuite analyser soi-même), et puis il n'y a pas de raison que la préférence soit communiquée à mon serveur dans la requête HTTP (je n'ai pas à savoir quelles tailles mes utilisateurs ont choisies), ce qui serait le cas avec un cookie. Donc j'ai plutôt opté pour une variable en local storage, ce qui est plus propre et plus moderne, mais je ne sais pas si j'ai bien fait (ça peut passer pour un cookie « sous le radar », et des gens n'aiment pas).

Il y a un point sur lequel je me suis moi-même un peu tiré une balle dans le pied, c'est que le JavaScript de ce site (comme le CSS) n'est pas inclus par référence, depuis un fichier JavaScript qui serait chargé en plus du HTML, il est incorporé directement dans le HTML. (Ma motivation était que j'aime que les fichiers HTML soient autonomes : on peut prendre le HTML d'un billet de mon blog et, tant qu'il n'y a pas d'images dedans, le sauvegarder dans un fichier et le lire tel quel sans avoir à ajouter un machin point js et un bidule point css à côté[#3].) J'ai une infrastructure Java sur le serveur qui inclut un fichier JavaScript commun dans chaque HTML du site (soit généré statiquement pour la plupart des pages, soit généré dynamiquement par Tomcat pour les entrées individuelles du blog). Comme je viens de le dire, ça peut présenter un intérêt ; mais pour tester du JavaScript et le modifier, ça devient vite un calvaire, parce que ça demande de régénérer la page pour chaque essai.

[#3] Raison principale pour laquelle je refuse d'utiliser des trucs comme jQuery ou analogue : ça me semble indispensable qu'on puisse sauvegarder un fichier HTML comme un simple fichier et le lire ensuite n'importe où avec une adresse en file:/// si besoin. Ce qui interdit l'appel à n'importe quel truc JavaScript externe, et notamment jQuery (lequel est beaucoup trop gros pour qu'il soit sérieusement envisageable de l'incorporer directement). C'est là encore une des crottes de ragondin — enfin, plutôt une merde de mammouth pour le coup — qui pollue le Web, qu'il n'y a aucun moyen simple, fiable et robuste de sauvegarder une page Web, avec toutes ses dépendances, et pouvoir la relire ensuite localement.

Mais il y a surtout une chose qui m'est insupportable, c'est si le changement de taille de texte n'est pas transparent mais apparaît après que la page a chargé ; autrement dit, si on voit d'abord la page s'afficher à la taille par défaut, pour ensuite changer et prendre celle qui a été choisie comme préférence. Non seulement c'est visuellement horripilant et très déstabilisant à la lecture, mais en plus ça risque de casser complètement les liens internes (si le navigateur positionne la vue d'après l'ancre qu'on lui a donnée puis change la taille du texte, on risque de voir un autre bout du texte que celui que pointait le lien qu'on a suivi).

J'ai cherché à éviter ce problème en réglant la taille de la police par une fonction JavaScript exécutée dès que l'élément <body> est créé (en gros j'appelle une fonction JavaScript onEarly() depuis le HTML immédiatement après avoir ouvert l'élément <body> de manière à pouvoir régler document.body.style.fontSize dedans, et cette fonction ne fait quasiment que ça pour ne pas retarder le chargement de la page). Cette solution semble marcher sous Firefox mais pas sous Chrome (enfin, sous le Chromium que j'ai pour tester). Je ne sais pas pourquoi : sous Firefox tout marche comme je voudrais, mais sous Chrome je vois d'abord la page s'afficher à la taille par défaut et ensuite changer de taille sous mes yeux — précisément ce que je voulais éviter. À vrai dire je ne comprends pas vraiment (← ceci est un euphémisme pour pas du tout) le synchronisme du JavaScript : à quel moment le code est exécuté, à quel moment on a accès au DOM, à quel moment on peut ajouter du CSS, etc. Donc je ne sais pas à quel moment il faut se positionner pour pouvoir exécuter du JavaScript qui puisse modifier le style de l'élément <body> en ayant la garantie que rien n'a encore été affiché à l'écran : si quelqu'un comprend ce qui se passe avec Chrome et pourquoi il ne se comporte pas comme Firefox à cet égard, qu'il me le dise. Correction : Juste après avoir écrit ça, je reteste et je m'aperçois que ça semble marcher comme je veux, aussi bien sous Chrome que sous Firefox ; je ne sais pas ce qui s'est passé, j'ai dû brièvement passer dans un univers parallèle, ou peut-être que je me suis fait avoir par un mécanisme de cache quelconque.

Toujours est-il que j'ai fait un truc. Je ne suis pas très content de ce truc, mais il marchouille. Si vous avez des suggestions pour le rendre plus élégant, plus robuste, plus intuitif, je suis preneur, mais comme je commence à en avoir sacrément marre à ce stade, toute modification qui requiert des efforts de ma part au-delà du simple copier-coller d'un code qu'on me donnerait va sans doute juste être ignorée.

Ajout : Puisque la longueur des lignes est aussi une râlerie fréquente concernant le style de ce site, j'ai aussi ajouté un jeu de boutons permettant de le régler (entre 50 et 150 caractères par ligne).

Nouvel ajout () : Pour éviter de trop encombrer l'espace visuel, j'ai caché les boutons de réglage de la taille du texte et de la longueur des lignes derrière un bouton ‘⚙’ qui fait apparaître les autres réglages. J'ai aussi ajouté des scrollIntoView() pour que les boutons restent en vue quand on les utilise.

Néanmoins, si mon truc donne grosso modo satisfaction, je verrai si je peux le mettre aussi sur les pages de commentaires du blog (qui sont gérées de façon complètement différentes, par un script Perl antédiluvien auquel je préfère toucher le moins possible, donc j'attends d'être sûr d'avoir le bon JavaScript avant de le recopier).

↑Entry #2777 [older| permalink|newer] / ↑Entrée #2777 [précédente| permalien|suivante] ↑

[Index of all entries / Index de toutes les entréesLatest entries / Dernières entréesXML (RSS 1.0) • Recent comments / Commentaires récents]