Libérer le potentiel des requêtes de conteneur CSS: leçons de l'équipe Netflix

Jeremy Weeks
Jeremy Weeks
Stefan Heymanns
Stefan Heymanns

Les requêtes de conteneur ont révolutionné la façon dont les développeurs abordent le responsive design. L'équipe Netflix a pu constater de visu l'impact profond qu'elles peuvent avoir sur la simplification du développement, l'amélioration de la flexibilité et les performances. Cet article décrit les principaux avantages de l'utilisation de requêtes de conteneur, en les comparant aux anciennes méthodes, en particulier celles qui reposent sur JavaScript pour le contrôle de la mise en page. Il comprend des exemples de code pour illustrer chaque point, montrant comment les requêtes de conteneur peuvent vous simplifier la vie en tant que développeur.

1. Conception simplifiée des composants, "bottom-up" (ascendante) par rapport à "top-down" (descendante)

L'un des changements les plus importants que l'équipe Netflix a vécus a été le passage d'une approche de conception "top-down" à une approche "bottom-up". Avant les requêtes de conteneur, les conteneurs parents devaient être parfaitement conscients des exigences de mise en page de leurs enfants. Avec les requêtes de conteneur, cette logique est inversée, ce qui permet aux composants enfants de contrôler leur mise en page en fonction de la taille de leur propre conteneur. Cela simplifie le rôle du parent et réduit la quantité de logique de mise en page dans le code.

Exemple: Requêtes de conteneur par rapport aux requêtes multimédias et JavaScript

Avant (JavaScript nécessaire):

/* Layout with media queries */
.card {
    width: 100%;
}

@media (min-width: 600px) {
    .card {
        width: 50%;
    }
}

@media (min-width: 900px) {
    .card {
        width: 33.33%;
    }
}
// JavaScript to detect parent container size
const container = document.querySelector('.container');
const card = document.querySelector('.card');

function adjustLayout() {
    if (window.innerWidth >= 900) {
        card.style.width = '33.33%';
    } else if (window.innerWidth >= 600) {
        card.style.width = '50%';
    } else {
        card.style.width = '100%';
    }
}

window.addEventListener('resize', adjustLayout);
adjustLayout();

Après :

/* Container Query */
.container {
    container-type: inline-size;
}

.card {
    width: 100%;
}

@container (min-width: 600px) {
    .card {
        width: 50%;
    }
}

@container (min-width: 900px) {
    .card {
        width: 33.33%;
    }
}

Cet exemple montre comment le conteneur parent n'a plus besoin de gérer la mise en page enfant. La règle @container permet à .card de réagir à la taille de son conteneur immédiat, ce qui simplifie la logique de mise en page et élimine complètement le besoin de JavaScript.

2. Réactivité sans requêtes multimédias complexes

L'équipe Netflix a découvert comment les requêtes de conteneur simplifient la réactivité, en particulier pour la conception mobile first. Au lieu d'écrire des requêtes multimédias complexes, vous pouvez créer des composants réutilisables qui s'adaptent en fonction de la taille de leur conteneur, ce qui permet d'obtenir des mises en page dynamiques sur différentes tailles d'écran et différents appareils. Cette fonctionnalité est particulièrement utile pour les applications comme Netflix, où le trafic mobile domine.

Exemple: Réactivité des composants avec les requêtes de conteneur

Avant :

/* Desktop versus Mobile
this only works if.sidebar is directly contained by a viewport-width element */
.sidebar {
    width: 300px;
}

@media (max-width: 768px) {
    .sidebar {
        width: 100%;
    }
}

Après :

/* Responsive sidebar based on container,
.sidebar can be placed in any element of any width */
.container {
    container-type: inline-size;
}

.sidebar {
    width: 100%;
}

@container (min-width: 768px) {
    .sidebar {
        width: 300px;
    }
}

Au lieu de dépendre des requêtes multimédias basées sur la fenêtre d'affichage, .sidebar répond désormais à la taille du conteneur, ce qui lui permet de s'adapter plus naturellement aux mises en page dynamiques sans avoir à connaître la taille de la fenêtre d'affichage ni du conteneur parent.

3. Réduction de la dépendance à JavaScript pour la gestion de la mise en page

Avant les requêtes de conteneur, de nombreuses équipes, y compris Netflix, devaient s'appuyer sur JavaScript pour les mises en page dynamiques. En interrogeant la taille de la fenêtre, JavaScript déclencherait des modifications de mise en page, ce qui augmenterait à la fois la complexité et le risque de bugs. Les requêtes de conteneur éliminent ce besoin en permettant au CSS de gérer la réactivité de la mise en page en fonction de la taille du conteneur.

