Catégories
Astuces et Design

Réalisation de l'alignement vertical (merci, sous-grille!)

Nos outils d'alignement vertical se sont beaucoup améliorés ces derniers temps. Mes débuts en tant que concepteur de sites Web impliquaient de disposer des conceptions de page d'accueil de 960 pixels de large et d'aligner les éléments horizontalement sur une page à l'aide d'une grille de 12 colonnes. Des questions médiatiques sont apparues, ce qui a nécessité un sérieux changement mental. Cela a résolu de gros problèmes, bien sûr, mais en a introduit de nouveaux, comme le traitement de l'alignement lorsque les éléments s'enroulent ou sont déplacés dans la mise en page.

Jetons un coup d'œil à un scénario particulier: une «barre» avec quelques boutons. Il existe deux groupes de ces boutons, chacun contenu dans un

avec un

.

Sur un grand écran, nous sommes tous prêts:

Deux groupes de deux boutons rose vif sur un fond sombre.

Et voici une méthode CSS très basique qui réalise cette mise en page et se décompose également en deux "lignes" à un point d'arrêt mobile:

.accessibility-tools fieldset {
  width: 48%;
  float: left;
  margin-right: 1%;
}


/* Mobile */
@media only screen and (max-width: 480px) {
  .accessibility-tools fieldset {
    width: 100%;
  }
}

Sur un petit écran, on se retrouve avec ceci:

Les deux mêmes groupes de deux boutons roses, avec un groupe de boutons empilés sur l'autre, montrant que les boutons sont de largeur inégale.

C'est le problème: le manque d'alignement vertical. Disons que nous voulons aligner ces boutons dans un arrangement plus agréable où les bords des boutons s'alignent bien les uns avec les autres.

Pour commencer, nous pourrions opter pour des solutions CSS à largeur fixe et basées sur des pixels pour forcer les éléments à s'aligner correctement à divers points d'arrêt, en utilisant des nombres magiques comme celui-ci:

/* Mobile */
@media only screen and (max-width: 480px) {
  legend {
    width: 160px;
  }
  button {
    width: 130px;
  }
}
les deux mêmes groupes de boutons roses mais où les boutons ont tous la même largeur constante et s'alignent uniformément.

Cela fait l'affaire.

Mais… ce n'est pas exactement une solution flexible au problème. Outre les nombres magiques (valeurs de pixels fixes basées sur un contenu spécifique), il reposait également sur l'utilisation de requêtes multimédias dont j'essaie de m'éloigner lorsque je le peux. J'en ai discuté dans un article intitulé «S'éloigner de Sass» sur mon blog.

Au fur et à mesure que je progressais vers certaines des fonctionnalités les plus modernes de CSS, la nécessité de cibler des tailles d'écran spécifiques avec un code unique a été supprimée.

Ce dont j'ai besoin, c'est de chaque bouton et étiquette pour répondre à:

  1. l'espace disponible
  2. leur contenu

et!

  1. D'autres éléments autour d'eux

Espace disponible

Le problème avec l'utilisation des requêtes multimédias est qu'elles ne prennent pas en compte l'espace autour des éléments qui sont en cours de réalignement – un point parfaitement démontré dans cette image de «The Flexbox Holy Albatross» par Heydon Pickering:

Trois navigateurs côte à côte. Le premier montre trois rectangles noirs sur une seule ligne, le second montre trois rectangles noirs empilés verticalement, et le troisième montre trois rectangles noirs placés à droite de l'écran.

Ce que je veux vraiment, c'est la seconde

envelopper sous le premier seulement quand ils ne peuvent plus s'adapter parfaitement sur une rangée.

Pouvons-nous faire cela avec flexbox?

Un argument de vente clé pour flexbox est sa capacité à créer des éléments qui répondent à l'espace qui les entoure. Les composants peuvent «fléchir» pour remplir un espace supplémentaire et se rétrécir pour s'adapter à des espaces plus petits.

