Apa aturan untuk kueri media CSS yang tumpang tindih?

90

Bagaimana kita membagi kueri media secara akurat untuk menghindari tumpang tindih?

Misalnya, jika kita mempertimbangkan kode:

@media (max-width: 20em) {
    /* for narrow viewport */
}

@media (min-width: 20em) and (max-width: 45em) {
    /* slightly wider viewport */
}

@media (min-width: 45em) {
    /* everything else */
}

Apa yang akan terjadi, di semua browser pendukung, tepat pada 20em, dan 45em?

Saya pernah melihat orang-orang menggunakan: hal-hal seperti 799px dan kemudian 800px, tapi bagaimana dengan lebar layar 799.5 px? (Jelas bukan pada tampilan biasa, tapi tampilan retina?)


Saya paling penasaran dengan jawabannya di sini mengingat spesifikasinya.

Baumr
sumber
1
Judul pertanyaan Anda saat ini tampaknya tidak cocok dengan yang Anda tanyakan. Sepertinya baris pertama konten pertanyaan Anda akan lebih cocok dengan judulnya :)
BoltClock
@BoltClock, terima kasih seperti biasa - Saya mengalihkannya; tapi bagaimana Anda mengartikan "memberi jarak kueri media"?
Baumr
1
@Baumr: Pertanyaan bagus - sebenarnya saya tidak begitu mengerti apa yang Anda maksud dengan itu. Sisa pertanyaan saya mengerti dan saya sedang menulis jawaban.
BoltClock
1
Saya akan berasumsi bahwa jika Anda memiliki lebar tepat 20em, maka pertama-tama akan menerapkan max-width: 20emdefinisi, kemudian juga menerapkan min-width: 20emdefinisi.
pengguna
1
@ Baumr, saya percaya ini hanya mengalir sama seperti deklarasi CSS umum. Karena lebar 20em memenuhi kedua kueri, kedua definisi kueri akan diterapkan.
pengguna

Jawaban:

111

Apa aturan untuk kueri media CSS yang tumpang tindih?

Riam.

@mediaaturan transparan ke kaskade, jadi ketika dua @mediaaturan atau lebih cocok pada saat yang sama, browser harus menerapkan gaya di semua aturan yang cocok, dan menyelesaikan kaskade yang sesuai. 1

Apa yang akan terjadi, di semua browser pendukung, tepat pada 20em, dan 45em?

Dengan lebar tepat 20em, kueri media pertama dan kedua Anda akan cocok. Browser akan menerapkan gaya di kedua @mediaaturan dan kaskade yang sesuai, jadi jika ada aturan yang bertentangan yang perlu diganti, aturan yang terakhir dinyatakan menang (memperhitungkan pemilih tertentu !important, dll). Begitu juga untuk media query kedua dan ketiga saat viewport tepat lebarnya 45em.

Mempertimbangkan kode contoh Anda, dengan beberapa aturan gaya aktual ditambahkan:

@media (max-width: 20em) {
    .sidebar { display: none; }
}

@media (min-width: 20em) and (max-width: 45em) {
    .sidebar { display: block; float: left; }
}

Jika area pandang browser tepat selebar 20em, kedua kueri media ini akan mengembalikan nilai true. Dengan kaskade, display: blockmenimpa display: nonedan float: leftakan diterapkan pada elemen apa pun dengan kelas .sidebar.

Anda dapat menganggapnya sebagai menerapkan aturan seolah-olah kueri media tidak ada di sana pada awalnya:

.sidebar { display: none; }
.sidebar { display: block; float: left; }

Contoh lain bagaimana kaskade terjadi saat browser cocok dengan dua atau lebih kueri media dapat ditemukan di jawaban lain ini .

Namun berhati-hatilah, jika Anda memiliki deklarasi yang tidak tumpang tindih di kedua @mediaaturan, maka semua aturan tersebut akan berlaku. Apa yang terjadi di sini adalah penyatuan deklarasi di kedua @mediaaturan, tidak hanya yang terakhir sepenuhnya mengesampingkan yang pertama ... yang membawa kita ke pertanyaan Anda sebelumnya:

Bagaimana kita membagi kueri media secara akurat untuk menghindari tumpang tindih?

Jika Anda ingin menghindari tumpang tindih, Anda hanya perlu menulis kueri media yang saling eksklusif.

Ingat bahwa awalan min-dan max-berarti "inklusif minimum" dan "inklusif maksimum"; ini berarti (min-width: 20em)dan (max-width: 20em)akan cocok dengan viewport yang lebarnya tepat 20em.

