Fermer

août 16, 2018

Refonte d'une mise en page Tumblr basée sur une carte avec CSS Grid –


Dans ce didacticiel, nous allons adapter une conception basée sur une grille à une mise en page inspirée de la page Qu'est-ce que vous avez? où l'utilisateur a pu sélectionner un ensemble de rubriques pour adapter leur contenu recommandé.

 La page tumblr

Seule la conception visuelle de la grille est exécutée, pas la fonctionnalité de sélection, comme le montre le Pen que nous allons construire:

Voir le stylo MBdNav par SitePoint ( @SitePoint ) sur CodePen .

L'objectif principal est d'implémenter la conception avec CSS Grid, mais une disposition de secours avec des flottants est décrite dans Support ci-dessous.

Markup

Essentiellement, le contenu de la page consiste en une liste de cartes:

  • Quels aliments aimez-vous?

    Dites-nous ce dont vous avez envie et nous allons obtenir les morceaux savoureux

  • Pizza

     Une pizza au salami

Une carte qui représente un sujet proposé à l'utilisateur (nourriture dans notre exemple) a à itle et une image illustrative, toutes deux enveloppées dans un élément de lien. D'autres pourraient être adoptés. voir par exemple l'excellent article sur le composant de carte Inclusive Components où sont analysés les avantages et les inconvénients de ces alternatives.

Structure Structural

les bases de la conception de la grille seront mises en œuvre. La prochaine section sera le style des cartes. Ce stylet affiche la mise en page simple en utilisant des espaces réservés pour les éléments de la grille. Exécutez-le sur un navigateur qui prend en charge CSS Grid.

Voir le stylo JBqgGm par SitePoint ( @SitePoint ) sur CodePen .

avec le code, il est important de spécifier les fonctionnalités et le comportement réactif de la grille. Essayons d'écrire certaines propriétés qu'il doit satisfaire.

Spécifications de conception

Le dessin comporte deux types de cartes: une série de cartes de sujet et une carte de présentation. Nous les organisons sur une grille sous-jacente composée de cellules carrées de taille fixe. Chaque carte de sujet occupe une seule de ces cellules, tandis que la couverture couvre une plus grande zone de cellules adjacentes, dont l'étendue dépend de la largeur de la fenêtre. De plus, les lignes et les colonnes sont séparées par la même gouttière de taille fixe.

 La grille sous-jacente et les deux types de carte

La grille comporte autant de colonnes (de taille fixe) que la fenêtre:

 Colonnes de taille fixe couvrant toute la largeur de la fenêtre

Mais nous ne voulons pas de colonnes sur les grands écrans, limitons donc le nombre maximal de colonnes:

 Limitation du nombre de colonnes

Les colonnes sont toujours centrées horizontalement dans la fenêtre d'affichage:

 Les colonnes sont centrées

Seulement les colonnes sont centrées, pas les éléments de la grille. Cela signifie que les cartes sur une ligne incomplète sont alignées à gauche de la grille, pas au centre de la fenêtre:

 Centrer les colonnes, pas les éléments

Découvrez ces exigences dans le Pen ci-dessus. En outre, il est utile d’inspecter la disposition avec les outils de grille CSS fournis par certains navigateurs, tels que l’Inspecteur de grille de Firefox .

Implémentation

Introduisons quelques variables globales Sass pour représenter les paramètres de disposition définis dans les spécifications, à savoir:

  • $ item-size pour la taille du côté des cellules de la grille [19659033] $ col-gutter pour la gouttière entre les pistes de la grille
  • $ vp-gutter pour un espace de sécurité à laisser entre les éléments de la grille et les bords de la fenêtre
  • $ max-cols pour le nombre maximal de colonnes que la grille peut avoir

Nous pourrions utiliser des propriétés personnalisées CSS pour ces variables, évitant le recours à un préprocesseur et nous permettant de les éditer avec les outils de développement intégrés au navigateur et de voir les modifications se produire instantanément . Mais nous allons utiliser ces valeurs même pour une configuration de secours adaptée aux anciens navigateurs, où les variables CSS ne sont pas prises en charge. De plus, nous utilisons des expressions avec ces valeurs même dans les sélecteurs de requête multimédia, où les propriétés personnalisées et la fonction calc () ne sont pas entièrement disponibles même sur les navigateurs récents:

 $ item-size: 210px;
$ col-gouttière: 10px;
$ vp-gutter: $ col-gutter;
$ max-cols: 5;

