Menu

CSS Media Queries: Breakpoint, min-width dan max-width

Media query menerapkan CSS hanya saat sebuah kondisi terpenuhi, misalnya lebar layar minimum, skema warna gelap, atau pointer mouse. Pelajari sintaks @media, breakpoint mobile first, sintaks range, prefers-color-scheme, matchMedia di JavaScript, dan container query.

Halaman ini dilengkapi editor yang bisa dijalankan. Edit, jalankan, dan lihat output-nya seketika.

Media query dalam satu contoh

Media query membungkus CSS di dalam sebuah kondisi. Aturan di dalam @media (min-width: 600px) hanya berlaku selama lebar viewport minimal 600px:

Preview-nya adalah sebuah frame, dan media query di dalamnya mengukur frame itu, bukan layarmu. Di desktop, lebarnya kurang lebih sama dengan kolom artikel ini, biasanya lebih dari 600px, jadi kotaknya biru. Perkecil jendela browser-mu sampai lebar frame turun di bawah 600px, dan kotaknya berubah menjadi kuning. Baris di bawah kotak melaporkan lebar frame secara langsung. Di ponsel, frame-nya sudah sempit, jadi kamu melihat versi kuning.

Sintaks @media

@media (min-width: 600px) { ... }                        /* one condition */
@media (min-width: 600px) and (max-width: 899px) { ... } /* both must be true */
@media (max-width: 599px), print { ... }                 /* either one (comma = or) */
@media not print { ... }                                 /* negation */
@media screen and (orientation: landscape) { ... }       /* media type plus a feature */
@media (width >= 600px) { ... }                          /* range syntax */
@media (600px <= width < 900px) { ... }                  /* a range with both ends */

and butuh spasi di kedua sisinya: (min-width: 600px)and(max-width: 900px) tidak valid dan seluruh query diabaikan. Sintaks range (width >= 600px) didukung di Chrome, Firefox, dan Safari versi terbaru, dan lebih jelas dibaca daripada min-width, terutama untuk "sampai, tetapi tidak termasuk".

Fitur yang paling sering kamu pakai:

FiturCocok saatContoh
min-width / width >=lebar viewport minimal sebesar ini(min-width: 768px)
max-width / width <=lebar viewport maksimal sebesar ini(max-width: 767px)
orientationportrait (lebih tinggi daripada lebarnya) atau landscape(orientation: landscape)
hoverpointer utama bisa hover (hover) atau tidak (none, sebagian besar layar sentuh)(hover: hover)
pointerpointer utama bersifat fine (mouse) atau coarse (jari)(pointer: coarse)
prefers-color-schemepengguna memilih tema dark atau light(prefers-color-scheme: dark)
prefers-reduced-motionpengguna meminta sistem untuk mengurangi animasi(prefers-reduced-motion: reduce)
print (sebuah media type)halaman dicetak atau disimpan sebagai PDF@media print

Mobile first: breakpoint min-width

Tulis layout ponsel sebagai CSS dasar, lalu tambahkan query min-width yang mengubah layout saat ruangnya makin lebar. Setiap query cukup menjelaskan apa yang berubah:

Di jendela desktop yang lebar, preview-nya lebih dari 720px, jadi kamu melihat tiga kolom. Baris di bawah grid melaporkan lebar dan jumlah kolomnya. Perkecil jendelanya, maka kolomnya turun menjadi dua di bawah 720px dan menjadi satu di bawah 480px. Urutan kedua query itu penting: keduanya bernilai benar di layar lebar, dan yang ditulis belakangan yang menang, jadi query min-width ditulis dari yang terkecil sampai terbesar. (Dengan query max-width urutannya terbalik: yang terbesar lebih dulu.)

Memilih breakpoint

Tidak ada daftar resmi. Berikut nilai yang umum dan apa yang biasanya dipisahkannya:

BreakpointBiasanya
min-width: 640pxponsel besar dalam mode landscape, tablet kecil
min-width: 768pxtablet dalam mode portrait
min-width: 1024pxtablet dalam mode landscape, laptop kecil
min-width: 1280pxdesktop

Cara yang lebih baik: mulai dari layout yang sempit, lebarkan jendelanya sampai ada yang terlihat salah (baris terlalu panjang, kartu terlalu lebar), lalu taruh breakpoint di situ. Dua atau tiga breakpoint sudah cukup untuk sebagian besar halaman. Sering kali kamu bahkan tidak butuh breakpoint sama sekali: repeat(auto-fit, minmax(200px, 1fr)) di grid, flex-wrap, dan clamp() menyesuaikan diri secara terus-menerus.

Setiap halaman butuh meta tag viewport

Tanpa tag ini di <head>, browser ponsel menata halaman seolah-olah layarnya selebar sekitar 980px lalu memperkecil tampilannya, jadi query min-width: 480px milikmu selalu bernilai benar dan layout ponselmu tidak pernah muncul:

<meta name="viewport" content="width=device-width, initial-scale=1">

Halaman meta viewport menjelaskan setiap nilai di dalamnya.

Mode gelap dengan prefers-color-scheme

prefers-color-scheme mengikuti pengaturan terang atau gelap di sistem operasi. Cara paling rapi untuk memakainya adalah menyimpan warna di variabel CSS, lalu hanya mengubah variabelnya di dalam query:

