Monsoon v0.2.0
Made by Alexandre Kohler Star

Getting started

Container queries

Viewport breakpoints answer "how wide is the window". A component usually needs to know "how wide is my column". Container queries answer that, and Monsoon exposes them as utility classes you write straight in your HTML.

3 min read

Two pieces: a container and a prefix

Mark a parent with the @container class. It sets container-type: inline-size, which makes the element a container measured by its width. Then prefix utilities on any descendant with a container breakpoint such as @md::

card.html
<div class="@container">
  <div class="flex flex-col @md:flex-row gap-4">
    <img class="rounded-xl @md:w-1/3" src="cover.jpg" alt="Cover">
    <div class="space-y-2">
      <h3 class="text-lg @lg:text-2xl font-bold">Title</h3>
      <p class="text-muted-foreground">Stacked when narrow, a row when wide.</p>
    </div>
  </div>
</div>

The class container-q does the same as @container, for templates or tools that do not like the at sign in a class name.

Container breakpoints

PrefixContainer width at leastIn pixels (16px root)Query
@xs:20rem320px@container (min-width: 20rem)
@sm:24rem384px@container (min-width: 24rem)
@md:28rem448px@container (min-width: 28rem)
@lg:32rem512px@container (min-width: 32rem)
@xl:36rem576px@container (min-width: 36rem)

They are measured in rem because containers are usually much smaller than screens, and they follow the user font size. Like the viewport breakpoints they are mobile first: write the narrow layout without a prefix and add the wider one with a prefix.

One card, two parents

Here the same card sits in a wide parent and in a narrow one. The card switches to a row when its own container reaches 20rem (@xs:), whatever the window width:

cards.html
<div class="grid sm:flex gap-4">
  <div class="@container flex-1 rounded-xl border bg-surface p-3">
    <!-- card -->
  </div>
  <div class="@container sm:w-48 rounded-xl border bg-surface p-3">
    <!-- the same card -->
  </div>
</div>

<!-- card -->
<div class="flex flex-col @xs:flex-row gap-3">
  <div class="h-24 @xs:w-1/3 shrink-0 rounded-lg bg-gradient-to-br from-primary to-accent"></div>
  <div class="space-y-1">
    <p class="font-semibold @xs:text-lg">Mountain cabin</p>
    <p class="text-sm text-muted-foreground">Sleeps four. Wood stove, lake view.</p>
  </div>
</div>
Same markup in a wide and a narrow container

Mountain cabin

Sleeps four. Wood stove, lake view.

Mountain cabin

Sleeps four. Wood stove, lake view.

On a phone both parents are narrow, so both cards stack. On a wider screen the left parent grows past 20rem and its card turns into a row, while the right parent stays at 12rem and keeps the stacked layout.

Which utilities have container variants

Container variants are generated for the utilities you use to rearrange a component. Each of the five prefixes covers the same set:

CategoryUtilities with @xs: to @xl:Classes per prefix
layoutblock, inline-block, inline, flex, inline-flex, grid, hidden7
flexboxflex-row, flex-col, flex-wrap, flex-nowrap4
gridgrid-cols-1 to grid-cols-12, col-span-1 to col-span-12, col-span-full25
spacingevery gap, gap-x and gap-y step; p, px and py at 0, 1, 2, 3, 4, 6, 8, 10, 12 and 16108
alignmentitems-* and justify-*13
sizingwidth fractions, w-full and w-auto14
typographytext-xs to text-9xl, text-left, text-center, text-right16

That is 187 classes per prefix. Filter the class reference by variant, or run npx monsooncss classes --filter @md:, to see each one.

Breakpoints or container queries?

They answer different questions, and most pages use both. Use viewport breakpoints (md:, lg:) for decisions about the whole page: how many columns the layout has, whether the navigation collapses, how wide the main content is. Use container queries for decisions inside a component: whether a card shows its image beside or above the text, how many items a row holds, how large a heading is.

A good test is to ask where the component will be reused. A product card that appears in a three column grid, in a sidebar and in a full width search result cannot rely on the window width, because the same window gives it three different widths. That card wants container queries. A site header always spans the window, so viewport breakpoints fit it.

A common pattern combines them: breakpoints decide the page grid, and each cell is an @container whose content adapts to the cell.

layout.html
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
  <section class="lg:col-span-2 @container">
    <div class="grid grid-cols-1 @md:grid-cols-2 gap-4">...</div>
  </section>
  <aside class="@container">
    <div class="grid grid-cols-1 @md:grid-cols-2 gap-4">...</div>
  </aside>
</div>

Named containers and other limits

Monsoon has no named container utilities: every prefixed class responds to its nearest ancestor container. That covers most components, because the nearest container is usually the one you mean. When you need to skip a level, name the container in your own CSS and write that one query by hand:

sidebar.css
.sidebar {
  container: sidebar / inline-size;
}

@container sidebar (min-width: 30rem) {
  .sidebar-nav {
    display: flex;
    gap: 1rem;
  }
}
  • An element cannot query itself. Put @container on a parent and the prefixed classes on its children.
  • An inline size container does not take its width from its content. Give it a width from the layout: a grid cell, a flex item with flex-1, or w-full. Inside a shrink to fit parent it can collapse to zero.
  • Containers nest. A prefixed class always responds to the nearest one.
  • Container queries work in all current browsers. Older ones ignore the prefixed classes and keep the unprefixed, narrow layout. See Browser support.

Frequently asked questions

What is the difference between md: and @md:?

md: checks the window width (768px and up). @md: checks the width of the nearest @container ancestor (28rem and up).

Do container queries need a build step?

No. The @container class and the @xs: to @xl: variants are in the stylesheet you link.

Does Monsoon support named containers?

Not as utilities. Prefixed classes use the nearest container. Name a container in your own CSS when you need to target a specific one.

No recent searches

Try , , or .

Recent

Loading the search index

No results for ""

Check the spelling, or search a class name such as px-4.