Nous devons établir un contexte de mise en forme de grille sur l'élément de grille:

 .grid {
  affichage: grille;
}

La propriété d'écart de grille sépare les pistes de la grille par la quantité d'espace spécifiée.
Mais ces gouttières ne sont insérées qu'entre les pistes et non avant la première et la dernière. Un remplissage horizontal sur le conteneur de grille empêche les colonnes de toucher les bords de la fenêtre:

 .grid {
  gap-gap: $ col-gouttière;
  rembourrage: 0 $ vp-gutter;
}

Les colonnes de la grille peuvent être définies avec la propriété grid-template-columns et la fonction repeat avec la valeur de remplissage automatique comme répétition number et la variable $ item-size pour l'argument de liste de pistes:

 .grid {
  grid-template-columns: repeat (remplissage automatique, $ item-size);
}

Cela indique au navigateur de remplir la largeur du conteneur (l'élément .grid ) avec autant de colonnes de taille fixe que possible, en tenant compte des gouttières verticales.

nous aurions pu utiliser le mode ajustement automatique et, dans de nombreuses combinaisons de tailles de fenêtre et de nombre d'éléments de grille, nous n'avons pas pu faire la différence avec remplissage automatique . Mais quand il y a seulement quelques articles dans la grille, avec juste une ligne incomplète, avec ajustement automatique les éléments seraient centrés, au lieu de partir de la gauche de la grille, comme détaillé dans les spécifications de conception . Cela se produit parce que, avec remplissage automatique la grille a toujours autant de colonnes que possible, avec ajustement automatique les colonnes vides sont supprimées et le centrage des colonnes restantes place les éléments au centre de la fenêtre:

Si la première ligne de la grille est complète, aucune colonne n'est supprimée et il n'y a pas de différence entre les deux modes:

 Aucune différence plusieurs cartes

Retour aux colonnes de la grille. Jusqu'à ce point, le nombre de colonnes était illimité. Il peut croître arbitrairement à mesure que la largeur de la fenêtre augmente. Mais selon la spécification, la grille doit comporter un nombre maximum de colonnes. Il est possible de résoudre ce problème avec la propriété max-width :

 .grid {
  max-width: grid-width ($ max-cols);
}

grid-width est une fonction Sass personnalisée qui renvoie la largeur d'une grille à n colonnes:

 @function grid-width ($ num-cols) {
  @return $ num-cols * $ item-size + ($ num-cols - 1) * $ col-gutter;
}

La première multiplication représente la taille requise par les colonnes, tandis que la seconde représente l'espace requis par les gouttières.

 Relation entre les colonnes et les gouttières

Selon les spécifications, la la grille doit toujours être centrée horizontalement. Nous pouvons combiner l'ancien tour de marges automatiques avec Justificatif-Content pour accomplir cette tâche:

 .grid {
  justifie le contenu: centre;
  marge: 40px auto;
}

jardins justifie centre les colonnes lorsqu'il reste de la place dans le conteneur de la grille. Cela se produit lorsque le conteneur saigne d'un bord de fenêtre à l'autre. Les marges automatiques latérales centrent le conteneur .grid lui-même lorsqu'il a atteint sa largeur maximale.

Maintenant, pour les lignes. Ils ne sont pas explicitement spécifiés, comme pour les colonnes. Au lieu de cela, ils sont implicitement ajoutés par le navigateur au besoin, et nous leur indiquons simplement leur taille avec la propriété grid-auto-rows . En réutilisant la variable $ item-size chaque cellule de la grille a la forme d'un carré, conformément aux spécifications:

 .grid {
  grid-auto-rows: $ taille-article;
}

Continuons en dimensionnant les cartes. Dans les petites fenêtres, lorsque la grille se configure sur une seule colonne, la carte de couverture ne couvre qu'une cellule de la grille, alors que lorsqu'il y a deux colonnes ou plus, elle doit couvrir une zone de la grille 4 × 4:

 @include when-n -cols (2) {
  .grid .header {
    rangée de grille: portée 2;
    colonne de grille: span 2;
  }
}

when-n-cols () est un mixin Sass permettant d'exprimer une requête média adaptée à une grille avec le nombre de colonnes donné:

 @mixin when-n-cols ($ n) {)
  @media screen et (min-width: # {grid-width ($ n) + 2 * $ vp-gutter + $ scrollbar-size}) {
    @contenu;
  }
}