Di preview ini, query-nya bisa mencetak false meskipun sistemmu diatur ke mode gelap: Chrome tidak meneruskan pengaturan sistem ke frame sandbox seperti ini. Tombolnya mengatur variabel yang sama secara manual, persis seperti cara kerja tombol ganti tema di sebuah situs. :root[data-theme] lebih spesifik daripada :root biasa di dalam query, jadi pilihan pembaca menang atas pengaturan sistem. Simpan contoh ini sebagai file dan buka untuk melihat query-nya mengikuti sistemmu.

Script-nya menunjukkan sisi lain dari media query: matchMedia() menjalankan query yang sama dari JavaScript, mengembalikan apakah query itu cocok saat ini, dan memicu event change saat jawabannya berubah. Pakai ini saat perilaku (bukan hanya tampilan) bergantung pada layar, misalnya membuka menu dengan cara yang berbeda di perangkat sentuh.

Animasi bekerja dengan cara yang sama. Bungkus animasi yang besar atau berulang dengan pengecekan prefers-reduced-motion, seperti yang ditunjukkan di halaman animation.

Container query: saat komponennya yang menentukan

Media query hanya tahu soal viewport. Sebuah kartu yang berada di kolom utama yang lebar sekaligus di sidebar yang sempit pada halaman yang sama perlu tahu ruangnya sendiri. Itulah container query: tandai elemen induk dengan container-type: inline-size, lalu pakai @container dengan kondisi yang sama.

Tarik sudut kotak abu-abu untuk mengubah ukurannya. Kartunya berganti layout saat lebar kotak mencapai 360px, berapa pun ukuran jendelanya:

Di lebar awal 480px, gambarnya berada di samping teks. Tarik kotaknya sampai lebih sempit dari 376px (isi 360px ditambah padding 8px di setiap sisi), dan gambarnya pindah ke atas teks. Container query berfungsi di semua browser utama versi terbaru.

Style untuk mencetak

@media print hanya berlaku saat halaman dicetak atau disimpan sebagai PDF. Sembunyikan navigasi dan tombol, lalu pakai teks gelap di atas latar putih:

@media print {
  nav, .ad, button { display: none; }
  body { color: black; background: white; }
  a::after { content: " (" attr(href) ")"; } /* print the URL after each link */
}

Kesalahan yang sering terjadi

  • Tidak ada meta tag viewport. Ponsel lalu melaporkan layout viewport yang lebar, dan query untuk layar kecil tidak pernah cocok.
  • Urutan query salah. Dua query yang bernilai benar dengan selector yang sama: yang ditulis belakangan yang menang. Urutkan query min-width dari kecil ke besar.
  • Batas yang tumpang tindih atau bercelah. max-width: 768px dan min-width: 768px sama-sama cocok tepat di 768px. Pakai 767px untuk salah satunya, atau sintaks range (width < 768px) dan (width >= 768px).
  • Tidak ada spasi setelah and. and( tidak valid, dan query-nya dibuang tanpa pemberitahuan.
  • Menguji hanya dengan mengubah ukuran jendela desktop. Periksa juga di ponsel sungguhan atau di mode perangkat browser, yang menerapkan viewport, rasio piksel, dan sentuhan ponsel.
  • Terlalu banyak breakpoint. Kalau setiap komponen butuh breakpoint sendiri, coba grid auto-fit, flex-wrap, atau container query.

Pertanyaan yang sering diajukan

Apa itu media query di CSS?

Sebuah aturan yang menerapkan CSS di dalamnya hanya saat kondisi tentang perangkat atau jendela browser terpenuhi. @media (min-width: 600px) { ... } menerapkan style-nya hanya saat lebar viewport minimal 600px. Dengan cara inilah satu halaman bisa menyesuaikan diri dari ponsel sampai desktop.

Sebaiknya memakai media query min-width atau max-width?

Sebagian besar situs ditulis dengan pendekatan mobile first: CSS dasar untuk layar kecil, lalu query min-width menambahkan layout saat layar makin lebar. Query max-width bekerja sebaliknya, dimulai dari layout desktop. Keduanya bisa dipakai, tetapi mencampur keduanya pada elemen yang sama menimbulkan tumpang tindih dan celah di batasnya.

Berapa breakpoint media query yang standar?

Tidak ada standar resmi. Pilihan yang umum ada di sekitar 640px, 768px, 1024px, dan 1280px, tetapi aturan yang lebih baik adalah menambahkan breakpoint di titik layout-mu mulai terlihat salah, dan menjaga jumlah breakpoint tetap sedikit.

Kenapa media query-ku tidak berfungsi di ponsel?

Penyebab paling umum adalah tidak adanya meta tag viewport. Tanpa <meta name="viewport" content="width=device-width, initial-scale=1">, browser ponsel menganggap halaman selebar sekitar 980px, jadi query untuk lebar kecil tidak pernah cocok. Periksa juga bahwa query ditulis setelah aturan yang ingin ditimpanya.

Bagaimana cara menulis media query untuk mode gelap?

Pakai @media (prefers-color-scheme: dark) { ... }. Query ini cocok saat sistem operasi atau browser pengguna diatur ke tema gelap, dan kamu bisa menimpa warna atau variabel CSS di dalamnya.

Apa perbedaan media query dan container query?

Media query menguji viewport (seluruh jendela). Container query, yang ditulis dengan @container, menguji ukuran elemen induk yang kamu tandai dengan container-type: inline-size. Pakai container query untuk komponen yang muncul di tempat yang lebar sekaligus sempit di halaman yang sama.

Ilustrasi bahasa pemrograman di Coddy

Belajar coding dengan Coddy

Mulai