Tailwind v4 arbitrary + container query
Arbitrary value Tailwind v4 + container query (@container) untuk responsive component yang depend size parent, bukan viewport.
Dipublikasikan 13 Juni 2026
Tailwind v4 bawa banyak QoL: arbitrary value lebih cleaner, native container query, dan engine baru yang lebih cepat. Snippet ini contoh kartu produk yang adapt layout berdasarkan lebar parent — di sidebar narrow jadi stack, di grid 3-col jadi horizontal. Tanpa hack media query atau JS measurement.
Kode
// components/KartuProduk.tsx
import Image from "next/image";
interface Produk {
id: number;
nama: string;
harga: number;
diskon_persen?: number;
foto: string;
rating: number;
}
interface Props {
produk: Produk;
}
export function KartuProduk({ produk }: Props) {
const hargaDiskon = produk.diskon_persen
? produk.harga * (1 - produk.diskon_persen / 100)
: produk.harga;
return (
// @container bikin element ini jadi container query root
<article className="@container rounded-lg border border-zinc-200 bg-white p-3 dark:border-zinc-800 dark:bg-zinc-900">
<div className="flex flex-col gap-3 @[280px]:flex-row">
{/* Foto: full width kalau sempit, fixed kalau lebar */}
<div className="relative aspect-square w-full overflow-hidden rounded @[280px]:w-32 @[280px]:flex-shrink-0">
<Image
src={produk.foto}
alt={produk.nama}
fill
sizes="(max-width: 280px) 100vw, 128px"
className="object-cover"
/>
{produk.diskon_persen && (
<span className="absolute left-1 top-1 rounded bg-red-500 px-1.5 py-0.5 text-[10px] font-semibold text-white">
-{produk.diskon_persen}%
</span>
)}
</div>
<div className="flex min-w-0 flex-1 flex-col">
<h3 className="line-clamp-2 text-sm font-medium text-zinc-900 dark:text-zinc-100">
{produk.nama}
</h3>
<div className="mt-1 flex items-baseline gap-2">
<span className="text-base font-bold text-zinc-900 dark:text-zinc-100">
Rp {hargaDiskon.toLocaleString("id-ID")}
</span>
{produk.diskon_persen && (
<span className="text-xs text-zinc-400 line-through">
Rp {produk.harga.toLocaleString("id-ID")}
</span>
)}
</div>
<div className="mt-auto pt-2 text-xs text-zinc-500 @[280px]:text-sm">
{/* Arbitrary value untuk warna brand */}
<span className="text-[#f59e0b]">{"★".repeat(Math.round(produk.rating))}</span>
<span className="ml-1">{produk.rating.toFixed(1)}</span>
</div>
</div>
</div>
</article>
);
}
Pemakaian
// Di sidebar 240px — kartu jadi stack
<aside className="w-60 space-y-3">
<KartuProduk produk={produk1} />
<KartuProduk produk={produk2} />
</aside>
// Di grid 4-kolom — masing-masing slot ~280px, kartu jadi horizontal
<section className="grid grid-cols-1 gap-3 md:grid-cols-2 lg:grid-cols-4">
{produkList.map((p) => (
<KartuProduk key={p.id} produk={p} />
))}
</section>
// Layout otomatis adapt — gak perlu prop "horizontal" / "vertical"
// Arbitrary breakpoint custom — @[420px], @[640px]
<div className="@container">
<div className="text-sm @[420px]:text-base @[640px]:text-lg">
Font size scale dengan lebar container, bukan viewport.
</div>
</div>
Kapan dipakai
- Kartu produk e-commerce yang di-reuse di sidebar, grid, dan listing.
- Dashboard widget yang re-arrange tergantung lebar panel dia ditaruh.
- Email template-style component yang harus jalan di iframe sempit dan layar wide.
- Design system component library — UI consistent di mana pun ditaruh.
Catatan
- @container syntax: prefix
@containerpada parent, lalu@[280px]:di child untuk respond ke 280px container. Bisa pakai named container@container/sidebar+@lg/sidebar:flex-row. - Arbitrary value escape — kalau ada karakter spesial (titik, bracket), pakai underscore:
bg-[rgb(255,0,0)]jadibg-[rgb(255_0_0)]. - Performance — container query lebih murah dari ResizeObserver. Native CSS, GPU accelerated.
- Layout shift — kalau parent berubah ukuran (sidebar collapse), child re-layout otomatis. Pakai
transition-allkalau perlu animasi. - Sizing —
@containerbutuhcontainer-type: inline-sizeatausize. Tailwind v4 set otomatis keinline-size.
Tailwind v3 ke v4 migration breaking:
@applydi tempat tertentu tidak lagi work, dan beberapa default value berubah (border0jaditransparent). Cek migration guide sebelum upgrade project lama.
# tags
tailwindcontainer-querycssresponsivereact
Ditulis oleh Asti Larasati · 13 Juni 2026