Les règles CSS représentées par @content sont actives chaque fois que la largeur de la fenêtre d'affichage est égale ou supérieure à la largeur d'une grille avec les colonnes $ n plus les deux espaces de sécurité pour séparer la éléments de grille des bords de la fenêtre. $ scrollbar-size n'est qu'une limite supérieure de la taille d'une barre de défilement verticale, pour tenir compte du fait que la largeur indiquée dans la requête de support correspond à la largeur totale de la fenêtre, y compris une barre de défilement verticale. ] En ce qui concerne les cartes de sujet, il n’ya rien à faire, car le comportement de grille par défaut les rend de la même taille que les cellules de grille qui leur ont été attribuées.

Référez-vous au stylo structurel au début de cette section pour voir tous les extraits de code rassemblés dans le code complet.

The Cards

Ici, nous construisons les cartes – ou leur contenu interne, pour être plus précis. [19659029] Traitons d'abord les cartes de sujet. Pour les rendre cliquables, l'élément link est développé pour remplir toute la zone de la carte:

 .grid .card a {
  bloc de visualisation;
  largeur: 100%;
  hauteur: 100%;

  position: relative;
}

Ensuite, nous nous assurons que l'image de la carte couvre toute la surface de la carte:

 .grid .card img {
  bloc de visualisation;
  largeur: 100%;
  hauteur: 100%;
  ajustement d'objet: couverture;
}

Dans l'exemple, les vignettes ont un rapport d'aspect carré et, par conséquent, elles s'adaptent parfaitement à leurs éléments de grille. Pour traiter des tailles d'image arbitraires, ajustement d'objet: couvrir échelles (en conservant le rapport hauteur / largeur) et, éventuellement, couper l'image pour l'adapter à l'intérieur du conteneur.

grille .card h2 {
  marge: 0;

  position: absolue;
  en haut: 0;
  à gauche: 0;
  à droite: 0;
  en bas: 0;

  rembourrage: 10px;

  décoration de texte: aucune;
  font-family: Raleway, sans-serif;
  taille de la police: 1em;
  espacement des lettres: 1px;

  couleur: #fff;
}

Avec le positionnement absolu, l'élément d'en-tête est supprimé du flux et placé au-dessus de l'image, dans le coin supérieur gauche de la carte.

Afin d'améliorer le contraste entre l'étiquette et une image de carte sous-jacente arbitraire, une couche partiellement transparente est intercalée entre ces deux éléments graphiques.

Ici, j'utilise la même technique exacte utilisée sur la page Tumblr originale, où cette superposition consiste en un dégradé radial qui commence complètement transparent au centre de la carte. se termine par un noir partiellement opaque vers les bordures, de façon circulaire, donnant à l'image une sorte d'effet de projecteur subtil. Rendons ce calque comme une image d'arrière-plan du lien de la carte, qu'il vient d'être étendu pour couvrir toute la surface de la carte:

 .grid .card h2 {
  background-image: gradient radial (ellipse au centre, transparent 0, rgba (0,0,0, 0,36) 100%);
}

 La couche transparente

En ce qui concerne la carte de couverture, de nombreuses techniques pourraient être utilisées ici, mais restons simples. La carte comporte deux blocs de texte centrés. Avec un rembourrage latéral, leur étendue horizontale est limitée et, avec text-align leur contenu est centré. Après cela, les blocs sont centrés verticalement simplement en les poussant vers le bas avec un peu de remplissage supérieur appliqué au conteneur de la carte:

 .grid .header {
  box-sizing: border-box;

  text-align: center;
  dessus de rembourrage: 23px;

  taille de police: 1.6875em;
  hauteur de ligne: 1,3;

  fond: gradient radial (ellipse au centre, transparent 0, rgba (0,0,0, 0,48) 100%) hsla (0, 0%, 27%, 1);
}

.grid .header h1 {
  margin-top: 0;
  margin-bottom: 0.67em;

  font-family: 'Cherry Swash', cursive;
  Transformation de texte: mettre en majuscule;
  taille de la police: 1em;
  poids de la police: normal;

  padding-left: 28px;
  droit de remplissage: 28px;
}

.grid .header p {
  marge: 0;

  font-family: 'Raleway', sans-serif;
  taille de la police: 0.52em;

  padding-left: 34px;
  droit de remplissage: 34px;
}

Avec une requête multimédia, la taille de la police est augmentée et le remplissage ajusté lorsque la grille affiche deux colonnes ou plus:

 @include when-n-cols (2) {
  .grid.header {
    taille de la police: 2.5em;

    dessus rembourré: 100px;
  }

  .grid .header H1 {
    padding-left: 80px;
    rembourrage à droite: 80px;
  }

  .grid .header p {
    padding-left: 120px;
    rembourrage à droite: 120px;
  }
}

Il est temps d'ajouter de l'interactivité aux cartes de sujet. Ils doivent réduire la taille en vol stationnaire:

 .grid .card: hover {
  transformer: échelle (0,95);
}

.grid .header: survolez {
  transformer: aucune;
}

Avec une transition CSS, cette modification de l'état visuel est lissée:

 .grid .card {
  propriété de transition: transformer;
  durée de transition: 0,3 s;
}

Les cartes peuvent être parcourues à l'aide d'un clavier, alors pourquoi ne pas personnaliser leur style de mise au point pour qu'il corresponde au même aspect de la souris? Nous devons mettre à l'échelle un conteneur .card lorsque le lien d'ancrage à l'intérieur reçoit le focus. Hmmm … nous avons besoin de styliser un élément seulement lorsqu'un de ses enfants obtient le focus – et nous avons la pseudo-classe : focus-within pour faire juste cela:

 .grid .card a: focus {
  contour: aucun;
}
.grid .card: focus-within {
  transformer: échelle (0,95);
}

D'abord, le style de focus de liaison par défaut est réinitialisé, puis la même transformation que précédemment est utilisée lorsque la carte (son lien) obtient le focus.

Support

CSS Grid

large support mais que pouvons-nous faire avec les autres navigateurs? Dans le stylo de démonstration, il y a une disposition de secours, implémentée avec des flottants, qui se comporte exactement comme la disposition de la grille. Jetons un coup d'œil à son fonctionnement et à son interaction avec la mise en œuvre de la grille.

Les cartes sont dimensionnées, flottent à gauche et ont une marge inférieure pour la gouttière horizontale:

 .card {
  float: à gauche;
  width: $ item-size;
  height: $ item-size;
  marge: 0;
  margin-bottom: $ col-gouttière;
}

À ce stade, nous pourrions simplement définir un max-width sur le conteneur .grid pour limiter le nombre de colonnes sur un grand écran, utiliser des marges automatiques pour centrer la grille. , et la disposition serait presque identique à celle de la grille, mais avec la différence importante que, lorsque le conteneur n'atteint pas sa largeur maximale, les cartes sont alignées à gauche de la fenêtre d'affichage. Ceci est une configuration de secours pour les navigateurs ne prenant pas en charge la grille CSS, nous pourrions donc être satisfaits de cela. Sinon, nous pourrions continuer et ajouter du code pour corriger cette différence. Essayons.

Nous définissons la largeur du conteneur .grid lorsqu'il n'y a qu'une colonne, centrez-la dans la fenêtre et séparez-la des bords de l'écran:

 .grid {
  width: grid-width (1);
  marge: 40px auto;
  padding-left: $ vp-gutter;
  Rembourrage à droite: $ vp-gutter;
}

Notez comment nous avons réutilisé la fonction grid-width introduite ci-dessus.

Maintenant, en réutilisant le mixin de requête de média, nous définissons la largeur du conteneur .grid lorsqu'il y a deux colonnes:

 @include when-n-cols (2) {
  width: grid-width (2);
  .card: nth-child (2n) {
    margin-right: $ col-gouttière;
  }
  .entête {
    $ header-size: grid-width (2);
    width: $ header-size;
    height: $ header-size;
  }
}

Nous avons également doublé la taille de la carte d'en-tête et attribué la marge droite à la gouttière horizontale de la grille.

Ce motif est répété pour une grille de deux, trois, … $ max-cols , en prenant soin de réinitialiser et d'attribuer les margin-right s des cartes appropriées. Par exemple, lorsque la grille comporte trois colonnes:

 @include when-n-cols (3) {
  width: grid-width (3);
  .carte {
    margin-right: $ col-gouttière;
  }
  .card: nth-child (2),
  .card: nth-child (3),
  .card: nth-child (3n + 6) {
    margin-right: 0;
  }
}

Veuillez vous référer au stylo pour le reste du code.

Maintenant que nous avons deux blocs de CSS qui implémentent la même disposition sur la même page, nous devons être sûrs qu'ils ne sont pas en conflit. En particulier, sur les navigateurs prenant en charge la grille, la disposition flottante ne doit pas perturber la disposition de la grille. Grâce aux capacités de substitution inhérentes à CSS Grid il suffit de réinitialiser la largeur du conteneur de la grille, de définir sa largeur maximale et de réinitialiser les marges des cartes (). gap s'occupe maintenant des gouttières de la grille):

 @supports (display: grid) {
  .la grille {
    width: auto;
    max-width: grid-width ($ max-cols);
    .carte {
      marge: 0! important;
    }
  }
}

