D
P
0
← Semua artikel Read in English

WordPress & PHP di Produksi

`body_class()` Menyuntikkan `search-results` ke `<body>`, dan Seluruh Halaman Pencarian Jadi Gepeng

· · 4 menit baca
`body_class()` Menyuntikkan `search-results` ke `<body>`, dan Seluruh Halaman Pencarian Jadi Gepeng

Kebanyakan bug yang saya tulis di sini bisa ditunjuk ke satu baris kode yang keliru. Yang ini tidak bisa. Semua barisnya benar, dan satu halaman penuh tetap berantakan, gara-gara nama class yang saya pilih kebetulan sudah dipakai WordPress lebih dulu. Beresnya belasan menit, tapi bentuk bugnya layak dicatat.

Gejala: satu halaman gepeng, sisanya baik-baik saja

Waktu itu saya sedang memindahkan sebuah situs statis milik klien ke theme WordPress buatan sendiri. Targetnya port yang setia, jadi markup dan CSS lama saya bawa hampir apa adanya, tinggal disambungkan ke loop dan sistem template WordPress.

Semua halaman tampil benar. Beranda normal, halaman layanan normal, arsip artikel normal. Sampai saya iseng mencoba kotak pencariannya.

Halaman hasil pencarian menyempit. Dan bukan cuma daftar hasilnya. Header, hero, footer, semuanya ikut terjepit ke satu kolom sempit di tengah layar, dengan ruang kosong lebar menganga di kiri dan kanan. Halaman lain tidak ada yang begitu, cuma halaman ini.

Lebarnya sendiri terasa familiar. Kira-kira 820px, dan angka itu memang saya yang tulis. Tapi saya menulisnya untuk daftar hasil pencarian, bukan untuk seluruh halaman.

Akar masalah: WordPress kebetulan memakai nama class yang sama

Di template pencarian saya ada blok seperti ini:

<div class="search-results">
  <?php while ( have_posts() ) : the_post(); ?>
    <?php get_template_part( 'template-parts/content', 'search' ); ?>
  <?php endwhile; ?>
</div>

CSS-nya sesederhana yang kamu bayangkan:

.search-results {
  max-width: 820px;
  margin: 0 auto;
}

Dan di header.php, persis seperti theme WordPress pada umumnya:

<body <?php body_class(); ?>>

Di situlah tabrakannya terjadi. body_class() bukan sekadar mencetak class yang kita oper ke fungsinya. Dia menghasilkan sekumpulan class kontekstual sesuai halaman yang sedang dirender, dan di halaman hasil pencarian salah satu class yang ditambahkan adalah search-results. Jadi tag body-nya keluar kurang lebih begini:

<body class="search search-results logged-in ...">

Artinya, khusus di halaman ini ada dua elemen yang cocok dengan selector .search-results: div daftar hasil punya saya, dan <body> itu sendiri. Dan max-width: 820px yang mendarat di <body> otomatis menjepit seluruh isi dokumen, termasuk bagian yang sama sekali tidak ada hubungannya dengan pencarian.

Itu juga menjelaskan kenapa halaman lain aman. Di luar halaman pencarian, WordPress tidak pernah menempelkan class itu ke body, jadi CSS saya cuma mengenai satu elemen yang memang saya tuju.

Yang bikin agak malu, devtools sebenarnya sudah menampilkan jawabannya sejak detik pertama. Saya cuma membaca deretan class di <body> sekilas dan menganggap semuanya tulisan saya sendiri.

Perbaikan: ganti nama class-nya, jangan tambal selectornya

Godaan pertama jelas mempersempit selector supaya tidak nyasar ke body:

main .search-results {
  max-width: 820px;
  margin: 0 auto;
}

Itu memang menghilangkan gejalanya, tapi ranjaunya masih di tempat. Namanya tetap tabrakan, dan cukup satu selector baru yang ditulis tanpa prefiks main untuk memunculkan masalah yang sama lagi, mungkin berbulan-bulan kemudian oleh orang lain.

Jadi saya ambil jalan yang lebih membosankan dan lebih aman: ganti nama div-nya.

<div class="search-list">
.search-list {
  max-width: 820px;
  margin: 0 auto;
}

Selesai. Nama search-list tidak pernah dihasilkan WordPress, jadi selectornya cuma bisa kena elemen yang saya buat sendiri.

Satu jalan lain yang sempat terpikir tapi cepat saya buang: menghapus class bawaannya lewat filter.

// Jangan begini.
add_filter( 'body_class', function ( $classes ) {
    return array_diff( $classes, [ 'search-results' ] );
} );

Class body bawaan itu bagian dari kontrak yang dipakai plugin dan CSS lain untuk menargetkan jenis halaman. Membuangnya berarti merusak barang orang lain demi menyelamatkan penamaan saya yang memang kurang hati-hati.

Cek nama sebelum menamai

Setelah kejadian ini saya menambah satu langkah kecil waktu bikin class layout di theme. Buka halaman yang bersangkutan, lihat isi atribut class di <body>, lalu cari nama-nama itu di CSS theme:

grep -rn "\.search-results" wp-content/themes/nama-theme/

Kalau ada hasil yang bukan aturan khusus body, berarti ada potensi tabrakan.

Nama-nama yang dihasilkan body_class() cenderung terdengar generik, dan justru itu bahayanya. search-results, search-no-results, error404, home, blog, archive, single, page-template. Semuanya nama yang sangat wajar kepikiran juga waktu kita menamai wrapper sendiri.

Yang saya bawa pulang