Pour cette situation, le flex-wrap la propriété est définie sur wrap. Cela signifie dès que les deux

les éléments ne tiennent plus sur une ligne, ils s'enrouleront sur une deuxième ligne.

.wrapper--accessibility-tools {
  display: flex;
  flex-wrap: wrap;
} 

le flex-wrap property a trois valeurs disponibles. La valeur par défaut est nowrap, laissant les éléments sur une seule ligne. le wrap value permet aux éléments de se déplacer sur plusieurs lignes. Puis il y a wrap-reverse, qui permet aux éléments de s'enrouler mais – attendez-le – dans inverser (c'est bizarre à voir: quand les éléments s'enroulent, ils vont au-dessus de la ligne précédente dans des situations de gauche à droite).

L'utilisation de flexbox empêche la mise en page d'être aussi rigide, mais min-width une valeur est toujours nécessaire pour supprimer le problème d'alignement vertical. Donc: proche mais pas de cigare.

Grid peut-il nous aider?

CSS Grid est le tout premier module CSS créé spécifiquement pour résoudre les problèmes de mise en page en cours auxquels sont confrontés les concepteurs et les développeurs Web. Ce n'est pas un remplacement direct de la flexbox; les deux modules fonctionnent plutôt bien ensemble.

Comme flexbox, la grille peut être utilisée pour permettre à chaque

occuper autant ou aussi peu d'espace dont ils ont besoin. Pour y arriver, nous pouvons tirer parti du auto-fill et auto-fit mots-clés (dans un repeat() function) pour permettre aux éléments de la grille de circuler sur plusieurs lignes sans avoir besoin de requêtes multimédias. La différence est un peu subtile, mais bien expliquée dans «Colonnes de dimensionnement automatique dans la grille CSS: remplissage automatique vs ajustement automatique» par Sara Soueidan. Utilisons auto-fit:

.wrapper--accessibility-tools {
  display: grid;
  grid-template-columns: repeat(auto-fit, 450px);
  grid-gap: 10px;
}

Comme l'exemple de la flexbox, je dois encore définir une valeur absolue pour la largeur de l'étiquette afin d'aligner le

éléments au fur et à mesure qu'ils s'empilent.

Une autre approche avec grille

CSS Grid permet également aux éléments de répondre en fonction de leur contenu à l'aide de pistes de grille flexibles. En plus d'autres valeurs de longueur telles que les pourcentages, les unités relatives ou les pixels, CSS Grid accepte une unité fractionnaire (fr), où 1fr occupera une partie de l'espace disponible, 2fr occupera deux parties de l'espace disponible, et ainsi de suite. Configurons ici deux colonnes égales:

.wrapper--accessibility-tools {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-gap: 10px;
}

Il y a aussi un minmax() qui crée des pistes de grille qui s'adaptent à l'espace disponible, mais qui ne rétrécissent pas non plus à une taille spécifiée.

.wrapper--accessibility-tools {
  display: grid;
  grid-template-columns: minmax(auto, max-content) minmax(auto, max-content);
  grid-gap: 10px;
}

Ces deux démos fonctionnent et sont exemptes de valeurs absolues ou de CSS spécifiques à l'appareil. Les résultats sont cependant loin d'être idéaux, chaque grille répond désormais à des points différents. Peut-être pas un gros problème, mais certainement pas génial.

Cela se produit car lors de l'ajout display: grid vers un conteneur, seuls les enfants directs de ce conteneur deviennent des éléments de la grille. Cela signifie que les unités de dimensionnement intrinsèques que nous avons utilisées ne concernent que les éléments de la même grille.

Utilisation de la sous-grille

Pour vraiment atteindre mon objectif, j'ai besoin des boutons et des étiquettes pour réagir aux éléments dans les conteneurs de grille frères. CSS Grid Level 2 inclut la fonctionnalité de sous-grille. Bien que nous ayons toujours été en mesure d'imbriquer des grilles, les éléments dans chaque conteneur de grille ont été indépendants. Avec subgrid, nous pouvons configurer des grilles imbriquées (enfants) qui utilisent des pistes de grilles parentes.