Exemple: Supprimer la logique de mise en page basée sur JavaScript

Avant :

const cardContainer = document.querySelector('.card-container');
const cards = cardContainer.children;

function adjustLayout() {
    if (cardContainer.offsetWidth > 900) {
        cards.forEach(card => card.style.width = '33.33%');
    } else if (cardContainer.offsetWidth > 600) {
        cards.forEach(card => card.style.width = '50%');
    } else {
        cards.forEach(card => card.style.width = '100%');
    }
}

window.addEventListener('resize', adjustLayout);
adjustLayout();

Après :

.card-container {
    container-type: inline-size;
}

.card {
    width: 100%;
}

@container (min-width: 600px) {
    .card {
        width: 50%;
    }
}

@container (min-width: 900px) {
    .card {
        width: 33.33%;
    }
}

Cette approche réduit non seulement la quantité de code JavaScript nécessaire, mais améliore également les performances en évitant les calculs d'exécution.

4. Moins de code, moins de bugs

L'équipe Netflix a constaté que l'utilisation de requêtes de conteneur réduisait le nombre de lignes de code et de bugs liés à la mise en page. En déplaçant la logique de mise en page de JavaScript vers le CSS et en éliminant le besoin de requêtes multimédias complexes, les développeurs peuvent écrire du code plus facile à gérer.

Exemple: Réduire le code de mise en page

L'équipe Netflix a constaté qu'après avoir adopté les requêtes de conteneur, elle a observé une réduction significative du code CSS, jusqu'à 30% pour certains composants. En même temps, l'équipe a pu simplifier de nombreuses requêtes multimédias complexes et parfois sujettes à des conflits en éliminant la logique qui contrôlait les composants enfants, obtenant ainsi un degré de séparation des préoccupations plus élevé. Cette réduction accélère non seulement le développement, mais réduit également les points de défaillance potentiels, ce qui entraîne moins de bugs.

Avant :

/* Before with complex media queries */
.card {
    width: 100%;
}

@media (min-width: 600px) {
    .card {
        width: 50%;
    }
}

@media (min-width: 900px) {
    .card {
        width: 33.33%;
    }
}

Après

.container {
    container-type: inline-size;
}

.card {
    width: 100%;
}

@container (min-width: 600px) {
    .card {
        width: 50%;
    }
}

@container (min-width: 900px) {
    .card {
        width: 33.33%;
    }
}

5. Expérience de développement améliorée

bq. "Cela m'a facilité la vie cent fois plus"

L'un des avantages les plus sous-estimés des requêtes de conteneur est l'amélioration de l'expérience pour les développeurs. En faisant en sorte que le CSS se comporte de manière plus intuitive et axée sur les composants, les développeurs peuvent se concentrer sur la création de composants réutilisables et flexibles sans se soucier de leur comportement dans tous les scénarios de mise en page possibles.

Comme l'a dit l'un des membres de l'équipe Netflix, "C'est ainsi que le CSS aurait dû fonctionner dès le départ."

6. Polyfill de remplacement

Bien que les requêtes de conteneur soient désormais disponibles dans tous les principaux navigateurs, les versions antérieures de navigateurs encore utilisées posent problème. Un fallback est très important. L'équipe Netflix utilise ce polyfill JavaScript créé par des contributeurs de la communauté Web. L'implémentation est simple avec la détection de fonctionnalités:

if (! CSS.supports("container-type:size")) {
  /*use polyfill from
  https://www.npmjs.com/package/container-query-polyfill */
 }

Conclusion

Les requêtes de conteneur représentent un grand pas en avant dans le CSS, car elles permettent aux développeurs de créer plus facilement des composants flexibles et responsifs qui peuvent être réutilisés dans différentes parties d'un site. En réduisant la dépendance à JavaScript pour la mise en page, en éliminant les requêtes multimédias complexes et en accélérant le développement, ils offrent des avantages significatifs en termes de performances et de facilité de maintenance. Actuellement, la plupart des cas d'utilisation se trouvent sur les pages Tudum de Netflix, avec des projets potentiels d'utiliser des requêtes de conteneur dans d'autres parties de Netflix. L'équipe Netflix considère les requêtes de conteneur comme un outil de premier plan dans la boîte à outils des développeurs. Leur utilisation ne fera qu'augmenter à mesure que de plus en plus de développeurs adopteront la flexibilité et la puissance qu'elles apportent. Que ce soit pour adapter des composants existants ou en concevoir de nouveaux, les requêtes de conteneur offrent une approche plus simple et plus claire pour la conception responsive.

Si ce n'est pas déjà fait, essayez les requêtes de conteneur. Vous constaterez probablement qu'elles simplifient votre workflow de manière inattendue.