4 astuces CSS pour bien commencer l’année !
L’année 2022 a été, pour ma part, très riche en projets Web. 🎉
Ce fut donc l’occasion rêvée d’expérimenter de nouvelles méthodologies d’intégration, de passer du côté obscur de la force en adoptant Tailwind CSS 😏, et bien évidemment, de m’amuser avec les dernières fonctionnalités CSS à la mode.
Afin de bien démarrer 2023, j’avais donc envie de vous partager 4 astuces CSS qui m’ont simplifié la vie l’an passé, et qui, je l’espère, vous seront également utiles pour vos prochains projets ! 🙂
Cet article se veut accessible au plus grand nombre, ces astuces sont rapides à mettre en place et facilement applicables en production via des cas d’usage concrets.
Non, je ne parlerai pas de la pseudo-classe :has()
, ni des CSS Container Queries !
Section intitulée la-fin-du-quot-padding-hack-quot-avec-la-propriete-css-code-aspect-ratio-codeLa fin du « padding hack » avec la propriété CSS aspect-ratio
Il y a quelque temps, maintenir un ratio spécifique pour une image, une vidéo, ou une iframe, nécessitait généralement de passer par un hack à base de padding
et de position: absolute
.
Cette technique a été utilisée de très nombreuses années, et disons-le, elle n’était pas des plus élégantes.
Pour rappel, le CSS ressemblait à ça (exemple avec un média au format 16 / 9) :
.container {
position: relative;
padding-bottom: 56.25%; /* 9 / 16 * 100% */
}
.media {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
L’arrivée de la propriété CSS aspect-ratio
et de sa prise en charge dans la plupart des navigateurs modernes (👋 RIP Internet Explorer) a donc véritablement changé la donne pour notre plus grand bien.
Le code précédent se simplifie maintenant de cette façon :
.media {
aspect-ratio: 16 / 9;
}
Oui, en une seule propriété CSS ! 😍
Dernièrement, j’avais pour mission d’afficher une galerie d’images au format 16 / 9 sur grands écrans, et au format carré sur tablettes et mobiles. En complément de l’élément HTML <picture>
(à utiliser pour des décisions de nature artistique), le CSS se décline simplement de cette façon :
@media screen and (min-width: 1024px) {
.media {
--media-aspect-ratio: 16 / 9;
}
}
.media {
max-width: 100%;
height: auto;
aspect-ratio: var(--media-aspect-ratio, 1);
object-fit: cover;
}
La propriété CSS object-fit
permet de gérer la façon dont l’image sera rognée, mise à l’échelle ou étirée en fonction des dimensions de celle-ci, elle est une très bonne alliée de la propriété CSS aspect-ratio
. 👍
Pour conclure, la propriété CSS aspect-ratio
permet également, à l’instar des attributs width
et height
propres aux éléments remplacés, d’éviter les « layout shifts » en allouant la place nécessaire avant le chargement du média, comme dans l’exemple précédent.
Section intitulée code-position-fixed-code-est-mort-vive-code-position-sticky-codeposition: fixed
est mort, vive position: sticky
! 👑
Section intitulée un-rapide-etat-des-lieuxUn rapide état des lieux
Le positionnement sticky est un mélange entre le positionnement relatif et fixe. L’élément sticky est considéré comme étant relatif jusqu’à ce qu’il franchisse un seuil spécifié, au-delà duquel, il est considéré comme fixe.
Ce positionnement s’avère très pratique pour reproduire ce type d’effet :
La structure HTML en question :
<header class="header">
Header
</header>
<main class="container">
<div class="content">
Lorem ipsum...
</div>
<aside class="sidebar">
Sticky sidebar...
</aside>
</main>
Et le CSS associé :
.container {
display: grid;
grid-template-columns: repeat(12, minmax(0, 1fr));
align-items: start;
}
.content {
grid-column: span 8;
}
.sidebar {
position: sticky;
top: 0;
grid-column: span 4;
}
Plutôt facile, non ? 🥳
Pour celles et ceux qui s’en souviennent, ce comportement n’était possible, à l’époque, qu’en JavaScript. Et cette fois-ci, c’était loin d’être une partie de plaisir ! 😅
Section intitulée cas-d-ecole-un-en-tete-fixeCas d’école : Un en-tête fixe
Il y a quelques mois, j’ai découvert un autre cas d’utilisation fort pratique, en partant d’un exemple connu, illustré ci-dessous :
La méthode classique pour réaliser un en-tête fixe est d’utiliser… 🥁 le positionnement fixe !
:root {
--header-height: 12rem;
}
.header {
position: fixed;
top: 0;
right: 0;
left: 0;
z-index: 100;
height: var(--header-height);
}
.container {
padding-top: calc(var(--header-height) + 2.4rem);
}
À priori, ce code ne pose pas de réelles problématiques, mais j’aimerais tout de même attirer votre attention sur un point en particulier.
Petit aparté : Un élément positionné de manière fixe sort du flux normal du document, par conséquent, aucun espace n’est attribué pour cet élément.
Dans notre exemple, le conteneur (ou tout autre élément du flux), devra donc être décalé verticalement, d’une valeur correspondant à la hauteur de l’en-tête, afin de ne pas être caché par celui-ci.
Il est donc indispensable de définir explicitement la hauteur de l’en-tête, comme vous pouvez le voir à la racine du document (via la pseudo-classe :root
), ce qui peut, cette fois-ci, entraîner quelques soucis : la hauteur de l’en-tête ou les espacements verticaux internes ou externes du conteneur peuvent varier en fonction de la largeur de la zone d’affichage, ou bien encore, en fonction des différentes mises en page.
Cette contrainte nécessite donc de devoir calculer en permanence la hauteur de l’en-tête, en fonction des différents scénarios évoqués précédemment, afin de décaler correctement les éléments s’affichant dans le flux normal du document.
L’idéal serait, en réalité, de pouvoir combiner les avantages du positionnement relatif (l’élément est positionné dans le flux normal du document) et du positionnement fixe. 🤔
Tada ! 🥳
.header {
position: sticky;
top: 0;
z-index: 100;
}
Et oui, tout simplement ! Ce code est beaucoup plus flexible, vous ne trouvez pas ?
Section intitulée code-position-absolute-code-vs-code-display-grid-codeposition: absolute
vs display: grid
⚔️
Pour cette troisième astuce, je vous propose un autre cas d’école, l’implémentation d’une carte (card) basique :
Commençons par la structure HTML :
<article class="card">
<header class="card__header">
<h2 class="card__title">
<a href="#" class="card__link">Card title</a>
</h2>
<img src="https://picsum.photos/id/443/248/180" width="248" height="180" alt="Mountain landscape" class="card__img" />
</header>
<div class="card__content">
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</p>
<p>
<strong>$99</strong>
</p>
</div>
</article>
Puis le CSS (version simplifiée pour l’exemple) :
.card {
/* ui styles */
}
.card__header {
position: relative;
}
.card__title {
position: absolute;
inset: 0;
z-index: 10;
display: flex;
align-items: flex-end;
}
.card__content {
/* ui styles */
}
Concentrons-nous plus particulièrement sur l’en-tête.
La structure HTML est assez simple, l’en-tête contient un titre, un lien et une image.
Pour la partie CSS, la solution classique afin de superposer un titre sur une image est d’utiliser le positionnement absolu position: absolute
, comme montré dans l’exemple… jusque là tout va bien.
Malheureusement, une semaine après, le client formule une nouvelle demande :
Client : J’aimerais que toute la carte soit cliquable, svp, merci.
Chef de projet : Mais bien sûr ! On (Jonathan) s’en occupe tout de suite ! 👍
Moi : C’était dans les specs ? 😒
La solution la plus simple afin de créer un lien étiré (stretched link) est d’utiliser les pseudo-éléments ::before
ou ::after
:
.card__link::after {
position: absolute;
inset: 0;
content: '';
}
Mais, quelle ne fut pas ma surprise au moment de découvrir que le lien ne s’étendait pas à l’extérieur de l’en-tête 😮 :
(En fait, je savais pertinemment que cela ne fonctionnerait pas, parce que je suis l’auteur de cet article, et par conséquent… bref !).
Ce comportement est, en réalité, parfaitement logique : les éléments relatifs et absolus ont pour particularité d’être positionnés. Cela implique que le pseudo-élément généré de manière absolue, sera positionné par rapport à son plus proche ancêtre positionné, à savoir, le titre, lequel étant lui-même positionné de façon absolue par rapport à son en-tête, CQFD.
Cette solution ne peut donc pas fonctionner en l’état.
Heureusement, le modèle de disposition en grille (CSS Grid Layout) permet de simuler le positionnement absolu à l’aide des placements explicites.
Pour faire simple, il est possible de forcer les éléments enfants d’une grille à se superposer, grâce, notamment, aux valeurs 1 / -1
associées à la propriété CSS grid-area
(propriété raccourcie pour grid-row-start
, grid-column-start
, grid-row-end
et grid-column-end
).
Modifions légèrement le CSS initial :
.card {
position: relative;
}
.card__header {
display: grid;
}
.card__title {
z-index: 10;
display: flex;
grid-area: 1 / -1;
align-items: flex-end;
}
.card__link::after {
position: absolute;
inset: 0;
content: '';
}
.card__img {
grid-area: 1 / -1;
}
.card__content {
/* ui styles */
}
Contrairement à tout à l’heure, le titre et l’en-tête n’étant plus positionnés, notre carte devient donc entièrement cliquable :
Et voilà ! 🙂
Section intitulée code-gap-code-ou-pas-code-gap-codegap
ou pas gap
?
Pour conclure, j’aimerais vous présenter une petite astuce que j’utilise quotidiennement afin de gérer les espacements verticaux (applicable également aux espacements horizontaux).
Prenons cet exemple :
Une marge verticale doit être présente entre chaque élément de cette liste, sans affecter les marges internes de celle-ci.
Pour ce faire, deux approches sont traditionnellement employées.
La première approche consiste à réinitialiser la valeur de la marge basse du dernier élément de la liste :
.list {
padding: 2.4rem;
}
.list__item {
margin-bottom: 2.4rem;
}
.list__item:last-child {
margin-bottom: 0;
}
La seconde approche consiste à utiliser la pseudo-classe de négation :not()
:
.list {
padding: 2.4rem;
}
.list__item:not(:last-child) {
margin-bottom: 2.4rem;
}
Dans les deux cas, nous sommes contraints d’augmenter la spécificité du dernier élément de la liste, avec pour conséquence directe, de potentiellement subir des problèmes de surcharge.
Heureusement, la propriété CSS gap
, applicable désormais au module de boîtes flexibles (flexbox), nous apporte une solution beaucoup plus élégante 🙂 :
.list {
display: flex;
flex-direction: column;
gap: 2.4rem;
padding: 2.4rem;
}
Section intitulée un-petit-mot-pour-la-finUn petit mot pour la fin
J’espère sincèrement, qu’à travers ces cas pratiques, ces quelques astuces CSS pourront vous aider dans votre travail quotidien.
Sur ce, je vous souhaite une très belle année 2023, et vive le CSS ! 🎉🥳
Commentaires et discussions
J’ai testé Tailwind CSS…
Paris 11e, un vendredi, 10h42, pause café : Greg (développeur Back-End) : Tu n’as jamais testé Tailwind CSS ? Allô, on est en 2021, même ma nièce de 2 ans s’y est mise ! Moi (développeur Front-End) : Mouais… c’est juste un générateur de classes utilitaires… mais ok, si tu insistes, …
Nos articles sur le même sujet
Nos formations sur ce sujet
Notre expertise est aussi disponible sous forme de formations professionnelles !
CSS avancé
Mettre en forme des pages web en offrant des possibilités de personnalisation poussées
Ces clients ont profité de notre expertise
Refonte complète de la plateforme d’annonces immobilières de Cushman & Wakefield France. Connecté aux outils historiques, cette nouvelle vitrine permet une bien meilleure visibilité SEO et permet la mise en avant d’actifs qui ne pouvaient pas l’être auparavant.
Dans le cadre du renouveau de sa stratégie digitale, Orpi France a fait appel à JoliCode afin de diriger la refonte du site Web orpi.com et l’intégration de nombreux nouveaux services. Pour effectuer cette migration, nous nous sommes appuyés sur une architecture en microservices à l’aide de PHP, Symfony, RabbitMQ, Elasticsearch et Docker.
L’équipe d’Alain Afflelou a choisi JoliCode comme référent technique pour le développement de son nouveau site internet. Ce site web-to-store incarne l’image premium de l’enseigne, met en valeur les collections et offre aux clients de nouvelles expériences et fonctionnalités telles que l’e-réservation, le store locator, le click & collect et l’essayage…