Cela rend beaucoup plus facile un modèle numérique qui était auparavant difficile, en particulier le modèle «carte» qui semble être l'exemple le plus populaire pour montrer les avantages de la sous-grille. Sans sous-grille, chaque carte est définie comme une grille indépendante, ce qui signifie que le dimensionnement des pistes dans la première carte ne peut pas répondre à un changement de hauteur dans la seconde. À partir d'un exemple utilisé par Rachel Andrew, voici un simple groupe de cartes:

Affichage de trois colonnes de cartes où chaque carte a un en-tête avec un fond bleu foncé et un texte blanc, un contenu avec un fond blanc et un pied de page avec un fond bleu foncé. Les cartes sont inégales car certaines d'entre elles ont plus de contenu que d'autres.
Crédits: Rachel Andrew

La sous-grille permet aux cartes d'utiliser les lignes définies dans la grille parent, ce qui signifie qu'elles peuvent réagir au contenu des cartes environnantes.

Les trois mêmes colonnes de cartes, mais avec chaque carte parfaitement alignée avec les autres.
Crédits: Rachel Andrew

Chaque carte dans cet exemple s'étend toujours sur trois pistes de ligne, mais ces lignes sont maintenant définies sur la grille parent, permettant à chaque carte d'occuper la même quantité d'espace vertical.

Pour l'exemple avec lequel nous avons travaillé, nous n'avons pas besoin d'utiliser de lignes. Au lieu de cela, nous devons dimensionner les colonnes en fonction du contenu des grilles frères. Tout d'abord, définissons la grille parente pour qu'elle contienne les deux

éléments. Ceci est similaire au code que nous avons précédemment examiné dans le auto-fit démo.

.wrapper--accessibility-tools {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  grid-gap: 10px;
}

Ensuite, nous positionnons chaque sous-grille sur la grille parent.

.sub-grid {
  display: grid;
  grid-column: span 3;
  grid-template-columns: subgrid;
  align-items: center;
}
Affichage des deux groupes de boutons rose vif avec les deux groupes sur la même ligne et tous les boutons ont une largeur cohérente.

Toutes les étiquettes et tous les boutons sont maintenant alignés sur les pistes de leur grille parent, ce qui les maintient cohérents. Ils auront chacun une largeur égale en fonction de l'espace disponible. S'il n'y a pas assez d'espace pour chaque grille imbriquée sur une ligne, la seconde s'enroulera sur une nouvelle ligne.

Les deux groupes de boutons empilés verticalement et les boutons sont tous alignés de manière cohérente avec la même largeur.

Cette fois, les deux éléments de grille imbriqués s'alignent parfaitement. La grille est également flexible si nous introduisons un titre plus long sur l'un des boutons, les autres éléments répondront en conséquence.

Compatibilité du navigateur

La prise en charge de la sous-grille n'est pas excellente au moment de la rédaction. Il n'est pris en charge que dans Firefox 71+, bien qu'il y ait des signaux positifs provenant d'autres navigateurs. Les requêtes de fonctionnalités CSS peuvent être utilisées pour fournir un style alternatif à Chrome et Edge.

Bureau

Chrome Firefox C'EST À DIRE Bord Safari
Non 71 Non Non Non

Mobile / tablette

Chrome Android Android Firefox Android Safari sur iOS
Non 79 Non Non

Notez que j'utilise un wrapper supplémentaire autour des jeux de champs dans ces démos. Il s'agit de lutter contre un bug avec les éléments de formulaire, la grille et la flexbox.

 

Le CSS de mise en page est appliqué au wrapper avec le fieldset défini sur display: contents.

.accessibility-tools fieldset {
  display: contents;
  border: 0;
} 

Autres écrits sur le sujet

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *