The simplest responsive switch is a media query on the grid template itself. A sidebar-plus-main layout collapses to a single column on mobile with \(@media (max-width: 768px) { grid-template-columns: 1fr; }\). For a truly automatic responsive grid, the combination \(grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));\) produces as many columns as fit at the current width, each between 220 pixels and a fair share of remaining space. The flex equivalent is \(flex-wrap: wrap\) with \(flex: 1 1 220px\) on each card and a \(gap\) for spacing.
A subtle distinction inside that auto-track syntax is the difference between \(auto-fit\) and \(auto-fill\). Both create as many tracks as fit, but \(auto-fill\) reserves empty tracks when there are fewer items than tracks (they collapse to their minimum size), while \(auto-fit\) collapses empty tracks entirely so the remaining items stretch to fill the row. Choosing the wrong one can leave awkward gaps in a sparse gallery. To avoid layout jumps when an \(auto-fit\) minimum is too aggressive, choose the \(minmax\) minimum carefully — typically a few pixels below the intended card width.
Container queries extend this idea beyond the viewport. With \(container-type: inline-size\) on a parent, \(@container (min-width: 400px) { ... }\) applies styles based on the parent's own width — perfect for reusable components placed in sidebars, modals, or main content. \(container-type: size\) queries both axes but requires a fixed height on the parent. The accompanying container query units (\(cqw\), \(cqh\), \(cqi\), \(cqb\), \(cqmin\), \(cqmax\)) let you size children relative to the container rather than the viewport. The older \(column-count\) property remains useful for newspaper-style text flow but is a different category from component layout — it is not a substitute for flex or grid in interactive UIs.