Pour les systèmes de conception, la cohérence et la compréhension sont essentielles. Un bon système de conception garantit la cohérence de la mise en œuvre grâce à la configuration du code qui l'implémente. Il doit s'agir de :
En utilisant ma pile par défaut de React avec Tailwind, je vais vous montrer comment définir vos propres valeurs par défaut pour la typographie, la couleur et l'espacement n'est pas seulement le point de départ pour différencier l'apparence de votre application. Plus important encore, cela réduit considérablement le code que nous devons écrire et maintenir, ce qui réduit la charge mentale liée à la mise en œuvre des styles de manière systématique, cohérente et sans erreur.
Je vais commencer par une critique majeure que je vois tout le temps, puis détailler une série d'étapes de configuration que j'utilise pour la résoudre.
Tailwind permet aux développeurs d'écrire facilement des styles, ce qui est idéal pour le prototypage rapide. Mais cette facilité ne garantit pas une bonne conception ou un système de conception évolutif et maintenable.
Les outils par défaut et sans configuration comme Tailwind constituent la couche de rythme d'infrastructure qui crée plus de temps pour la construction. Mais si vous faites évoluer une application qui utilise un système de conception pour se différencier, vous ne pouvez pas compter uniquement sur des configurations prêtes à l'emploi « gratuites comme au déjeuner ».
Si vous exécutez avec la configuration par défaut de Tailwind et poussez la gestion des styles vers l'application de classes sur les composants, le résultat est souvent un désordre de classes difficiles à raisonner réparties sur les composants, se faisant passer pour un système de conception.
Ci-dessus est un excellent exemple. C’est presque illisible et prend beaucoup de temps à comprendre, sans parler de manipuler. Les tentatives en ce sens sont très susceptibles d'entraîner des duplications et des erreurs, ce qui s'éloignera de la cohérence de la conception dans l'ensemble de l'application.
Il est facile de regrouper vos classes de conception en un seul nom de classe. Mais il n’est pas facile de le savoir.
La facilité d'utilisation s'accompagne de compromis. Utiliser le standard de quelqu'un d'autre, c'est s'appuyer sur son savoir-faire. Cela peut être bénéfique, mais cela peut aussi être un piège. Prenons du recul et réfléchissons à ce que consistent les bases d'un système de conception :
Dans le contexte de React avec Tailwind, ces éléments et bien d'autres éléments du système de conception sont définis dans la configuration Tailwind, que nous pouvons personnaliser.
{/* plus joli-ignorer */}
const config = { theme: { fontSize: { /* ... */ }, colors: { /* ... */ }, spacing: { /* ... */ }, }, };
Avez-vous déjà eu du mal à vous souvenir de l'espacement correct des lettres pour votre petit texte ? Et si vous pouviez le régler une fois et l'oublier ?
Nous pouvons définir l'interlignage (hauteur de ligne) et le suivi (espacement des lettres) comme paramètres pour chaque tuple de taille de police directement dans tailwind.config. Cela signifie que nous n'avons pas besoin de définir un interligne ou un suivi lorsque nous utilisons une classe de taille de police. Pas besoin de se rappeler (ou de ne pas rechercher) quel est l'espacement des lettres d'un petit texte.
fontSize: { small: [ "13px", { lineHeight: 1.5, letterSpacing: "0.015em" }, ], base: [ "16px", { lineHeight: 1.5, letterSpacing: 0 }, ], }
L'utilisation de text-small définit désormais la taille de la police, la hauteur des lignes et l'espacement des lettres. Le fait de regrouper le tuple typographique principal dans une seule classe centralise la mise en œuvre de ces valeurs dans la configuration plutôt que dans une base de code. Une énorme victoire pour la maintenabilité.
/* 13px/1.5 with 0.015em letter-spacing */
Nous pouvons utiliser des variables CSS pour définir des couleurs réactives sous les scopes :root et html.dark. Cela signifie que nous écrivons et gérons une seule classe, comme bg-canvas, au lieu de deux, comme bg-gray-100 dark:bg-gray-800.
@import "@radix-ui/colors/gray.css"; @import "@radix-ui/colors/gray-dark.css"; :root { --color-gray-base: var(--gray-1); --color-gray-bg: var(--gray-3); --color-gray-line: var(--gray-4); --color-gray-border: var(--gray-5); --color-gray-solid: var(--gray-10); --color-gray-fill: var(--gray-12); }
Parce que j'utilise Radix Colors ici, je n'ai pas besoin de définir la portée .dark car cela est déjà fait pour moi. Si vous n'aimez pas les couleurs Radix, vous pouvez les personnaliser, utiliser une autre bibliothèque ou écrire la vôtre.
Ensuite, définissez les variables CSS dans la configuration Tailwind.
colors: { canvas: "var(--color-gray-base)", background: "var(--color-gray-bg)", line: "var(--color-gray-line)", border: "var(--color-gray-border)", solid: "var(--color-gray-solid)", fill: "var(--color-gray-fill-contrast)", }
L'utilisation de bg-canvas définit désormais la couleur appropriée en mode clair ou sombre. La suppression de cette duplication dans une base de code centralise la gestion des couleurs dans notre configuration au lieu de la répartir sur l'implémentation des classes sur les composants. Une énorme victoire pour la cognition et la maintenabilité.
/* sets --gray-1 as #fcfcfc on :root or #111111 on html.dark */
Je préconise les noms sémantiques pour les couleurs et les tailles de police, car la dénomination sémantique est une fonction de forçage qui lie le sens à utiliser. Cela supprime les approximations de mise en œuvre et réduit les erreurs.
J'ai vu d'innombrables projets dans lesquels des gris-50, gris-100 ou gris-200 incohérents sont tous utilisés pour les arrière-plans. Ce problème est facilement résolu en définissant une couleur appelée arrière-plan.
De la même manière, il est plus facile de se souvenir des noms des couleurs de texte sombres et claires lorsqu'elles sont appelées remplissage et solide. C'est plus difficile et plus sujet aux erreurs lorsqu'ils sont appelés gris-900 et gris-600, car vous devez alors vous rappeler spécifiquement qu'il ne s'agissait pas de gris-950 et gris-500, ou de gris-800 et gris-700.
Mais nommer les choses – et se mettre d’accord sur leur nom – est difficile. Dans l'esprit de zéro configuration, je suggère de prendre le paradigme des arrière-plans, des bordures, des solides et des remplissages de Radix Color. Ou cette sémantique de palette.
Et une fois que vous avez défini cela dans tailwind.config, Typescript rafraîchira votre mémoire du bout des doigts avec la saisie semi-automatique.
Si vous étendez un thème Tailwind et n'écrivez pas le vôtre, n'utilisez pas une clé d'échelle qui a déjà été utilisée. Vous pouvez par inadvertance écraser une classe que vous devez utiliser.
Vous remarquerez dans l'exemple de configuration de couleur précédent que j'ai défini la variable --color-gray-base sur canvas, et non sur base. Si j'utilisais base, l'utilisation de cette échelle de couleurs comme couleur de texte (text-base) entrerait en conflit avec la valeur de base de taille de police par défaut, qui est également text-base.
Ce n'est pas un inconvénient de la personnalisation de la configuration de Tailwind, c'est un héritage de la dénomination de son thème : la définition des classes de taille de police ou de couleur dans Tailwind utilise toutes deux du texte-*.1
Nous pouvons également utiliser des variables CSS pour définir les espacements.
:root { --height-nav: 80px; --height-tab: 54px; --space-inset: 20px; --container-text-px: 660px; --container-hero-px: 1000px; }
spacing: { em: "1em", /* relate icon size to parent font-size */ nav: "var(--height-nav)", inset: "var(--space-inset)", text: "var(--container-text)", hero: "var(--container-hero)", }
On pourrait dire qu'il s'agit d'une ingénierie excessive. Sauf que lorsque vient le temps de calculer des mises en page interactives complexes comme des en-têtes collants, des marges de défilement, etc., ce travail de configuration initial le rend simple et sans erreur, au pixel près.
/* ... */
Notez encore une fois que l'utilisation de la dénomination sémantique facilite la mémorisation et l'utilisation.
Nous avons désormais configuré les jetons de typographie, de couleur et d'espacement d'une manière facile à comprendre et à gérer dans un endroit unique et centralisé. Et nous n'avons pas besoin d'écrire autant de classes pour implémenter le système. Gagnant. Et nous pouvons prendre d'autres mesures pour réduire ces frais de mise en œuvre.
Et si je vous disais qu'il existe un moyen d'éviter complètement d'écrire text-lg lg:text-xl xl:text-2xl p-2 md:p-4 lg:p-8 partout ?
Nous pouvons éviter de définir des classes de taille de police réactives en utilisant clamp comme valeur de taille de police dans tailwind.config. Voici la fonction de serrage simple que j'utilise.
fontSize: { title: [ /* clamp(17px, 14.1429px 0.5714vw, 21px) */ generateClampSize(500, 1200, 17, 21), { lineHeight: 1.5, letterSpacing: "-0.015em" }, ]; }
Donc, au lieu d'écrire text-lg lg:text-xl xl:text-2xl, nous pouvons simplement écrire text-title. Une fois de plus, en hissant la réactivité de la taille de police dans une valeur de serrage, nous évitons à nouveau l'écueil des « classes d'implémentation », économisant ainsi des efforts mentaux, des erreurs et du temps de débogage.
Gardez à l'esprit que cela signifie que nous sommes passés de text-lg lg:text-xl xl:text-2xl leads-none tracking-wide à text-title en configurant correctement Tailwind. Gagnant!
/* 17px at 500px, 21px at 1200, fluidly calculated inbetween */ /* …with default line-height and letter-spacing also specified */Heading copy
Nous pouvons également le faire pour l'espacement. Lors de l'extension d'un thème, je préfixe ces touches avec d pour "dynamique" pour le différencier de l'échelle d'espacement par défaut.
spacing: { /* lower value is 2/3 of upper value */ d4: generateClampSize(500, 1200, 10.5, 16), d8: generateClampSize(500, 1200, 21, 32), d16: generateClampSize(500, 1200, 43, 64), d24: generateClampSize(500, 1200, 64, 96), d64: generateClampSize(500, 1200, 171, 256), }
Cela nous permet d'écrire py-d24 au lieu de py-16 md:py-20 lg:py-24. Cela nous évite d’avoir à l’esprit une gamme de versions de sites Web pour chaque requête multimédia. Au lieu de cela, cela nous encourage à imaginer des mises en page fluides et réactives où les mesures importent moins que des relations cohérentes.
/* ... */ /* ... */
Une interface utilisateur bien conçue est votre dernière défense contre la vague à venir d'applications d'IA imprudentes. Voici comment la personnalisation de Tailwind peut vous faire gagner du temps et vous éviter des maux de tête afin que vous puissiez vous concentrer sur le soin irrationnel nécessaire pour créer une interface utilisateur qui fonctionne en un clin d'œil :
Oui, il y a un coût initial en termes de temps. Mais cela rapporte beaucoup : moins de code, moins d'erreurs, une plus grande cohérence de conception et une équipe qui comprend réellement le système.
Ensuite : nous explorerons comment utiliser Class Variance Authority pour créer une API de style à toute épreuve avec des accessoires sémantiques tirés de Tailwind. Restez à l'écoute.
C'est aussi pourquoi je n'aime pas utiliser tailwind-merge pour supprimer les classes Tailwind en double dans JSX. Le plus souvent, je trouve que cela supprime une couleur de texte au profit d'une taille de police de texte lorsque les deux sont nécessaires. Je suis surpris que davantage de développeurs ne soulèvent pas ce problème. ↩
Clause de non-responsabilité: Toutes les ressources fournies proviennent en partie d'Internet. En cas de violation de vos droits d'auteur ou d'autres droits et intérêts, veuillez expliquer les raisons détaillées et fournir une preuve du droit d'auteur ou des droits et intérêts, puis l'envoyer à l'adresse e-mail : [email protected]. Nous nous en occuperons pour vous dans les plus brefs délais.
Copyright© 2022 湘ICP备2022001581号-3