J'aime travailler avec des composants stylisés. Ils vous permettent d'écrire du CSS dans votre JavaScript, en gardant votre CSS très proche de votre JavaScript pour un seul composant. En tant que développeur front-end qui aime disséquer une page Web et la décomposer en composants réutilisables, l'idée de composants stylisés me procure de la joie. L'approche est propre et modulaire et je n'ai pas besoin d'aller fouiller dans un gigantesque fichier CSS pour voir si une classe dont j'ai besoin existe déjà. Je n'ai pas non plus à ajouter une classe à ce fichier CSS sans fin et se sentir coupable d'avoir rendu ce fichier déjà gigantesque encore plus grand.
Cependant, alors que je continue sur la voie de l'utilisation de composants stylisés, j'ai commencé à réaliser que, s'il est bon de séparer les styles CSS pour être spécifiques aux composants singuliers, je commence à me répéter beaucoup pour organiser mes styles par composant. J'ai créé de nouvelles déclarations CSS, et donc, de nouveaux composants stylisés, pour chaque composant, et je constate beaucoup de duplication dans mon CSS. Non, les composants stylisés ne sont pas toujours exactement les mêmes, mais deux des trois lignes de CSS correspondraient à deux des trois lignes de CSS dans un autre composant. Dois-je vraiment répéter ce code à chaque endroit où j'ai besoin de ces styles?
Prenez flexbox, par exemple. Flexbox est idéal pour les mises en page réactives. Il alignera les éléments d'une certaine manière et, avec des modifications minimes, peut être modifié pour avoir une belle apparence sur différentes tailles d'écran. Donc, plus souvent qu'autrement, je me retrouve à écrire:
display: flex;
flex-direction: row; /* the default; in react native, column is the default */
Presque aussi souvent, je me suis retrouvé à écrire:
display: flex;
flex-direction: column;
Les deux extraits de code ci-dessus sont assez courants: le premier prend tous les éléments enfants et les positionne l'un à côté de l'autre – de gauche à droite – dans une rangée. Le second prend tous les éléments enfants et les positionne au-dessus et en dessous les uns des autres – de haut en bas – dans une colonne. Chacun de ces extraits de code peut être rendu plus spécifique; cependant, nous pouvons ajouter différentes propriétés pour spécifier davantage comment nous voulons que les éléments enfants soient disposés sur la page. Si nous voulons que les éléments soient régulièrement espacés sur la largeur d'écran disponible, par exemple, nous pouvons ajouter la ligne suivante à chaque extrait de code:
justify-content: space-evenly;
De plus, il existe d'autres propriétés, comme align-items
que nous pouvons ajouter pour personnaliser davantage la disposition de ces éléments. Donc, si nous avons trois composants différents qui nécessitent tous une mise en page flexbox, mais ont des propriétés différentes supplémentaires, comment pouvons-nous utiliser des composants stylisés de manière non répétitive?
Au départ, il est logique de créer trois ensembles de styles pour chaque composant, comme ceci:
// component one
const ComponentOne = styled.div`
display: flex;
flex-direction: row;
justify-content: flex-start;
`
// component two
const ComponentTwo = styled.div`
display: flex;
flex-direction: row;
justify-content: space-between;
`
// component three
const ComponentThree = styled.div`
display: flex;
flex-direction: row;
justify-content: space-evenly;
`
Les styles énumérés ci-dessus feront l'affaire. Les trois composants ont des éléments enfants disposés en ligne – positionnés de gauche à droite – avec un espacement différent entre chaque élément enfant. Cependant, avoir les mêmes deux lignes de code répétées trois fois ajoute un gonflement CSS.
Pour éviter de nous répéter, nous pouvons étendre un composant de base à chacun des autres composants, puis ajouter les éléments supplémentaires dont nous avons besoin à ces composants:
// flex row component
const ExampleFlex = `
display: flex;
flex-direction: row;
`
// component one
const ComponentOne = styled(ExampleFlex)`
justify-content: flex-start;
`
// component two
const ComponentTwo = styled(ExampleFlex)`
justify-content: space-between;
`
// component three
const ComponentThree = styled(ExampleFlex)`
justify-content: space-evenly;
`
Cela fait beaucoup mieux. Non seulement cette version – où nous nous étendons de la
composant – supprime le code répétitif, mais il conserve également le code lié à l'affichage des éléments dans une ligne en un seul endroit. Si nous devions mettre à jour ce code lié à la direction des éléments dans une colonne, nous pouvons le faire en un seul endroit au lieu de trois.
Note importante: Lorsque vous étendez les styles d'un autre composant, les styles qui héritent de ce composant de base doivent être répertoriés après le composant de base, comme dans l'exemple ci-dessus. Placement
au dessus
provoquerait une erreur qui se lit comme suit: Uncaught ReferenceError: impossible d'accéder à «ExampleFlex» avant l'initialisation.
Pour pousser cette idée un peu plus loin, la démo suivante montre une situation où vous pourriez avoir besoin de styles similaires sur deux éléments d'interface utilisateur différents sur la page, mais ces éléments ont chacun leurs légères différences.
Comme vous pouvez le voir, la navigation qui se trouve en haut de la page et le pied de page qui se trouve en bas de la page doivent être disposés dans le sens des lignes sur des écrans plus grands, puis passer à une disposition en colonnes sur les appareils mobiles. Les deux éléments diffèrent, cependant, en ce que la navigation en haut de la page doit être alignée à gauche pour laisser de la place pour le logo à droite tandis que les liens de pied de page doivent être alignés à droite. En raison de ces différences, il est logique de créer deux composants de style différents pour chacun de ces éléments; la
élément pour la navigation supérieure et le composant pour le bas de la navigation de page.
Les meilleurs styles de navigation ressemblent à ceci:
const Navigation = styled.div`
align-items: center;
display: flex;
flex-direction: row;
justify-content: space-between;
padding: 10px;
width: calc(100% - 20px);
@media (max-width: 768px) {
flex-direction: column;
}
`
Alors que les styles de bas de page ressemblent à ceci:
const Footer = styled.div`
align-items: center;
display: flex;
flex-direction: row;
justify-content: flex-end;
padding: 10px;
width: calc(100% - 20px);
@media (max-width: 768px) {
flex-direction: column;
}
`
La seule différence entre ces deux éléments? le justify-content
propriété. De plus, le
utilisations des composants display: flex
avec la même requête multimédia.
En dehors de ces trois composants partageant une grande partie du même CSS, le
composant et
sont des composants de liaison très similaires avec de légères différences. Alors, comment on sèche ça?
En regardant l'exemple ci-dessous, vous verrez que le CSS réutilisé dans plusieurs composants peut être extrait dans son propre composant que nous étendons pour apporter les modifications spécifiques dont nous pourrions avoir besoin pour des composants plus spécifiques.
Avec les changements mis en place, notre fichier JavaScript qui contient tous les composants stylisés est 10 lignes plus court que la version précédente. Bien que cela puisse sembler une petite différence, à mesure que les applications se développent, ces modifications pourraient aider à minimiser le CSS fourni avec une application à mesure que des styles continuent d'être ajoutés.
Il y a aussi l'accessoire polymorphe "as"!
En plus d'étendre les styles d'un composant à un autre, styled-components nous donne également un accessoire polymorphe appelé «as» qui applique les styles d'un composant donné à un autre élément tant que ce nouvel élément est spécifié. Ceci est utile dans les situations où l'interface utilisateur de deux éléments peut avoir la même apparence, mais la fonctionnalité HTML sous-jacente derrière ces deux éléments est différente.
Prenons l'exemple des boutons et des liens sous forme de boutons. Bien qu'ils semblent avoir des fonctionnalités similaires à première vue – ils peuvent tous les deux être cliqués pour déclencher une action – les deux ont des objectifs fonctionnellement différents. Un bouton est idéal pour soumettre un formulaire ou modifier la mise en page de la page actuelle sur laquelle vous vous trouvez, mais un lien vous mènera à une ressource.
J'ai créé un stylo ci-dessous qui illustre cela. À première vue, les deux boutons se ressemblent. Cependant, celui de droite est en fait un élément stylé comme un bouton, tandis que celui de gauche est un élément réel
élément. Ces deux boutons pourraient faire partie d'une navigation sur le site sur toute la ligne, l'un devant être lié à un site externe. Lors d'une première tentative de construction de ces deux éléments, il est logique de voir le code pour chaque composant comme dans le premier exemple que nous avons examiné.
Si nous savons que ces deux éléments auront exactement les mêmes styles, nous pouvons les styliser comme un , regroupant le composant stylisé avec le JavaScript qui accompagne le bouton que nous créons. Ensuite, nous appliquons ces mêmes styles exacts à un
composant que nous spécifions:
En regardant le stylo ci-dessus, vous pouvez voir que nous avons supprimé tous les CSS en double liés au style de ces deux éléments. Plutôt que de répéter le CSS pour le bouton à utiliser sur le composant de lien, nous pouvons appliquer la transmission d'une valeur à l'as prop comme suit:
Cela nous donne la possibilité de changer l'élément en une balise HTML tout en conservant les styles que nous avons déjà définis pour le Button.
Étendre les styles de base – et peut-être même en garder certains ensemble en un seul globalStyles.js
file – est un moyen efficace de SÉCHER le code de nos composants stylisés, ce qui le rend beaucoup plus gérable. Garder CSS au minimum améliore non seulement les performances d'un site Web, mais cela peut également éviter aux développeurs d'avoir à fouiller dans des lignes de CSS à l'avenir.