Agar baris baru sumber tunggal dibaca sebagai spasi sementara baris kosong memulai paragraf, buat struktur paragraf sebelum menerapkan pembungkus teks normal. Di Mac, Anda dapat mengujinya di halaman browser lokal; CSS saja tidak membuat pembedaan itu.
Panduan ini untuk orang yang menyiapkan prosa bahasa Inggris untuk halaman web sederhana atau pratinjau Markdown. Tugannya adalah mempertahankan baris sumber yang mudah dibaca sambil menghasilkan paragraf yang mengalir dan terbungkus ulang saat lebar jendela browser berubah.
Mengapa pengaturan whitespace CSS tidak memenuhi kedua persyaratan
Perhatikan teks sumber sintetis ini. Setiap paragraf menempati dua baris sumber, dan baris kosong memisahkan paragraf:
Panel A memperkenalkan tata letak
dan mendeskripsikan bagian pertama.
Panel B memperkenalkan bagian lain
dan mendeskripsikan ruang yang tersisa.
Hasil yang diinginkan adalah dua paragraf. Di dalam setiap paragraf, baris baru sumber menjadi spasi. Browser kemudian memilih pemutusan baris terlihat sesuai lebar yang tersedia.
Dengan white-space: normal, baris baru sumber runtuh bersama whitespace lain yang dapat diruntuhkan. Termasuk baris baru beruntun: baris sumber kosong tidak membuat paragraf. Dengan white-space: pre-line, karakter baris baru tetap sebagai pemutus baris, termasuk baris baru tunggal yang Anda inginkan untuk digabungkan. MDN mendokumentasikan perilaku ini di referensi properti white-space.
| Pengaturan yang diterapkan pada satu blok teks | Baris baru sumber tunggal | Baris sumber kosong | Cocok untuk tugas ini? |
|---|---|---|---|
white-space: normal |
Runtuh dengan whitespace | Juga runtuh | Hanya setelah paragraf dibuat |
white-space: pre-line |
Menjaga pemutusan baris | Menjaga pemutusan | Tidak |
white-space: pre-wrap |
Menjaga pemutusan baris | Menjaga pemutusan | Tidak |
Elemen paragraf terpisah dengan white-space: normal |
Mengalir di dalam setiap paragraf | Diwakili oleh batas paragraf | Ya |
W3C mendeskripsikan pemrosesan whitespace sebagai operasi rendering yang meninggalkan data dokumen yang mendasarinya tidak berubah. Aturan pemutus segmen-nya juga bergantung pada teks sekitar; menggantikan baris baru dengan spasi sesuai untuk prosa bahasa Inggris yang digunakan di sini, bukan transformasi universal untuk semua teks. Lihat CSS Text Module Level 3.
Solusi praktis oleh karena itu memiliki dua tahap: mengenali paragraf di sumber, lalu biarkan browser menata teks mereka. Standar HTML WHATWG mendefinisikan elemen p sebagai mewakili paragraf. Pemisahan terlihatnya dapat dikendalikan independen melalui styling. Lihat elemen p.
Pilih jalur yang cocok dengan sumber Anda
Gunakan bantuan keputusan berikut sebelum mengubah apa pun. Ia memisahkan interpretasi sumber dari tampilan, yang membantu menghindari memperbaiki lapisan yang salah.
| Apa yang Anda miliki | Apa yang harus dilakukan |
|---|---|
| Teks biasa yang hanya berisi prosa | Pecah pada baris kosong, gabungkan baris baru tunggal di dalam setiap paragraf, dan buat elemen paragraf |
| Markdown dengan heading, daftar, atau blok kode | Gunakan parser Markdown dan periksa perilaku soft-break-nya |
| HTML yang sudah ada dengan elemen paragraf terpisah | Periksa whitespace dan gaya spasi paragraf tersebut |
| Halaman yang berisi elemen pemutus baris eksplisit | Koreksi sumber atau konfigurasi rendering jika pemutusan itu tidak disengaja |
| Halaman yang hanya bisa dilihat | Gunakan alur kerja sumber atau ekspor yang tersedia; contoh di sini memerlukan kontrol dokumen |
Jangan mengganti setiap baris baru dengan spasi sebelum mengidentifikasi paragraf: itu menghapus pemisah yang dibedakan untuk membedakan mereka. Demikian pula, jangan menggantikan elemen br berulang untuk struktur paragraf. WHATWG mendefinisikan br sebagai pemutus baris dan mengatakan ia tidak boleh digunakan untuk memisahkan kelompok tematik di dalam paragraf. Lihat elemen br.
Buat contoh lokal yang berfungsi dengan TextEdit
Halaman lengkap berikut memerlukan TextEdit dan browser dengan JavaScript diaktifkan. Ia berisi kolom sumber yang dapat diedit dan pratinjau terpisah. Ia tidak menggunakan pustaka eksternal.
- Buka TextEdit dan pilih
File > Baru, laluFormat > Buat Teks Biasa. - Tempelkan contoh lengkap di bawah.
- Pilih
File > Simpandan beri nama fileparagraph-demo.html. - Jika diminta tentang ekstensi, pilih
Gunakan .html. - Buka file yang disimpan di Safari atau browser desktop lain.
Apple mendokumentasikan langkah pembuatan teks biasa dan ekstensi di Bekerja dengan dokumen HTML di TextEdit di Mac. Saat membuka kembali file untuk diedit, gunakan pengaturan TextEdit Tampilkan file HTML sebagai kode HTML bukan teks terformat di bawah TextEdit > Pengaturan > Buka dan Simpan.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Paragraph flow demo</title>
<style>
body {
max-width: 46rem;
margin: 2rem auto;
padding: 0 1rem;
font: 1rem/1.6 system-ui, sans-serif;
}
label { display: block; }
textarea {
box-sizing: border-box;
width: 100%;
min-height: 12rem;
font: 1rem/1.5 monospace;
}
#preview p {
white-space: normal;
margin: 0;
}
#preview p + p { margin-top: 1em; }
</style>
</head>
<body>
<h1>Paragraph flow demo</h1>
<label for="source">Source text</label>
<textarea id="source">Panel A introduces the layout
and describes the first section.
Panel B introduces another section
and describes the remaining space.</textarea>
<h2>Preview</h2>
<div id="preview"></div>
<script>
function toParagraphs(source) {
return source.replace(/\r\n?/g, '\n')
.split(/\n[ \t]*\n(?:[ \t]*\n)*/)
.map(block => block
.replace(/^[ \t\n]+|[ \t\n]+$/g, '')
.replace(/[ \t]*\n[ \t]*/g, ' '))
.filter(text => text.length > 0);
}
const source = document.getElementById('source');
const preview = document.getElementById('preview');
function render() {
const paragraphs = toParagraphs(source.value).map(text => {
const paragraph = document.createElement('p');
paragraph.textContent = text;
return paragraph;
});
preview.replaceChildren(...paragraphs);
}
source.addEventListener('input', render);
render();
</script>
</body>
</html>
Konverter pertama menormalkan akhir baris carriage-return dan CRLF ke LF. Kemudian ia memecah teks di mana saja baris kosong atau hanya berisi spasi dan tab biasa. Di dalam setiap blok yang dihasilkan, ia menggantikan baris baru yang tersisa, ditambah spasi atau tab berdekatan, dengan satu spasi biasa.
Ini adalah aturan eksplisit untuk contoh ini, bukan parser dokumen umum. Beberapa baris kosong menghasilkan satu batas paragraf. Whitespace biasa di awal dan akhir dihapus. Input kosong tidak menghasilkan paragraf. Sumber asli tetap terlihat di kolom input, sehingga transformasi dapat dibandingkan dengannya.
Setiap paragraf output menerima teksnya melalui textContent. MDN mendokumentasikan bahwa menetapkan properti ini menggantikan anak-anak node dengan node teks. Di sini ia hanya ditetapkan ke paragraf yang baru dibuat, kosong. Lihat Properti textContent Node.
Fungsi konversi lolos enam pemeriksaan deterministik di Node.js: input paragraf biasa, input CRLF, input carriage-return, input hanya-kosong, baris kosong berulang, dan pelestarian spasi tidak-pemutus. Rendering browser tidak dieksekusi selama persiapan; gunakan pemeriksaan visual di bawah untuk memverifikasinya di Mac Anda.
Periksa batas paragraf dan pembungkusan secara terpisah
Mulai dengan contoh yang disediakan. Pratinjau harus berisi Panel A memperkenalkan tata letak dan mendeskripsikan bagian pertama. sebagai satu paragraf, diikuti paragraf Panel B yang sesuai. Pada lebar jendela sempit, salah satu paragraf mungkin menempati beberapa baris terlihat.
Sekarang buat pengeditan terkontrol ini:
- Ganti baris baru tunggal setelah
layoutdengan spasi. Struktur paragraf pratinjau harus tetap sama. - Kembalikan baris baru itu dan hapus baris kosong antara dua blok. Pratinjau harus menjadi satu paragraf.
- Tambahkan baris kosong yang hanya berisi spasi atau tab di antara blok. Pratinjau harus kembali menjadi dua paragraf.
- Tambahkan beberapa baris kosong di sana. Jaraknya harus tetap satu celah paragraf.
- Ubah ukuran jendela browser. Batas paragraf harus tetap tetap sementara baris di dalam setiap paragraf terbungkus ulang.
Urutan ini membedakan batas sumber dari pembungkusan browser. Dalam contoh, spasi paragraf berasal dari aturan margin paragraf berdekatan. Mengubah margin itu mengubah celah terlihat tanpa mengubah cara sumber diurai.
Jika Anda menggunakan white-space: normal tanpa konverter ini, gabungan visual tidak berarti baris baru sumber dihapus. MDN menjelaskan bahwa whitespace konten-teks biasa tetap ada di DOM bahkan ketika CSS meruntuhkannya selama rendering. Lihat Menangani whitespace.
Gunakan parsing Markdown untuk dokumen Markdown
Markdown sudah menyediakan konvensi paragraf yang diperlukan di sini. CommonMark mendefinisikan paragraf sebagai baris non-kosong berurutan yang bukan tipe blok lain; baris kosong memisahkan paragraf. Baris baru biasa di dalam paragraf adalah soft break, yang renderer mungkin keluarkan sebagai baris baru atau spasi. Lihat paragraf CommonMark dan soft line breaks.
Tempelkan contoh sintetis ke tampilan sumber editor Markdown Anda dan periksa pratinjaunya. Jika setiap baris baru tunggal menghasilkan pemutusan terlihat, periksa opsi rendering yang terdokumentasi editor. Jangan asumsikan setiap aplikasi Markdown mengekspos pengaturan yang sama.
Untuk proyek yang menggunakan pustaka bernama markdown-it, opsi breaks yang terdokumentasinya default ke false. Mengatur ke true mengubah baris baru paragraf menjadi elemen br. Menjaga false mendukung hasil paragraf yang mengalir, asalkan CSS output juga meruntuhkan whitespace. Lihat MarkdownItOptions.
Hard break Markdown eksplisit tetap memerlukan perhatian. Di bawah CommonMark, dua atau lebih spasi di akhir atau backslash di akhir dapat membuat hard line break. Hapus penanda itu hanya di tempat mereka tidak disengaja. Aturannya terdokumentasi di bawah hard line breaks.
Jangan jalankan konverter teks biasa ke seluruh dokumen Markdown. Ia tidak mengenali heading, daftar, kode berpagar, atau aturan indentasi. Biarkan parser Markdown mempertahankan struktur itu; terapkan styling whitespace ke paragraf prosa yang dihasilkan.
Pertahankan batas browser dan pembentukan teks
Jaga setiap paragraf prosa sebagai teks berkelanjutan di mana praktis. Contoh membuat satu node teks per paragraf dan menyerahkan pembungkusan baris dan tata letak glyph ke browser. Ia tidak mengukur kata atau menyisipkan elemen terpisah di sekitar setiap karakter.
Batas itu penting untuk tipografi. W3C menentukan keadaan di mana pembentukan harus berlanjut melewati batas elemen-inline dan keadaan di mana harus terputus, termasuk perubahan spasi dan perataan tertentu. Hindari menambahkan kotak-inline tidak perlu hanya untuk mengontrol posisi baris. Lihat Pembentukan Melewati Batas Elemen.
Gunakan konverter hanya ketika setiap baris baru sumber terisolasi adalah pembungkus editorial. Jika baris baru sengaja membagi label, atau berada di dalam kata, menggabungkannya dengan spasi mengubah konten. Contoh ini juga memperlakukan baris yang berisi spasi tidak-pemutus sebagai konten, bukan pemisah kosong; MDN membedakan spasi tidak-pemutus dari whitespace dokumen biasa yang dapat diruntuhkan di Menangani whitespace.
Untuk prosa bahasa Inggris, tetapkan batas paragraf terlebih dahulu dan izinkan pembungkusan browser normal di dalamnya. Contoh lokal membuat aturan itu dapat diperiksa: sumber mempertahankan baris yang dapat diedit, pratinjau berisi paragraf nyata, dan mengubah ukuran hanya mengubah pembungkusan baris terlihat.
Sumber
- CSS Text Module Level 3 — W3C.
- HTML Standard: Elemen p — WHATWG.
- HTML Standard, Edisi untuk Pengembang Web: Elemen br — WHATWG.
- Properti CSS white-space — MDN Web Docs.
- Menangani whitespace — MDN Web Docs.
- Properti textContent Node — MDN Web Docs.
- Bekerja dengan dokumen HTML di TextEdit di Mac — Apple Support.
- Spesifikasi CommonMark, Versi 0.31.2 — CommonMark.
- MarkdownItOptions — markdown-it.