Sepertinya Anda sudah memiliki contoh, yang membawa kita ke pertanyaan terakhir Anda:

Saya pernah melihat orang-orang menggunakan: hal-hal seperti 799px dan kemudian 800px, tapi bagaimana dengan lebar layar 799.5 px? (Jelas bukan pada tampilan biasa, tapi tampilan retina?)

Ini saya tidak sepenuhnya yakin; semua nilai piksel di CSS adalah piksel logis, dan saya kesulitan menemukan browser yang akan melaporkan nilai piksel pecahan untuk lebar viewport. Saya sudah mencoba bereksperimen dengan beberapa iframe tetapi belum dapat menemukan apa pun.

Dari percobaan saya, tampaknya Safari di iOS membulatkan semua nilai piksel pecahan untuk memastikan bahwa salah satu dari max-width: 799pxdan min-width: 800pxakan cocok, bahkan jika viewport benar-benar 799.5px (yang tampaknya cocok dengan yang pertama).


1 Meskipun tidak ada yang secara eksplisit dinyatakan baik dalam modul Aturan Bersyarat atau modul Kaskade ( modul yang terakhir saat ini dijadwalkan untuk penulisan ulang), kaskade tersirat berlangsung secara normal, karena spesifikasi hanya mengatakan untuk menerapkan gaya di dan semua @mediaaturan yang cocok dengan browser atau media.

BoltClock
sumber
2
@Baumr: Tidak masalah, meskipun saya belum selesai - saya melewatkan pertanyaan Anda tentang kueri media yang tumpang tindih. Saya telah memperbarui jawaban saya, dan dengan itu saya menyebutnya malam. Oh dan hanya iseng: kueri media adalah salah satu topik favorit saya di CSS, tapi saya tidak tahan dengan istilah RWD;)
BoltClock
BoltClock, mungkin ini pertama kalinya saya menggunakan "RWD" sebenarnya - penerimaan dingin Anda dicatat, haha! Selamat malam, tetapi ketika Anda kembali, lihat pembaruan yang saya buat untuk pertanyaan asli. Sekarang untuk melihat pembaruan Anda ...
Baumr
BoltClock, haruskah saya menghapus pembaruan itu dan membuatnya menjadi pertanyaannya sendiri? Saya merasa saya membuat ini berbelit
Baumr
@Baumr: Ya, jauh lebih baik seperti itu.
BoltClock
BoltClock: Saya mengeluarkannya dan memasukkannya ke dalam, semoga, pertanyaan yang lebih ringkas: Bagaimana cara menghindari tumpang tindih kueri media? - jika Anda memiliki saran edit untuk membuatnya lebih dapat diterapkan ke orang lain, silakan bagikan. PS Ini tidak membiarkan saya @ Anda di komentar.
Baumr
8

Saya telah mencoba seperti yang direkomendasikan di sini:

@media screen and (max-width: calc(48em - 1px)) {
    /*mobile styles*/
}
@media screen and (min-width: 48em) {
    /*desktop styles*/
}

tetapi ternyata ini bukan ide yang baik karena saat ini tidak berfungsi di Chrome baik di desktop Ubuntu atau di ponsel Android saya. (seperti yang dijelaskan di sini: calc () tidak berfungsi dalam kueri media ) Tapi, saya menemukan cara yang lebih baik ...

@media screen and (max-width: 47.9999em) {
    /*mobile styles*/
}
@media screen and (min-width: 48em) {
    /*desktop styles*/
}

dan bam!

Pierre-Verthume Larivière
sumber
Ini harus menjadi jawaban yang diterima. BoltClock memberikan jawaban yang tidak masuk akal, tetapi jawaban ini adalah yang paling berguna!
John Henckel
2

calc()dapat digunakan untuk mengatasi hal ini (min-width: 50em and max-width: calc(50em - 1px)akan ditumpuk dengan benar), tetapi dukungan browser yang buruk dan saya tidak akan merekomendasikannya.

@media (min-width: 20em) and (max-width: calc(45em - 1px)) {
    /* slightly wider viewport */
}

Informasi:

Beberapa orang lain menyebutkan, tidak menggunakan emunit akan membantu dalam penumpukan kueri Anda.

Milche Patern
sumber
7
calc()bukan bagian dari spesifikasi kueri media dan tidak akan berfungsi.
Jason T Featheringham