
Perbedaan antara berhasil menggunakan CSS dan upaya menyakitkan untuk menghadapinya sering tergantung pada detail kecil. Padahal, CSS memiliki banyak nuansa. Salah satu area paling umum di mana saya sering melihat perjuangan seperti itu adalah tata letak styling. Secara pribadi, saya suka belajar pola CSS. Saya perhatikan bahwa saya cenderung menggunakan sejumlah kecil dari mereka untuk menyelesaikan sebagian besar masalah dengan tata letak. Artikel ini adalah tentang pola-pola CSS yang saya gunakan untuk mengatasi masalah tata letak. Situasi akan dipertimbangkan terlepas dari metodologi CSS yang digunakan: apakah itu SMACSS, BEM, atau bahkan topik CSS-in-JS yang panas, karena semuanya fokus pada properti CSS itu sendiri, dan bukan pada arsitektur, organisasi, atau strategi.
Untuk bersenang-senang, mari kita mulai dengan tes.
Kami akan menggunakan platform yang saya kembangkan, disebut
Questionable.io, dan saya menggunakannya untuk membuat tes, yang akan kita lanjutkan ke bawah. Jangan khawatir, tidak ada data pribadi yang dikumpulkan, hasilnya anonim dan itu benar-benar gratis.
Tujuan pengujian adalah untuk melihat apakah Anda dapat mengenali perilaku CSS tertentu dan beberapa masalah tanpa terlebih dahulu membaca artikel. Saya tidak akan mempersulit pengujian, tetapi nuansa gaya CSS bisa sangat rumit. Ingat, pengujian ini hanya untuk bersenang-senang. Hasil tes tidak menunjukkan kesejukan Anda, tetapi saya berharap mereka tetap berguna.
Tes terdiri dari 10 pertanyaan dan harus memakan waktu tidak lebih dari 10 menit
Dari penerjemah:
Di akhir artikel tentang Habr, jajak pendapat tentang jumlah poin yang dicetak dalam tes ditambahkan.
Catatan: jika Anda tidak ingin membuang waktu,
berikut ini tautan ke pertanyaan dengan jawaban yang benar.
Apakah Anda lulus ujian? Hebat! Mari kita telusuri pertanyaan satu per satu untuk mendapatkan gambaran yang lebih baik tentang pola gaya yang terpengaruh dalam tes.
Pertanyaan 1: Model Blok
Mempelajari model blok harus menjadi prioritas dalam daftar pengembang FrontEnd. Mungkin artikel "
Model Kotak CSS " agak lama, jangan meremehkan nilai dan relevansinya dengan CSS modern. Model blok adalah dasar untuk hampir setiap masalah terkait tata letak CSS.
Pertanyaan khusus ini memeriksa bagaimana cara mencari lebar berdasarkan prinsip-prinsip model blok. Blok memiliki lebar eksplisit melalui properti
width: 100px
, tetapi ternyata
aturan model blok default menerapkan properti
width
ke layer "content" dari blok ini. Lebar yang dihasilkan (seberapa lebar blok digambarkan pada halaman) adalah jumlah dari konten, lapisan dan lapisan perbatasan. Untuk alasan ini, jawabannya adalah 112px.
.box { width: 100px; height: 50px; padding: 5px; border: 1px solid red; background-color: red; }
Jika Anda dihadapkan dengan situasi di mana kolom atau tab terakhir di antarmuka dipindahkan ke baris berikutnya, meskipun Anda menentukan semua
width: 20%;
dan yakin bahwa mereka akan cocok dengan 100% elemen induk, mungkin ini menjadi masalah. Lima kolom dengan lebar 20% ditempatkan di 100%, tetapi jika mereka diberi tambahan padding dan / atau perbatasan, ini akan menambah lebar masing-masing, sehingga tidak cukup ruang di baris saat ini untuk kolom terakhir.
Ketika CSS3 diperkenalkan, alat baru yang disebut
box-sizing
. Hal ini memungkinkan kita untuk mengontrol lapisan model blok yang ingin kita terapkan properti
width
. Sebagai contoh, kita dapat menentukan
box-sizing: border-box
. Ini berarti bahwa kami ingin aturan lebar diterapkan ke lapisan batas luar alih-alih lapisan konten. Dalam pertanyaan dari tes, jika
box-sizing: border-box
properti
box-sizing: border-box
diterapkan, lebar blok yang dihasilkan adalah 100px.
Bagi sebagian dari Anda, ini adalah fakta yang terkenal, tetapi tetap akan menjadi pengingat yang baik bagi para profesional dan pemula.
Ada sejumlah artikel tentang model blok dan cara menggunakan properti ukuran kotak sebagai reset untuk segera menerapkannya ke seluruh proyek.
Ukuran Kotak dan
Warisan ukuran kotak Mungkin Sedikit Lebih Baik Praktik Terbaik adalah dua artikel Trik CSS yang baik untuk dibaca.
Pertanyaan 2: Batas Elemen
Pertanyaan tes kedua sebagian dapat dilihat sebagai kelanjutan dari yang pertama. Ingat, itu satu hal untuk dibaca: "Model blok memiliki lapisan (konten, padding, perbatasan) dan mereka semua mempengaruhi lebar akhir dan tinggi elemen", hal lain adalah untuk dapat mengenali masalah model blok dalam situasi nyata. Masalah khusus ini agak klasik di antara mereka yang telah bekerja dengan CSS selama beberapa waktu. Ini mengikuti dari fakta bahwa frame akan menempati ruang tambahan tertentu dan menjauhkan elemen di sekitarnya, karena mereka adalah bagian dari model blok. Menambahkan bingkai sambil mengubah keadaan elemen, seperti
:hover
, akan berarti bahwa blok akan menjadi lebih besar dan kemudian blok yang mengikuti akan didorong ke bawah. Ini
bisa mengganggu :
Dari semua solusi yang mungkin disebutkan dalam pertanyaan pengujian, menambahkan
border: 2px solid transparent
ke keadaan semula (tanpa melayang) adalah satu-satunya solusi yang mungkin untuk masalah tersebut.
box-sizing
tidak menyelesaikan masalah ini, karena kami tidak secara eksplisit mengatur ketinggian. Jika kami melakukan ini, frame akan menjadi bagian dari keseluruhan tinggi elemen dan pergeseran tidak akan terjadi, tetapi ini bukan kasus kami.
Ada solusi lain yang tidak kami sebutkan dalam opsi jawaban. Salah satunya adalah menambahkan pseudo-border menggunakan properti
box-shadow
atau menggunakan
outline
alih-alih
border
. Masing-masing tidak akan menyebabkan bias, karena itu bukan lapisan model blok. Inilah
artikel Trik CSS lain di mana Anda dapat membaca lebih lanjut tentang solusi semacam itu.
Catatan:
Ingatlah bahwa
outline
tidak mendukung
border-radius
Pertanyaan 3: Posisi - absolut vs tetap
Selain memahami kapan harus menggunakan masing-masing jenis dan
bagaimana mereka berbeda dalam representasi visual , juga sangat penting untuk mengetahui aturan tentang bagaimana masing-masing metode penentuan posisi terikat pada elemen induk menggunakan properti atas, kanan, bawah, atau kiri.
Pertama-tama, mari kita lihat
blok yang berisi . Definisi singkatnya adalah bahwa blok yang mengandung paling sering merupakan induk dari setiap elemen yang dipertanyakan. Namun, aturan untuk blok berisi berbeda untuk elemen yang diposisikan secara mutlak dan tetap.
1) Untuk elemen absolut . Blok yang berisi adalah leluhur terdekat yang posisinya tidak
static
. Misalnya, ketika sebuah elemen diposisikan secara absolut dan berisi properti
top
,
right
,
bottom
atau
left
, mereka akan diposisikan relatif terhadap setiap induk yang memiliki posisi
absolute
,
relative
,
fixed
atau
sticky
.
2) Untuk elemen tetap . Blok yang berisi adalah viewport, meskipun ada elemen induk dengan posisi selain
static
. Selain itu, perilaku gulir berbeda dari elemen yang diposisikan benar-benar. Elemen tetap tetap "tetap" di area tampilan, karenanya namanya.
Banyak pengembang berpikir bahwa elemen yang diposisikan benar-benar hanya mencari elemen induk terdekat dengan posisi
position: relative
. Kesalahpahaman ini telah menyebar luas hanya karena
position: relative
paling sering ditentukan berpasangan dengan
position: absolute
untuk membuat blok yang mengandung. Alasan mengapa ini sering digunakan adalah bahwa posisi relatif dari blok induk membiarkannya
dalam aliran , yang sering lebih disukai. Ada situasi di mana induk dari elemen yang diposisikan mutlak itu sendiri diposisikan sepenuhnya. Ini sangat normal. Jika semua orang tua statis, maka elemen yang benar-benar diposisikan akan dilampirkan ke viewport - tetapi agar itu bergulir bersama dengan viewport.
Ada sedikit tambahan aturan yang disebutkan di atas: dalam situasi di mana elemen induk memiliki properti
transform
(
antara lain ) dengan nilai selain
none
, itu menjadi blok yang berisi elemen yang diposisikan secara mutlak dan tetap. Konfirmasi ini dapat dilihat di CodePen, di mana elemen dengan teks "Perhatikan!" Merupakan elemen tetap, dan induk memiliki properti transformasi, tetapi hanya ketika kursor mouse di atasnya (dalam status
:hover
)
Pertanyaan 4: Ciutkan margin elemen orang tua dan anak
Ini adalah salah satu dari hal-hal kecil CSS yang dapat menyebabkan banyak masalah jika Anda tidak tahu cara kerjanya. Ada konsep yang disebut margin runtuh dan banyak orang yang akrab dengan manifestasi ini, yang disebut margin runtuh saudara kandung yang berdekatan. Namun, ada bentuk lain, yang disebut Ciutkan margin dari orang tua dan anak pertama / terakhir, yang kurang dikenal. Berikut ini adalah demonstrasi kedua kasus:
Setiap tag paragraf memiliki margin atas dan bawah sama dengan 1em, yang ditata oleh browser. Sejauh ini ini adalah bagian termudah dari situasi ini. Tapi mengapa jarak antar paragraf bukan 2em (jumlah atas dan bawah)? Ini disebut runtuh margin saudara kandung yang berdekatan. Margin tumpang tindih sedemikian rupa sehingga semakin besar dari dua margin akan menjadi ukuran kesenjangan, jadi dalam hal ini kesenjangan akan menjadi 1 em.
Namun, sesuatu yang aneh sedang terjadi. Apakah Anda memperhatikan bahwa margin atas paragraf pertama tidak membuat celah antara itu dan div wadah biru? Alih-alih melanggar, tampaknya menanamkan margin di div induk, seolah-olah div memiliki margin atas. Ini disebut Runtuh margin orang tua dan anak pertama / terakhir. Jenis margin keruntuhan ini tidak akan terjadi dalam keadaan tertentu jika berikut ini merupakan karakteristik dari induk:
- Ada padding atas / bawah lebih besar dari nol
- Ada batas atas / bawah lebih besar dari nol
- Konteks pemformatan blok ditentukan yang dapat dibuat menggunakan
overflow: hidden
atau overflow: auto
- Tampilan: rangkaian properti root-rooting (dukungan browser buruk)
Ketika saya senang menjelaskan kepada orang-orang ini detail CSS kecil dan menyelesaikannya dengan padding atau border, jawabannya hampir selalu: "Bagaimana dengan padding atau border sama dengan 0?". Ya, ini tidak berhasil, karena nilainya harus bilangan bulat positif.
Pada contoh sebelumnya, padding 1px memungkinkan kita untuk beralih antara menggunakan collapse dan mencegah margin yang menyusut dari induk dan anak. Ruang yang muncul antara paragraf pertama / terakhir dan induk adalah padding 1px, tetapi sekarang margin dianggap bagian dalam wadah, karena lapisan padding menciptakan penghalang untuk mencegah margin dari runtuh.
Adapun pertanyaannya, saya yakin Anda dapat melihat apa masalahnya di antarmuka ini:
Elemen pertama dengan kelas
.comment
(tanpa kelas
.moderator
) mengecilkan margin. Bahkan tanpa melihat kode, kita dapat melihat bahwa elemen dengan kelas
.moderator
memiliki bingkai, dan elemen tanpa kelas ini tidak. Sebenarnya ada tiga jawaban atas pertanyaan ini yang dianggap benar. Masing-masing, pada kenyataannya, sudah diterapkan di sumber CodePen, mereka hanya berkomentar.
Salah satu alasan mengapa jenis margin keruntuhan ini tidak sebanyak yang dikenal sebagai yang lain adalah karena ada banyak situasi di mana kita dapat menghindarinya secara tidak sengaja. Elemen Flexbox dan Grid membuat konteks pemformatan blok, jadi saat menggunakannya, kami tidak menemukan jenis margin runtuh ini. Jika antarmuka komentar kami adalah proyek nyata, kemungkinan bagus bahwa bantalan ditetapkan pada keempat sisi untuk meninggalkan ruang sekitar, dan ini, pada gilirannya, memperbaiki keruntuhan margin bagi kami.
Pertanyaan 5: Persentase dari apa?
Ketika satuan persentase digunakan, persentase didasarkan pada lebar atau tinggi blok yang mengandung (biasanya induknya). Seperti yang kami katakan sebelumnya, elemen dengan properti
transform
akan menjadi blok yang berisi, jadi ketika elemen menggunakan transformasi, unit dalam persen (hanya untuk
transform
)
pada ukuran elemen itu sendiri, dan bukan pada ukuran induk.
Dalam contoh di bawah ini, kita dapat melihat bahwa 50% mengambil dua nilai berbeda tergantung pada konteksnya. Blok merah pertama memiliki properti
margin-left: 50%
, dan blok merah kedua menggunakan
transform: translateX(50%)
.
Pertanyaan 6: Model blok mogok lagi ...
Hanya Anda yang berpikir bahwa kami telah selesai berbicara tentang model blok ...
Masalahnya adalah karena kami menggunakan
width: 100%
untuk footer dan pada saat yang sama menambahkan padding. Lebar wadah adalah 500px, yang berarti bahwa lapisan konten footer (menjadi 100%) juga 500px sebelum paddings ditambahkan ke ukuran ini.
Masalahnya dapat diperbaiki dengan salah satu dari dua teknik umum:
- Gunakan properti ukuran kotak untuk footer secara langsung atau melalui reset yang disebutkan sebelumnya
- Hapus properti
width
dari elemen dan gunakan properti left: 0
dan right: 0
. Ini adalah contoh yang baik untuk menggunakan properti left
dan right
pada saat yang bersamaan. Pendekatan ini menghindari masalah model blok, karena properti width
akan menggunakan nilai default auto
untuk mengisi ruang yang tersedia antara padding dan batas ketika left: 0
dan right:0
.
Catatan: Salah satu opsi adalah untuk menghapus bantalan dari footer. Secara teknis, ini akan memperbaiki masalah, karena lapisan konten akan 100% dan tidak memiliki bantalan atau perbatasan untuk memperluas di luar lebar wadah. Tapi saya pikir solusi ini adalah pendekatan yang salah, karena kita tidak perlu mengubah antarmuka kita untuk beradaptasi dengan masalah model blok, yang mudah diperbaiki tanpa itu.
Kenyataannya bagi saya adalah bahwa saya selalu memiliki
box-sizing: border-box
properti
box-sizing: border-box
sebagai bagian dari reset gaya umum saya. Jika Anda melakukan hal yang sama, kemungkinan besar Anda jarang mengalami masalah ini. Tapi saya masih suka teknik dengan mengatur properti
left:0
dan
right:0
pada saat yang sama, karena, seperti yang ditunjukkan oleh waktu, itu lebih dapat diandalkan (dalam hal apapun, menilai dari pengalaman saya) daripada memecahkan masalah model blok yang muncul karena lebar 100%
Pertanyaan 7: Memusatkan Elemen Mutlak dan Tetap
Sekarang kita benar-benar mulai menggabungkan semua materi yang dijelaskan di atas, dengan pemusatan elemen absolut dan tetap:
Karena kita telah membahas sebagian besar materi dalam pertanyaan pengujian ini, saya hanya menunjukkan bahwa pemusatan horizontal dan vertikal dapat dilakukan dengan menggunakan metode old-school melalui margin negatif, atau yang lebih baru menggunakan properti transform. Saya juga membawa kepada Anda
panduan pemusatan elemen CSS-Trik yang bagus .
Catatan : beberapa waktu lalu dikatakan bahwa jika kita mengetahui lebar dan tinggi blok, kita harus menggunakan margin negatif, karena mereka bekerja lebih stabil daripada properti transformasi baru. Saat ini, transformasi bekerja dengan stabil dan saya hampir selalu menggunakan properti ini, kecuali saya perlu menghindari mengubah blok ke yang mengandung.
Pertanyaan 8: Memusatkan elemen dalam aliran normal
Flexbox memberi kami banyak alat luar biasa untuk menyelesaikan masalah tata letak yang rumit. Sebelum dirilis, dilaporkan bahwa pemusatan vertikal adalah salah satu fitur paling kompleks yang diterapkan dalam CSS. Dengan munculnya Flexbox, pemusatan vertikal telah menjadi rutin:
.parent { display: flex; } .child { margin: auto; }
https://codepen.io/bradwestfall/pen/GPNmbMCatatan : perhatikan bahwa untuk elemen flex, margin: otomatis diterapkan ke atas, bawah, kanan dan kiri untuk memusatkan elemen secara vertikal dan horizontal. Sebelumnya, pemusatan vertikal tidak berfungsi untuk elemen blok, jadi
margin: 0 auto;
cukup umum
margin: 0 auto;
Pertanyaan 9: Perhitungan dengan unit yang berbeda
Menggunakan fungsi calc () sangat bagus ketika Anda perlu bekerja dengan dua unit pengukuran yang tidak bisa kita tambahkan sendiri atau ketika kita perlu membuat pecahan
lebih mudah dipahami . Pertanyaan tes ini menawarkan kita untuk mencari tahu seperti apa hasil dari ekspresi
calc(100% + 1em)
akan terlihat, mulai dari fakta bahwa lebar elemen div adalah 100px. Ini bisa sedikit membingungkan, karena pada kenyataannya, tidak masalah bahwa lebar elemen div adalah 100px. Persentase selalu dimulai dari lebar induk, jadi jawaban yang benar adalah: "100% dari blok yang berisi (induk) ditambah 1em".
Ada beberapa situasi di mana saya secara teratur menggunakan
calc()
. Pertama, setiap kali saya ingin mengubah sesuatu sebesar 100%, tetapi juga menambahkan jumlah ruang ekstra yang tetap. Menu dropdown bisa menjadi contoh yang baik untuk ini:
Keunikan di sini adalah bahwa kami ingin membuat menu tarik-turun yang dapat digunakan bersama-sama dengan elemen pemanggil ukuran yang berbeda (dalam hal ini, dua ukuran tombol yang berbeda). Kami tidak tahu berapa tinggi elemen yang memanggil menu ini, tetapi kami tahu itu
top: 100%
akan menempatkan tepi atas menu tarik-turun di tepi bawah tombol panggil. Jika setiap menu berada di tepi bawah tombol yang sesuai, ditambah 0,5em, ini dapat dicapai dengan
calc(100% + 0.5em)
. Tentu saja, kita juga bisa menggunakan
top: 110%
, tetapi tambahan 10% ini akan tergantung pada ketinggian tombol dan wadah panggilan.
Pertanyaan 10: Margin negatif
Tidak seperti margin positif yang mengusir saudara kandung, margin negatif membuat mereka lebih dekat satu sama lain
tanpa mengubah saudara kandung . Pertanyaan tes akhir ini menawarkan dua solusi, yang keduanya secara teknis menghilangkan batas ganda pada kelompok tombol kami, tetapi saya sangat menyukai teknik margin negatif, karena menghapus bingkai akan membuatnya lebih sulit untuk melakukan teknik-teknik tertentu, seperti efek mouseover.
Efek yang dihasilkan adalah "batas umum" yang ditampilkan di antara tombol. Faktanya, tombol tidak dapat memiliki batas bersama, jadi kita perlu menggunakan teknik margin negatif sehingga satu frame saling tumpang tindih. Kemudian saya menggunakan
z-index
untuk mengatur frame mana yang ingin saya paskan di atas yang lain, berdasarkan pada kondisi mouse hover. Perhatikan bahwa
z-index
berguna di sini bahkan tanpa menggunakan penentuan posisi absolut, tetapi Anda harus mengatur
position: relative
. Jika saya menggunakan teknik menghapus bingkai kiri tombol kedua, efek ini akan jauh lebih sulit untuk diterapkan.
Itu semua masuk akal.
Saya ingin menunjukkan kepada Anda demo terbaru lainnya yang menggunakan banyak trik yang telah kita bahas sebelumnya. Tugasnya adalah membuat ubin yang meluas ke tepi kiri dan kanan wadah, dengan mempertimbangkan lekukan. Dengan ubin, maksud saya kemampuan untuk memiliki daftar blok yang membungkus ke baris berikutnya ketika tidak ada cukup ruang lebar. Arahkan kursor ke ubin untuk melihat hasilnya:
Hambatan dalam melakukan tugas ini adalah lekukan. Tanpa bantalan, akan mudah untuk mendapatkan ubin yang berdekatan dengan tepi kiri dan kanan wadah. Masalahnya adalah bahwa indentasi akan dibuat menggunakan margin, dan ketika kami menambahkan margin di semua sisi ubin, kami membuat dua masalah:
- Kehadiran tiga ubin dengan lebar
33.33%
bersamaan dengan margin tidak akan bisa masuk berturut-turut. Meskipun box-sizing
memungkinkan kami memiliki lapisan dan tepi pada elemen .tile
dan pas di 33.33%
, ini tidak akan membantu kami dalam hal margin - yang berarti bahwa lebar yang dihitung dari ketiga ubin akan lebih dari 100%, yang akan memaksa ubin terakhir untuk pindah ke yang berikutnya tali.
- Ubin kiri dan kanan tidak lagi terletak di tepi wadah.
Masalah pertama bisa diselesaikan dengan calc((100% / 3) - 1em)
. Yang berarti 33,33% dikurangi margin kiri dan kanan setiap ubin. Runtuhnya elemen saudari yang berdekatan tidak akan terjadi di sini, karena hanya mungkin pada margin atas dan bawah. Akibatnya, jarak horizontal antara dua ubin adalah jumlah dari dua margin (1em). Dalam hal ini, keruntuhan juga tidak berlaku untuk margin atas dan bawah, karena ubin pertama dan terakhir tidak berdekatan secara teknis, bahkan jika secara visual satu di bawah yang lain.Dengan membawacalc()
Tiga ubin dapat masuk secara berurutan, tetapi mereka masih tidak menyentuh tepi wadah. Untuk melakukan ini, kita dapat menggunakan margin negatif dalam ukuran yang sama dengan margin kiri dan kanan setiap ubin. Garis putus-putus hijau dalam contoh adalah wadah tempat kami menerapkan margin negatif untuk menggambar ubin yang sesuai dengan tepi konten sekitarnya. Kita bisa melihat bagaimana mereka cocok dengan area padding dari elemen induk. Ini normal karena margin negatif tidak mengusir elemen tetangga.Sebagai hasilnya, kami mendapatkan ubin yang memiliki ruang yang cukup yang berkembang dari tepi ke tepi sehingga mereka sejajar dengan tag paragraf yang berdekatan di luar ubin.Ada banyak cara untuk membuat ubin (dan biasanya mereka memiliki kelebihan dan kekurangannya). Sebagai contoh, ada solusi CSS Grid yang cukup elegan yang dibicarakan oleh Haydon Pickering. Solusi ini diimplementasikan menggunakan teknik yang mensimulasikan permintaan untuk kontainer (tetapi menggunakan Grid magic). Pada akhirnya, solusinya menggunakan Grid lebih baik daripada flexbox, yang saya contohkan tetapi memiliki dukungan browser yang lebih buruk.Ringkasan
Pada awalnya, saya menyatakan bahwa saya cenderung mencari pola dalam memecahkan masalah. Artikel ini tidak banyak membahas tentang skenario yang ditunjukkan di atas; ini lebih tentang seperangkat alat yang dapat digunakan untuk memecahkan ini dan banyak masalah penyusunan huruf lain yang kita semua bisa hadapi. Saya harap alat ini membantu Anda.Ngomong-ngomong, ada sejumlah sumber daya luar biasa yang dengan cermat memeriksa topik model blok. Pertama-tama, artikel oleh Rachel Andrew dan Jen Simmons, yang pasti layak dibaca.- Box Alignment Cheatsheet adalah materi hebat dengan elemen visual yang menekankan berbagai properti yang memengaruhi bagaimana elemen-elemen itu menyelaraskan baik elemennya sendiri atau relatif terhadap elemen lain.
- Jen Simmons Labs — , .