Memecah Kotak Dengan Fragmentasi CSS
Diterbitkan: 2022-03-10Pada artikel ini, saya akan memperkenalkan Anda pada spesifikasi Fragmentasi CSS. Anda mungkin belum pernah mendengarnya, namun, jika Anda pernah membuat lembar gaya cetak dan ingin mengontrol di mana konten terputus di antara halaman, atau tata letak multi-kolom dan ingin menghentikan gambar yang pecah di antara kolom, Anda telah menemukannya.
Saya menemukan bahwa cukup sering masalah yang dilaporkan orang dengan multicol benar-benar masalah dengan dukungan browser untuk fragmentasi. Setelah ikhtisar singkat tentang properti yang terkandung dalam spesifikasi ini, saya akan menjelaskan status dukungan browser saat ini dan beberapa hal yang dapat Anda lakukan untuk membuatnya berfungsi sebaik mungkin dalam proyek multikolom dan pencetakan Anda.
Apa itu Fragmentasi?
Fragmentasi dalam CSS menjelaskan proses dimana konten menjadi dipecah menjadi kotak yang berbeda. Saat ini, kami memiliki dua tempat di mana kami mungkin mengalami fragmentasi di web: saat kami mencetak dokumen, dan jika kami menggunakan tata letak multi-kolom. Kedua hal ini pada dasarnya sama. Saat Anda mencetak (atau menyimpan ke PDF) halaman web, konten dipecah menjadi halaman sebanyak yang diperlukan untuk mencetak konten Anda.
Saat Anda menggunakan multikol, konten dipecah menjadi kolom. Setiap kotak kolom seperti halaman dalam konteks halaman. Jika Anda menganggap sekumpulan kolom sama seperti sekumpulan halaman, ini bisa menjadi cara yang membantu untuk memikirkan tentang multikol dan bagaimana fragmentasi bekerja di dalamnya.
Jika Anda melihat Spesifikasi Fragmentasi CSS, Anda akan melihat konteks terfragmentasi ketiga yang disebutkan — konteks itu adalah Wilayah. Karena tidak ada implementasi Regions yang dapat digunakan saat ini, kami tidak akan membahasnya di artikel ini, melainkan melihat dua konteks yang mungkin Anda temui dalam pekerjaan Anda.
Blokir Dan Kotak Sebaris
Saya akan banyak menyebutkan kotak blok di artikel ini. Setiap elemen halaman Anda memiliki kotak. Beberapa dari kotak-kotak itu ditata sebagai blok: paragraf, item daftar, judul. Ini dikatakan berpartisipasi dalam konteks pemformatan blok. Lainnya inline seperti kata-kata dalam paragraf, span dan elemen jangkar. Ini berpartisipasi dalam konteks pemformatan sebaris. Sederhananya, ketika saya merujuk ke kotak blok, saya berbicara tentang kotak di sekitar hal-hal seperti paragraf. Ketika berhadapan dengan fragmentasi, penting untuk mengetahui jenis kotak yang Anda hadapi.
Untuk informasi lebih lanjut tentang tata letak blok dan sebaris, lihat artikel MDN “Blokir dan Tata Letak Sebaris Dalam Aliran Normal”. Ini adalah salah satu hal yang mungkin kita semua mengerti pada tingkat tertentu tetapi mungkin tidak menemukan terminologi sebelumnya.
Mengontrol Istirahat
Baik Anda membuat lembar gaya cetak, menggunakan agen pengguna cetak tertentu untuk membuat PDF, atau menggunakan multikol, terkadang Anda akan mengalami masalah yang terlihat seperti ini.
Dalam contoh multicol di bawah ini, saya memiliki beberapa konten yang saya tampilkan sebagai tiga kolom. Di tengah konten ada area kotak, yang dipecah menjadi dua kolom. Saya tidak ingin perilaku ini — saya ingin kotak itu tetap bersama.
Untuk memperbaikinya, saya menambahkan properti break-inside: avoid
ke kotak. Properti break-inside
mengontrol break di dalam elemen ketika mereka berada dalam konteks yang terfragmentasi. Di browser yang mendukung properti ini, kotak sekarang akan tetap berada di salah satu kolom. Kolom akan terlihat kurang seimbang, namun, itu umumnya merupakan hal yang lebih baik daripada berakhir dengan pemisahan kotak di seluruh kolom.
Properti break-inside
adalah salah satu properti yang dirinci dalam spesifikasi fragmentasi. Daftar lengkap properti adalah sebagai berikut:
-
break-before
-
break-after
-
break-inside
-
orphans
-
widows
-
box-decoration-break
Mari kita lihat bagaimana ini seharusnya bekerja sebelum kita beralih ke apa yang sebenarnya terjadi di browser.
Properti break-before
Dan break-after
Ada dua properti yang mengontrol jeda antara kotak level blok: break-before
dan break-after
. Jika Anda memiliki h2
diikuti oleh dua paragraf <p>
Anda memiliki tiga kotak blok dan Anda akan menggunakan properti ini untuk mengontrol jeda antara judul dan paragraf pertama, atau di antara dua paragraf.
Properti digunakan pada pemilih yang menargetkan elemen yang ingin Anda pecahkan sebelum atau sesudahnya.
Misalnya, Anda mungkin ingin lembar gaya cetak Anda masuk ke halaman baru setiap kali ada judul level 2. Dalam hal ini, Anda akan menggunakan break-before: page
pada elemen h2
. Ini mengontrol fragmentasi dan memastikan selalu ada jeda sebelum kotak elemen h2
.
h2 { break-before: page; }
Persyaratan umum lainnya adalah untuk mencegah heading berakhir sebagai hal terakhir pada halaman atau kolom. Dalam hal ini, Anda dapat menggunakan break-after
dengan nilai dari avoid
. Ini harus mencegah jeda langsung setelah kotak elemen:
h1, h2, h3, h4 { break-after: avoid; }
Fragmen Dalam Fragmen
Ada kemungkinan Anda memiliki elemen yang terfragmentasi bersarang di dalam elemen lain. Misalnya, memiliki multikol di dalam sesuatu yang di-page. Dalam hal ini, Anda mungkin ingin mengontrol jeda untuk halaman tetapi tidak untuk kolom, atau sebaliknya. Inilah sebabnya mengapa kami memiliki nilai seperti page
yang akan selalu memaksa jeda sebelum atau sesudah elemen tetapi hanya jika fragmennya adalah halaman. Atau avoid-page
yang akan menghindari jeda sebelum atau sesudah elemen hanya untuk konteks halaman.
Hal yang sama berlaku untuk kolom. Jika Anda menggunakan column
nilai , ini akan selalu memaksa jeda sebelum atau sesudah elemen itu, tetapi hanya untuk konteks multikolom. Nilai avoid-column
akan mencegah pemutusan dalam konteks multikolom.
always
ada nilai dalam spesifikasi Level 4 yang menunjukkan bahwa Anda ingin menerobos semuanya — halaman atau kolom. Namun, sebagai tambahan terbaru untuk spesifikasi, saat ini tidak berguna bagi kami.
Nilai Tambahan Untuk Media Berhalaman
Jika Anda membuat buku atau majalah, Anda memiliki halaman kiri dan kanan. Anda mungkin ingin mengontrol pemutusan untuk memaksakan sesuatu ke halaman kiri atau kanan spread. Oleh karena itu, menggunakan yang berikut ini akan menyisipkan satu atau dua halaman sebelum h2
untuk memastikan itu diformat sebagai halaman yang benar.
h2 { break-before: right; }
Ada juga nilai recto dan verso yang berhubungan dengan perkembangan halaman karena buku yang ditulis dalam bahasa vertikal atau kanan ke kiri memiliki perkembangan halaman yang berbeda dari buku yang ditulis dalam bahasa Inggris. Saya tidak akan membahas nilai-nilai ini lebih jauh dalam artikel ini karena saya terutama memperhatikan apa yang mungkin dari browser kali ini.
break-inside
Kita telah melihat contoh properti break-inside
. Properti ini mengontrol pemecahan di dalam kotak blok, misalnya di dalam paragraf, heading, atau div.
Hal-hal yang mungkin tidak ingin Anda pecahkan dapat mencakup boxout seperti yang dijelaskan di atas: gambar di mana Anda tidak ingin keterangannya terlepas dari gambar, tabel, daftar, dan sebagainya. Tambahkan break-inside: avoid
ke wadah apa pun yang tidak ingin Anda pecahkan dalam konteks fragmentasi apa pun. Jika Anda hanya ingin menghindari jeda antar kolom, gunakan break-inside: avoid-column
dan antar halaman break-inside: avoid-page
.
orphans
dan widows
Properti orphans
dan widows
berurusan dengan berapa banyak baris yang harus ditinggalkan sebelum atau sesudah jeda (baik disebabkan oleh kolom atau halaman baru). Misalnya, jika saya ingin menghindari satu baris tertinggal di akhir kolom, saya akan menggunakan properti orphans
, seperti dalam tipografi, anak yatim adalah baris pertama paragraf yang muncul sendirian di bagian bawah halaman dengan sisa paragraf dipecah ke halaman lain. Properti harus ditambahkan ke elemen yang sama yang terfragmentasi (dalam kasus kami, wadah multikol).
.container { column-count: 3; orphans: 2; }
Untuk mengontrol berapa banyak baris yang harus berada di bagian atas kolom atau halaman setelah jeda, gunakan widows
:
.container { column-count: 3; widows: 2; }
Properti ini menangani jeda antara kotak sebaris seperti baris kata di dalam paragraf. Oleh karena itu, mereka tidak membantu dalam situasi di mana heading atau elemen blok lainnya sendirian di bagian bawah kolom atau halaman, Anda memerlukan properti break yang dibahas di atas untuk itu.
Dekorasi Kotak
Properti terakhir yang mungkin menarik adalah properti box-decoration-break
. Ini mengontrol situasi di mana Anda memiliki kotak dengan batas yang rusak di antara dua kotak kolom atau halaman. Apakah Anda ingin perbatasan pada dasarnya diiris menjadi dua? Atau apakah Anda ingin masing-masing dari dua bagian kotak itu dibungkus sepenuhnya dalam bingkai?
Skenario pertama adalah default, dan seolah-olah Anda mengatur properti box-decoration-break
untuk slice
pada kotak.
.box { box-decoration-break: slice; }
Untuk mendapatkan perilaku kedua, setel box-decoration-break
ke clone.
.box { box-decoration-break: clone; }
Dukungan Browser Untuk Fragmentasi
Sekarang kita sampai pada alasan mengapa saya tidak memiliki banyak contoh CodePen di atas untuk mendemonstrasikan semua ini kepada Anda, dan alasan utama saya menulis artikel ini. Dukungan browser untuk properti ini tidak bagus.
Jika Anda bekerja di Paged Media dengan agen pengguna tertentu seperti Prince, maka Anda dapat menikmati dukungan yang sangat baik untuk fragmentasi, dan mungkin akan menemukan properti ini sangat berguna. Jika Anda bekerja dengan browser web, baik dalam multikolom, membuat lembar gaya cetak, atau menggunakan sesuatu seperti Chrome Tanpa Kepala untuk menghasilkan PDF, dukungannya agak tidak merata. Anda akan menemukan bahwa browser dengan dukungan terbaik adalah Edge — sampai tetap berpindah ke Chromium!
Can I Use tidak terlalu membantu dengan menjelaskan dukungan karena mencampurkan properti fragmentasi dengan multikol, kemudian memiliki beberapa data terpisah untuk properti lawas. Jadi, sebagai bagian dari pekerjaan yang telah saya lakukan untuk MDN untuk mendokumentasikan properti dan dukungannya, saya mulai menguji dukungan browser yang sebenarnya. Berikut ini adalah beberapa saran berdasarkan pengujian itu.
Properti Awalan Legacy Dan Vendor
Saya tidak bisa melangkah lebih jauh tanpa pelajaran sejarah. Jika Anda merasa benar-benar membutuhkan dukungan untuk fragmentasi maka Anda mungkin menemukan beberapa kelegaan di properti warisan yang awalnya merupakan bagian dari CSS2 (atau di beberapa properti awalan yang ada).
Di CSS2, ada properti untuk mengontrol pemecahan halaman. Multicol tidak ada pada saat itu, jadi satu-satunya konteks yang terfragmentasi adalah konteks halaman. Ini berarti bahwa tiga properti pemecah halaman khusus diperkenalkan:
-
page-break-before
-
page-break-after
-
page-break-inside
Ini bekerja dengan cara yang mirip dengan properti yang lebih umum tanpa awalan page-
, mengontrol jeda sebelum, sesudah, dan di dalam kotak. Untuk lembar gaya cetak, Anda akan menemukan bahwa beberapa browser lama yang tidak mendukung properti break-
baru, mendukung properti awalan halaman ini. Properti diperlakukan sebagai alias untuk properti baru.
Dalam Draf Kerja 2005 dari spesifikasi multikol adalah rincian sifat pemutusan untuk multikol — menggunakan properti yang diawali dengan column-
(yaitu column-break-before
, column-break-after
, dan column-break-inside
). Pada tahun 2009, ini telah hilang, dan sebuah draf berada dalam spesifikasi multicol untuk properti break yang tidak diperbaiki yang akhirnya masuk ke spesifikasi Fragmentasi CSS.
Namun, beberapa properti khusus kolom awalan vendor diimplementasikan berdasarkan properti ini. Ini adalah:
-
-webkit-column-break-before
-
-webkit-column-break-after
-
-webkit-column-break-inside
Dukungan Untuk Fragmentasi Dalam Multicol
Berikut ini didasarkan pada pengujian fitur-fitur ini dalam konteks multikolom. Saya sudah mencoba menjelaskan apa yang mungkin, tetapi lihatlah CodePens di browser mana pun yang Anda miliki.
Multicol Dan break-inside
Dukungan dalam multikol adalah yang terbaik untuk properti break-inside
. Versi terbaru dari Chrome, Firefox, Edge, dan Safari semuanya mendukung break-inside: avoid
. Jadi, Anda harus menemukan bahwa Anda dapat mencegah kotak pecah di antara kolom saat menggunakan multikol.
Beberapa browser, kecuali Firefox, mendukung properti -webkit-column-break-inside
, ini dapat digunakan dengan nilai avoid
dan dapat mencegah pecahnya kotak di antara kolom yang tidak mendukung break-inside
.
Firefox mendukung page-break-inside: avoid
di multicol. Oleh karena itu, menggunakan properti ini akan mencegah kerusakan di dalam kotak di browser Firefox sebelum Firefox 65.
Ini berarti bahwa jika Anda ingin mencegah jeda antar kotak dalam multikol, menggunakan CSS berikut akan mencakup browser sebanyak mungkin, mundur sejauh mungkin.
.box { -webkit-column-break-inside: avoid; page-break-inside: avoid; break-inside: avoid; }
Adapun nilai column
, secara eksplisit menyatakan bahwa Anda hanya ingin menghindari jeda antar kolom, dan bukan halaman, berfungsi di semua browser kecuali Firefox.
CodePen di bawah ini merangkum beberapa tes ini dalam multikol sehingga Anda dapat mencobanya sendiri.
Multicol Dan break-before
Untuk mencegah jeda sebelum elemen, Anda harus dapat menggunakan break-before: avoid
atau break-before: avoid-column
. Properti menghindari tidak memiliki dukungan browser.
Edge mendukung break-before: column
untuk selalu memaksa break sebelum kotak elemen.
Safari, Chrome, dan Edge juga mendukung -webkit-column-break-before: always
yang akan memaksa break sebelum kotak elemen. Oleh karena itu, jika Anda ingin memaksa jeda sebelum kotak elemen, Anda harus menggunakan:
.box { -webkit-column-break-before: always; break-before: column; }
Mencegah istirahat sebelum kotak saat ini merupakan tugas yang mustahil. Anda dapat bermain-main dengan beberapa contoh properti di bawah ini:
Multicol Dan break-after
Untuk mencegah jeda setelah elemen, untuk menghindarinya menjadi hal terakhir di bagian bawah kolom, Anda harus dapat menggunakan break-after: avoid
dan break-after: avoid-column
. Satu-satunya browser dengan dukungan untuk ini adalah Edge.
Edge juga mendukung pemutusan paksa setelah elemen dengan menggunakan break-after: column
, Chrome mendukung break-after: column
dan juga -webkit-column-break-after: always
.
Firefox tidak mendukung break-after
atau properti awalan apa pun untuk memaksa atau mengizinkan jeda setelah kotak.
Oleh karena itu, selain Edge, Anda tidak dapat benar-benar menghindari jeda setelah sebuah kotak. Jika Anda ingin memaksanya, Anda akan mendapatkan hasil di beberapa browser dengan menggunakan CSS berikut:
.box { -webkit-break-after: always; break-after: column; }
Dukungan Saat Mencetak Dari Browser
Apakah Anda mencetak langsung dari browser desktop atau membuat file PDF menggunakan Chrome tanpa kepala atau solusi lain yang bergantung pada teknologi browser tidak ada bedanya. Anda bergantung pada dukungan browser untuk properti fragmentasi.
Jika Anda membuat lembar gaya cetak, Anda akan menemukan dukungan serupa untuk properti break seperti untuk multikol; namun, untuk mendukung browser lama, Anda harus menggandakan properti untuk menggunakan properti awalan page-
.
Cetak Stylesheet Dan break-inside
Di browser modern, properti break-inside
dapat digunakan untuk mencegah jeda di dalam kotak, tambahkan properti page-break-inside
untuk menambahkan dukungan untuk browser lama.
.box { page-break-inside: avoid; break-inside: avoid; }
Cetak Stylesheet Dan break-before
Untuk memaksa jeda sebelum kotak gunakan break-before:page
bersama dengan page-break-before: always
.
.box { page-break-before: always; break-before: page; }
Untuk menghindari jeda sebelum kotak gunakan break-before: avoid-page
bersama dengan page-break-before: avoid
.
.box { page-break-before: avoid; break-before: avoid-page; }
Ada dukungan yang lebih baik untuk nilai page
dan avoid-page
daripada yang kita lihat untuk nilai multikolom yang setara. Mayoritas browser modern memiliki dukungan.
Cetak Stylesheet Dan break-before
Untuk memaksa jeda setelah kotak, gunakan break-after: page
bersama dengan page-break-after: always
.
.box { page-break-after: always; break-after: page; }
Untuk mencegah jeda setelah kotak gunakan break-after: avoid-page
bersama dengan page-break-after: avoid
.
.box { page-break-after: avoid; break-after: avoid-page; }
Janda dan Yatim
Properti widows
dan orphans
menikmati dukungan lintas-browser yang baik — satu-satunya browser tanpa implementasi adalah Firefox. Saya akan menyarankan menggunakan ini saat membuat tata letak multicol atau mencetak stylesheet. Jika mereka tidak bekerja karena suatu alasan, Anda akan mendapatkan janda dan anak yatim, yang tidak ideal tetapi juga bukan bencana. Jika mereka berhasil, tipografi Anda akan terlihat lebih baik untuk itu.
kotak-dekorasi-break
Properti terakhir dari box-decoration-break
memiliki dukungan untuk multicol dan print di Firefox. Safari, Chrome, dan browser berbasis Chromium lainnya mendukung -webkit-box-decoration-break
, tetapi hanya pada elemen sebaris. Jadi Anda bisa mengkloning garis batas garis bulat kalimat misalnya; mereka tidak memiliki dukungan dalam konteks yang kita lihat.
Dalam CodePen di bawah ini, Anda dapat melihat bahwa pengujian untuk -webkit-box-decoration-break: clone
dengan Feature Query mengembalikan nilai true; namun, properti tidak berpengaruh pada batas kotak dalam konteks multikol.
Menggunakan Fragmentasi
Seperti yang Anda lihat, status fragmentasi saat ini di browser agak terfragmentasi! Yang mengatakan, ada jumlah yang masuk akal yang dapat Anda capai dan jika gagal, hasilnya cenderung kurang optimal tetapi bukan bencana. Artinya patut dicoba.
Perlu dicatat bahwa menjadi terlalu berat dengan sifat-sifat ini dapat menghasilkan sesuatu yang lain dari yang Anda harapkan. Jika Anda bekerja di web daripada mencetak dan memaksa jeda kolom setelah setiap paragraf, kemudian berakhir dengan lebih banyak paragraf daripada ruang untuk kolom, multikol akan berakhir meluap ke arah sebaris. Ini akan kehabisan kolom untuk menempatkan paragraf tambahan Anda. Oleh karena itu, bahkan di mana ada dukungan, Anda masih perlu menguji dengan hati-hati, dan ingat bahwa lebih sedikit lebih banyak dalam banyak kasus.
Lebih Banyak Sumber Daya
Untuk membaca lebih lanjut tentang properti, buka MDN, saya baru-baru ini memperbarui halaman di sana dan saya juga mencoba untuk memperbarui data kompatibilitas browser. Halaman utama untuk Fragmentasi CSS tertaut ke halaman properti individual yang memiliki contoh lebih lanjut, data kompatibilitas browser, dan informasi lain tentang penggunaan properti ini.