Comment développer un éditeur de texte pour le Web
Publié: 2022-03-10Je travaille pour Readymag, qui crée un outil de conception basé sur un navigateur qui aide les gens à créer des sites Web, des portefeuilles et toutes sortes de publications en ligne, sans codage. De nombreux widgets sont disponibles dans notre outil, et le widget texte est l'un des plus utilisés.
Le widget de texte est un champ de saisie de texte dans lequel l'utilisateur peut styliser le texte à l'aide d'une série de commandes dans l'éditeur. Chaque contrôle applique une propriété CSS au texte. Du côté de l'utilisateur, cela ressemble à un champ ordinaire pour saisir du texte, mais un grand nombre de processus complexes sont cachés derrière son apparente simplicité.
Dans cet article, j'expliquerai les défis auxquels mon entreprise a été confrontée et les solutions que nous avons utilisées pour créer un widget texte dans notre application. Je vais également plonger dans la façon dont nous l'avons implémenté et ce que nous avons appris en cours de route - et comment la saisie sur le Web fonctionne en général.
Modification de texte sur le Web
Il existe plusieurs façons d'implémenter des champs de saisie de texte sur le Web. Nous pourrions utiliser un simple champ de texte, ou un élément textarea
multiligne, ou l'attribut contenteditable
pour rendre une entrée modifiable, ou document.designMode = on
. Comment sont-ils différents?
Les éléments input
et textarea
sont idéaux pour ajouter du texte à une page, mais ils ne fournissent pas une expérience de formatage de texte riche. Pour cela, nous pouvons utiliser l'attribut contenteditable
pour rendre presque tous les éléments modifiables et permettre l'utilisation de styles de texte.
Si vous avez besoin de modifier la page entière en une seule fois, vous pouvez utiliser document.designMode
. Ce mode permet de modifier n'importe quel élément d'un document donné, même un iframe
.
Nous avons opté pour l'attribut contenteditable
, qui inclut toutes les fonctionnalités d'édition de texte nécessaires. Avec cet attribut, tout texte sur la page devient modifiable, ce qui est très important si nous voulons permettre aux gens de styliser le texte avec CSS . Par exemple, les utilisateurs peuvent ensuite styliser des sections sélectionnées ou l'intégralité du texte directement.
Styles de texte et propriétés de police
Nous permettons aux utilisateurs de styliser le texte comme ils le souhaitent en leur donnant accès à toutes les options fournies par CSS. En plus des propriétés bien connues, telles que la police, le style, la couleur et la décoration, nous donnons aux utilisateurs la possibilité d'utiliser les fonctionnalités de police OpenType, telles que les ligatures, les ensembles stylistiques, les fractions, etc. Ces fonctionnalités fonctionnent via la propriété CSS font-feature-settings
, qui permet aux utilisateurs de personnaliser les styles de texte.
Note : Je recommande fortement la lecture de l'excellent article de Sparanoid présentant toutes les fonctionnalités d'OpenType.
La typographie moderne a fait un grand pas en avant, permettant l'utilisation de polices variables sur le Web via la propriété font-variation-settings
.
Chaque police variable possède des propriétés variables dont vous pouvez modifier les valeurs. Par exemple, dans une police standard, vous pouvez modifier l'épaisseur de la police en utilisant des valeurs strictement spécifiées ( 400
, 500
, 600
, etc.), tandis que dans une police variable, vous pouvez utiliser n'importe quelle valeur dans la plage disponible, offrant des possibilités plus étendues pour le style de texte.
.style-1 { font-weight: 600; } .style-2 { font-variation-settings: "wght" 777; }
Ci-dessous, vous pouvez voir un exemple d'utilisation d'une police variable dans un widget de texte.
En plus des valeurs enregistrées ( wght
, wdth
, slnt
, etc.), les créateurs de polices peuvent également créer leurs propres caractéristiques de police uniques (comme dans l'exemple ci-dessus). Pour donner à nos utilisateurs la possibilité d'utiliser toutes les fonctionnalités de police possibles, nous avons d'abord besoin de ces informations.
Toutes les fonctionnalités que vous souhaitez utiliser doivent être définies dans le fichier de police. Voyons ses spécifications. Chaque police peut être représentée sous forme de tableaux, fournissant toutes les différentes informations utilisées lors du rendu de ses caractères.
Nous utilisons deux tables pour collecter ces informations sur les polices :
- Tableau de substitution des glyphes
La table de substitution de glyphes (GSUB) contient une liste de données de rendu de glyphes. L'objetGSUB.featureList
est une énumération des fonctionnalités de police et de leurs propriétés. Vous pouvez afficher un exemple de données dans le tableau sur GitHub. Dans ce tableau, le champtag
est le plus intéressant. Il s'agit du nom de la fonctionnalité de police, et il indique que cette fonctionnalité est disponible avec cette police. Nous pouvons utiliser en toute sécurité latag
dans la propriétéfont-feature-settings
. - Tableau des variantes de police
La table des variations de police (fvar) est une représentation des propriétés variables associées à une police. Un exemple de tableau est également disponible sur GitHub. Chaque objet est une propriété de police, avec une description des valeurs possibles (min
,max
, default) et un nom localisé (le cas échéant). Nous utilisons ces valeurs avec la propriétéfont-variation-settings
.
À l'aide de ces deux tableaux, nous pouvons couvrir l'ensemble de nos besoins : utiliser des propriétés de police variables et diverses fonctionnalités de police. Les données résultantes sont affichées dans les contrôles de widget de texte de l'éditeur, où les utilisateurs peuvent styliser le texte sans utiliser de code.
Utilisation de votre clavier
La saisie de texte est l'un des aspects les plus importants de l'expérience utilisateur du widget texte. En plus d'activer des raccourcis pour travailler avec du texte, nous avons dû faire face à des défis inhabituels. La navigation dans le texte avec les touches fléchées en faisait certainement partie.
Pendant que l'utilisateur édite, le widget de texte affiche également des caractères masqués, tels que des espaces insécables et des sauts de ligne. Elles sont implémentées sous forme d'icônes SVG insérées dans le texte, ce qui pose problème : si on utilise contenteditable
, alors ces icônes empêchent les utilisateurs de déplacer leur curseur avec les touches fléchées.
La solution est assez simple : utilisez un span
et le pseudo-élément :before
. De cette façon, le navigateur perçoit l'icône comme étant du texte et les touches fléchées fonctionnent très bien.
span:before { content: ""; height: 1em; position: relative; background-repeat: no-repeat; background-image: url("data:image/svg+xml,..."); background-position: center bottom; background-size: 1em; }
Raccourcis
Il existe deux raccourcis clavier pour coller du texte dans un widget de texte.
Cmd / Ctrl + V colle le texte du presse-papiers et conserve tous les styles qu'il avait dans le document d'origine. Si le texte a été copié à partir d'une application telle que Pages, Notes, Word ou Google Docs, votre presse-papiers contiendra des informations HTML, et pas seulement du texte brut. Ce code HTML peut être analysé et collé tout en conservant les styles d'origine.
Vous pouvez obtenir les données HTML comme suit :
// https://www.w3.org/TR/clipboard-apis/#reading-from-clipboard document.addEventListener('paste', (e) => { const text = e.clipboardData.getData('text/plain'); const html = e.clipboardData.getData('text/html'); handlePaste(); });
De plus, nous avons le raccourci Cmd + Maj + V. Lorsque vous insérez du texte à l'aide de cette combinaison de touches, le navigateur laisse les données brutes dans la charge utile, de sorte que le style est contrôlé par la destination de collage. Ces raccourcis existent par défaut dans le navigateur, mais vous devez vous rappeler de les implémenter dans votre projet.
Sélection de texte et mise au point
La sélection de texte aide les utilisateurs à voir quel morceau de texte est en cours de modification. Essayons un exemple simple : un champ de saisie avec un bouton pour contrôler la mise en gras du texte.
Dans cet exemple, nous pouvons sélectionner un morceau de texte et appuyer sur le bouton Bold
, et la sélection dans le texte restera ensuite. Et si notre exemple était plus compliqué ? Disons que nous ajoutons un champ de saisie au sélecteur de taille de texte. Dans ce cas, le focus se déplacera vers la nouvelle entrée.
Il existe deux options pour résoudre ce problème :
- Après chaque événement d'entrée, nous forçons le focus à revenir au bloc de texte. Dans ce cas, la sélection commencera à clignoter après un certain nombre d'événements d'entrée — nous ne le voulons pas.
- Nous pouvons ajouter le bloc de texte à un
iframe
. Comme vous le savez probablement, uniframe
a son propre objetwindow
global. Ainsi, tant que la sélection se trouve dans l'iframe
, elle persistera même si le focus à l'extérieur est déplacé.
Nous nous sommes retrouvés avec un widget de texte enveloppé dans une iframe
. Ainsi, tant que la sélection se trouve dans l' iframe
, elle persistera même si le focus à l'extérieur est déplacé. Jetez un oeil à la capture d'écran ci-dessous. Nous avons deux sélections sur la page : le fragment sélectionné dans le widget de texte et la valeur sélectionnée de la taille du texte dans le contrôle.
Performances lors de la saisie de texte
La réactivité de votre interface d'édition de texte est importante. Surveillez de près la valeur d'images par seconde (FPS), en particulier lorsqu'il s'agit de tâches telles que l'édition de texte à grande vitesse ou la modification de la taille de la police.
Readymag a deux fenêtres : bureau et mobile . Les styles de texte peuvent apparaître différents dans chacun. Pendant la saisie du texte, l'éditeur effectuera divers calculs pour synchroniser les données entre les fenêtres. Une grande réactivité est obtenue en utilisant l'API du navigateur : requestAnimationFrame
et requestIdleCallback
:
-
requestAnimationFrame
est appelée à chaque rafraîchissement de l'écran ; -
requestIdleCallback
est appelé uniquement lorsque le navigateur est inactif.
C'est un excellent moyen d'effectuer des opérations fastidieuses sans bloquer le thread principal.
Accessibilité
L'activation de l'accessibilité est l'une des pratiques les plus importantes dans le développement Web aujourd'hui. Si votre site Web est conçu dans un souci d'accessibilité, il permettra à davantage de personnes d'accéder à votre produit . Cela signifie accueillir non seulement les personnes handicapées, mais également les utilisateurs sur différentes plates-formes : appareils de bureau et tactiles, lecteurs d'écran, appareils auditifs, etc. Pour comprendre à quel point il est important de rendre les projets accessibles, je vous recommande de consulter les statistiques récentes sur l'accessibilité.
Pour commencer à intégrer les pratiques d'accessibilité Web, consultez d'abord les Règles pour l'accessibilité des contenus Web (WCAG), la ressource la plus complète sur le sujet. Et tant que Readymag est un outil de publication, en plus des WCAG, nous devons également suivre les Authoring Tool Accessibility Guidelines (ATAG).
Notre équipe est actuellement au stade de l'intégration de l'accessibilité dans l'éditeur. Dans les articles suivants, nous partagerons plus d'informations sur notre parcours vers l'intégration complète de l'accessibilité chez Readymag. Vous pouvez également vérifier tout travail effectué avec Readymag en utilisant notre liste de contrôle d'accessibilité.
Les meilleures pratiques
Enfin, voici quelques conseils pour vous aider à développer un éditeur de texte sur le web :
- Réfléchissez bien à la mise en page.
Identifiez à l'avance les fonctionnalités dont vous avez besoin et comment vous allez travailler avec les éléments de l'éditeur de texte. - Mettre en place des tests visuels.
Lorsque vous travaillez avec du texte, vous ne pouvez pas vous fier entièrement au résultat du test d'instantané. Vous pouvez obtenir le résultat correct dans le test, en attendant le CSS donné pour le bloc, mais parfois le résultat peut ne pas être celui que vous attendiez. - Testez votre travail dans différents navigateurs.
Bien que la plupart des navigateurs prennent raisonnablement en charge les nouvelles fonctionnalités en ligne, l'affichage des mêmes styles dans différents navigateurs pose souvent des problèmes. - Utilisez des indicateurs de fonctionnalité pour un développement plus sûr de nouvelles fonctionnalités.
- Mesurez le FPS dans le navigateur lors de la saisie de texte.
N'effectuez pas de tâches gourmandes en CPU dans un seul thread. - N'ayez pas peur d'expérimenter .
- Enfin, essayez Text Widget dans Readymag.
Quelques liens utiles
- "La démo CSS complète pour les fonctionnalités OpenType", Sparanoid
- "Introduction aux polices variables sur le Web", web.dev
- "Une typographie géniale", Joel Galeran
- "Polices variables", Nick Sherman
- Kit de polices
- OpenType.js