z-index dan stacking context

Aturan stacking context dan bug z-index yang umum terjadi.

Daftar isi

Topik ini menjelaskan cara browser menentukan elemen mana yang tampil di atas ketika beberapa elemen menumpuk pada posisi yang sama. Pembahasan mencakup urutan penumpukan alami, properti z-index beserta syarat penerapannya, konsep stacking context yang mengurung perhitungan penumpukan, dan bug z-index yang paling sering dijumpai beserta perbaikannya. Diagram pada bagian tengah memperlihatkan mekanisme pengurungan tersebut secara visual.

Urutan penumpukan alami#

Browser menggambar kotak-kotak halaman dalam urutan tertentu, dan kotak yang digambar belakangan menutupi kotak yang digambar lebih dulu. Pada elemen-elemen yang sama-sama tidak terposition, urutan ini mengikuti urutan dokumen. Elemen yang terposition, yaitu elemen dengan nilai position selain static, digambar di atas elemen yang tidak terposition. Di antara dua elemen terposition tanpa z-index, elemen yang muncul belakangan di HTML menutupi yang lebih dulu. Aturan yang sama berlaku pada teks: potongan teks yang digambar belakangan menutupi potongan sebelumnya pada bagian yang tumpang-tindih. Urutan ini berlaku tanpa satu angka penumpuk pun, sehingga disebut urutan penumpukan alami.

Perilaku bawaan itu dapat diamati dari dua kotak absolute yang saling menumpuk:

css Contoh: dua kotak absolute bertumpuk
.kotak-a,
.kotak-b {
  position: absolute;
  top: 0;
  left: 0;
  width: 160px;
  height: 90px;
}

.kotak-a { background-color: #93c5fd; }
.kotak-b { background-color: #fde68a; }

Kotak kotak-b tampil di atas karena digambar belakangan, meskipun keduanya menempel pada sudut yang sama persis. Susunan seperti ini sudah cukup untuk banyak kebutuhan, misalnya menyusun kartu yang bertumpuk pada sebuah ilustrasi. Properti z-index baru diperlukan ketika urutan dokumen tidak lagi cocok dengan urutan visual yang diinginkan.

Properti z-index#

Properti z-index menerima bilangan bulat, termasuk bilangan negatif, dan menentukan posisi elemen pada urutan penumpukan. Nilai yang lebih tinggi digambar di atas nilai yang lebih rendah. Properti ini hanya bekerja pada dua jenis elemen, yaitu elemen terposition dan anak dari kontainer flex atau grid. Pada elemen static di luar kontainer flex atau grid, z-index tidak berpengaruh sama sekali.

Nilai bawaan z-index adalah auto, yang membiarkan elemen mengikuti urutan penumpukan alami. Memberi z-index: 1 pada satu elemen dan z-index: 2 pada elemen lain sudah cukup untuk menukar urutannya. Angka yang jauh lebih besar memang sah, tetapi tidak menambah kepastian apa pun di luar urutan relatifnya.

Konsep stacking context#

Sebuah stacking context adalah kelompok elemen yang dihitung penumpukannya sebagai satu kesatuan terhadap lingkungan di luarnya. Browser membentuk konteks ini pada elemen akar dokumen, lalu membentuk konteks baru pada elemen yang memenuhi kondisi tertentu. Kondisi yang paling sering dijumpai adalah elemen terposition dengan z-index selain auto, elemen dengan opacity kurang dari 1, elemen dengan transform, serta elemen dengan filter.

Akibatnya, z-index anak tidak dibandingkan langsung dengan elemen di luar induknya. Perbandingan pertama terjadi antara induk-induk yang membentuk konteks, dan barulah isi dari konteks pemenang dibandingkan di dalamnya. Anak dengan z-index setinggi apa pun tidak dapat menembus batas konteks induknya. Diagram berikut memperlihatkan situasi tersebut: satu induk bernilai opacity: 0.9 membentuk konteks baru, sedangkan saudaranya yang diberi z-index: 1 tetap menggambar di atas seluruh isinya.

Anak A dengan z-index 9999 tetap tertutup Kotak B karena terkurung stacking context Induk AInduk Aopacity: 0.9, membentuk stacking context baruAnak Az-index: 9999Kotak Bz-index: 1saudara Induk AKotak B menutupi Anak A karena perbandingan z-index hanya dilakukan antara Induk A dan Kotak B.
Anak A tidak dapat menembus stacking context Induk A

Pada diagram, Anak A membawa nilai 9999 sedangkan Kotak B hanya 1, tetapi Kotak B tetap menutupi Anak A. Angka 9999 hanya berlaku di dalam konteks Induk A, sedangkan perbandingan antara Induk A dan Kotak B diselesaikan pada tingkat yang lebih atas. Inilah sebabnya konteks sering disebut batas yang mengurung: nilai anak tidak melewati batas itu.

Bug z-index tinggi yang tetap tertutup#

Bentuk bug yang paling umum terjadi pada komponen dengan efek visual. Kartu diberi animasi kemunculan dengan opacity atau efek naik dengan transform, sedangkan kartu itu memuat tooltip ber-z-index tinggi yang seharusnya menimpa kartu lain. Saat dirender, tooltip justru tertutup kartu berikutnya meskipun angkanya jauh lebih besar. Penyebabnya persis seperti pada diagram sebelumnya: transform atau opacity pada kartu membentuk stacking context baru, sehingga tooltip hanya bersaing di dalam konteks kartunya.

css Contoh: konteks yang mengurung tooltip
.kartu {
  position: relative;
  transform: translateY(0); /* efek hover membentuk stacking context baru */
}

.kartu .tooltip {
  position: absolute;
  z-index: 9999; /* hanya berlaku di dalam konteks kartu */
}

Perbaikannya ada dua arah. Cara pertama adalah menghapus pembentuk konteks pada induk, misalnya menerapkan transform pada elemen di dalam kartu alih-alih pada kartunya. Cara kedua adalah mengangkat konteks induknya, yaitu memberi position: relative dan z-index yang lebih tinggi pada kartu tersebut, sehingga seluruh isinya ikut naik:

css Contoh: perbaikan dengan mengangkat konteks induk
.kartu {
  position: relative;
  z-index: 10; /* konteks kartu yang dinaikkan */
}

Kedua cara menghasilkan tampilan yang sama pada kasus di atas, tetapi keduanya berbeda akibat sampingnya. Menghapus pembentuk konteks menjaga jumlah konteks tetap sedikit dan perilaku penumpukan tetap dapat diprediksi. Mengangkat konteks induk lebih cepat dilakukan, tetapi menambah satu konteks baru yang juga harus dipertimbangkan nilainya terhadap induk-induk sekelilingnya. Pilih cara pertama bila memungkinkan, dan gunakan cara kedua saat struktur animasinya tidak dapat diubah.

Ringkasan#

  • Urutan penumpukan alami menggambar elemen terposition di atas yang tidak terposition, dan elemen belakangan di atas yang lebih dulu.
  • z-index hanya bekerja pada elemen terposition dan anak kontainer flex atau grid, dengan nilai lebih tinggi digambar lebih atas.
  • Stacking context mengurung perhitungan z-index anak-anaknya dan dibentuk oleh, antara lain, opacity kurang dari 1, transform, filter, dan z-index selain auto pada elemen terposition.
  • Tooltip atau menu yang tertutup meskipun z-index-nya besar biasanya terkurung konteks induknya, dan perbaikannya adalah menghapus pembentuk konteks atau mengangkat konteks induk.

Referensi#