Ces remplacements ne doivent avoir lieu que lorsque CSS Grid est pris en charge, car ils ne respecteraient pas la disposition flottante. Cette substitution conditionnelle est effectuée avec la règle @supports .

Le code dans la plume est organisé de sorte que ces deux blocs de code pour la mise en page soient indépendants. C'est-à-dire que l'un d'eux peut être retiré sans affecter l'autre. Pour ce faire, les règles CSS communes aux deux implémentations ont été regroupées:

 .grid {
  marge: 0;
  remplissage: 0;
  style de liste: aucun;

  marge: 40px auto;
  padding-left: $ vp-gutter;
  padding-right: $ vp-gutter;
}

Donc, si un jour on veut se débarrasser de la mise en page flottante, c'est facile à faire.

Pour terminer cette discussion sur la mise en page de repli, remarquez comment son code semble plus compliqué et pas aussi intuitif que le CSS La grille. Cela met en évidence la puissance d'une technique CSS spécifiquement développée pour la mise en page, par opposition à une fonctionnalité CSS plus ancienne (floats) dont l'intention initiale était (ab) utilisée pendant de nombreuses années faute de méthodes plus spécifiques.

En ce qui concerne : focus-within il n'est pas pris en charge sur les navigateurs Microsoft . Avec le CSS défini ci-dessus, sur ces agents utilisateur, l'utilisateur ne reçoit pas le retour visuel lorsqu'un lien d'élément de grille reçoit le focus. Voici un moyen de résoudre ce problème:

 .grid .card a: focus {
  contour: 2px solide # d11ee9;
}
.grid .card: focus-within {
  transformer: échelle (0,95);
}
.grid .card: focus-dans a: focus {
  contour: aucun;
}

Un navigateur non pris en charge utilise uniquement la première règle, ce qui personnalise l'apparence du contour par défaut. Même un navigateur prenant en charge utilise cette règle, mais le contour est réinitialisé à la troisième ligne.

Une autre solution consiste à utiliser les pseudo-classes : hover et : focus sur le lien. élément, pas sur l'élément racine de la carte. En fait, pour plus de généralité, j'ai préféré mettre à l'échelle la carte entière, mais dans ce cas particulier, où le lien s'étend sur toute l'étendue de la carte, nous pouvons simplement faire ceci:

 .grid .card a: hover {
  transformer: échelle (0,95);
}
.grid .card a: focus {
  contour: aucun;
  transformer: échelle (0,95);
}

De cette manière, n'est pas nécessaire dans et la mise au point se déroule de la même manière que dans les navigateurs plus anciens.

fit-fit a également des problèmes sur les navigateurs Microsoft, donc si les images n'ont pas le même rapport d'aspect que les cartes, elles peuvent paraître étirées.

Enfin, sur IE9 et sous, les dégradés CSS ne sont pas implémentés . Par conséquent, la couche transparente qui améliore le contraste entre le titre de la carte et l'image sous-jacente n'est pas visible. Sur IE9, cela peut être corrigé en ajoutant une couleur d'arrière-plan spécifiée avec la fonction de couleur rgba () :

 .grid .card h2 {
  contexte: rgba (0,0,0, 0,2);
  fond: gradient radial (ellipse au centre, transparent 0, rgba (0,0,0, 0,36) 100%);
}

Final Words

Nous avons déjà souligné la puissance de CSS Grid dans la section précédente. En outre, nous pouvons également noter que le comportement réactif de la grille décrit dans les spécifications de conception a été réalisé sans requêtes de support. En fait, les deux seules requêtes utilisées dans les extraits précédents étaient à la fois la carte de couverture – une pour assigner la carte à sa zone de grille, et l'autre pour son contenu.

Donc, après un certain codage et beaucoup de pizzas et gâteaux, nous sommes arrivés à la fin. Mais une fin n'est qu'un début, et nous pourrions poursuivre le travail, par exemple en ajoutant des animations d'entrée aux cartes, en effectuant une révision de l'accessibilité et en essayant de réaliser une fonctionnalité de sélection similaire à la page Tumblr d'origine.

Merci à Freepik pour les images savoureuses. Suivez les liens de la carte pour voir les images originales.




Source link