Container queries have revolutionized how developers approach responsive design, and the Netflix team has experienced firsthand the profound impact they can have on streamlining development, improving flexibility, and enhancing performance. This post breaks down the key benefits of using container queries, comparing them to older methods, particularly those relying on JavaScript for layout control. It includes code examples to illustrate each point, showing how container queries can make your life as a developer much easier.
1. Simplified component design, "bottom-up" versus "top-down"
One of the most significant shifts the Netflix team experienced was moving from a "top-down" design approach to a "bottom-up" approach. Before container queries, parent containers had to be fully aware of their children's layout requirements. With container queries, this logic is reversed, allowing child components to control their layout based on their own container's size. This simplifies the parent's role and reduces the amount of layout logic in the code.
Example: Container queries versus media queries and JavaScript
Before (JavaScript needed):
/* 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 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();
After:
/* 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%;
}
}
This example shows how the parent container no longer needs to manage the child
layout. The @container
rule lets the .card
react to its immediate
container's size, simplifying layout logic and removing the need for JavaScript
altogether.
2. Responsiveness without complex media queries
The Netflix team discovered how container queries simplify responsiveness, especially for mobile-first design. Instead of writing complex media queries, you can create reusable components that adjust based on their container's size, allowing for dynamic layouts across various screen sizes and devices. This is particularly useful for apps like Netflix, where mobile traffic dominates.
Example: Component responsiveness with container queries
Before:
/* 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%;
}
}
After:
/* 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;
}
}
Instead of depending on viewport-based media queries, the .sidebar
now
responds to the container size, allowing it to adapt more naturally to dynamic
layouts without needing to know the size of the viewport or the parent
container.
3. Reduced dependency on JavaScript for layout management
Prior to container queries, many teams, including Netflix, had to rely on JavaScript for dynamic layouts. By querying the window size, JavaScript would trigger layout changes, increasing both complexity and the potential for bugs. Container queries eliminate this need by allowing CSS to handle layout responsiveness based on container size.
Example: Removing JavaScript-based layout logic
Before:
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();
After:
.card-container {
container-type: inline-size;
}
.card {
width: 100%;
}
@container (min-width: 600px) {
.card {
width: 50%;
}
}
@container (min-width: 900px) {
.card {
width: 33.33%;
}
}
This approach not only reduces the amount of JavaScript needed but also improves performance by avoiding runtime calculations.
4. Less code, fewer bugs
The Netflix team found that using container queries led to fewer lines of code and fewer layout-related bugs. By moving layout logic from JavaScript into CSS and eliminating the need for complex media queries, developers can write more maintainable code.
Example: Cutting down on layout code
The Netflix team observed that after adopting container queries, they noticed a significant reduction in CSS code—up to 30% for certain components. At the same time, the team was able to simplify many complex and sometimes conflict-prone media queries by peeling away logic that controlled the child components, achieving a higher degree of separation of concerns. This reduction not only speeds up development but also minimizes potential points of failure, leading to fewer bugs.
Before:
/* Before with complex media queries */
.card {
width: 100%;
}
@media (min-width: 600px) {
.card {
width: 50%;
}
}
@media (min-width: 900px) {
.card {
width: 33.33%;
}
}
After
.container {
container-type: inline-size;
}
.card {
width: 100%;
}
@container (min-width: 600px) {
.card {
width: 50%;
}
}
@container (min-width: 900px) {
.card {
width: 33.33%;
}
}
5. Improved developer experience
bq. "this made my life a hundred times easier"
Perhaps one of the most underappreciated benefits of container queries is the improved developer experience. By making CSS behave in a more intuitive, component-focused way, developers can focus on building reusable, flexible components without worrying about how they will behave in every possible layout scenario.
As one of the members from the Netflix team said, "This is how CSS should have worked from the start."
6. Polyfill fallback
Although container queries are in all major browsers now, there's concern about earlier versions of browsers still in use. A fallback is very important, the Netflix team uses this JavaScript polyfill created by web community contributors. The implementation is straightforward with feature detection:
if (! CSS.supports("container-type:size")) {
/*use polyfill from
https://www.npmjs.com/package/container-query-polyfill */
}
Conclusion
Container queries represent a huge step forward in CSS, making it easier for developers to build flexible, responsive components that can be reused across different parts of a site. By reducing the reliance on JavaScript for layout, eliminating complex media queries, and speeding up development, they offer significant advantages in both performance and maintainability. Currently, most of the use cases are on Netflix's Tudum pages with potential plans to use container queries in other parts of Netflix. The Netflix team considers container queries a first-class tool in the developer toolbox, and their use will only expand as more developers embrace the flexibility and power they bring. Whether for retrofitting existing components or designing entirely new ones, container queries offer a simpler, cleaner path forward for responsive design.
If you haven't already, give container queries a try—you'll likely find that it simplifies your workflow in ways you didn't expect.