Sebuah tombol tidak punya jumlah baris bawaan. Yang dia punya cuma lebar yang tersisa untuknya dan panjang isi yang harus dia tampung, dan jumlah baris adalah hasil pertemuan keduanya. Di satu halaman produk toko Shopify, pertemuan itu mendarat di angka tiga: label tombol beli pecah jadi tiga baris di iPhone 12 Pro, pada lebar 390 piksel.
Kotak belinya buatan sendiri, bukan bawaan tema, karena temanya memang dibangun dari nol. Bentuk halamannya galeri produk di kiri dan kotak beli di kanan, berisi variant picker, tombol add to cart, dan opsi langganan.
Dari mana angka tiga itu keluar
Baris belinya satu, display: flex, isinya dua elemen: stepper kuantitas di kiri dengan lebar tetap, lalu tombol add to cart yang menyerap sisanya dengan flex: 1.
Lebar tetap stepper itu tercatat sekitar 116 piksel, dan angkanya bisa ditelusuri dari isinya sendiri. Dua tombol selebar 40 piksel mengapit satu input selebar 36 piksel, jadi 40 + 36 + 40 = 116, dan garis tepi 1,5 piksel di kiri dan kanannya itulah kenapa angkanya ditulis sekitar.
Dari situ hitungannya lurus. Viewport 390 piksel dikurangi stepper 116 piksel menyisakan 274 piksel untuk tombol. Angka itu pun belum final, karena masih ada jarak antar kedua elemen yang nilainya diambil dari token spasi tema, jadi ruang tombol yang sebenarnya sedikit lebih sempit dari 274, bukan lebih lebar.
Ke ruang segitu, yang dijejalkan bukan satu potong teks. Label tombolnya punya dua anak, tulisan add to cart di kiri dan harga produk di kanan, didorong saling menjauh dengan justify-content: space-between, dan tidak ada white-space: nowrap di mana pun di rantai itu.
Sisanya perilaku browser yang paling biasa, yaitu memecah teks yang tidak muat di spasi terdekat. Barisnya sendiri tidak pernah diberi flex-wrap, jadi yang melipat bukan barisnya melainkan teks di dalam tombol.
Karena titik patahnya lahir dari hitungan tadi, tiga bukan sifat tombol itu. Tambah beberapa karakter di harga, atau kurangi sedikit lebar yang tersedia, dan potongan berikutnya pindah ke baris baru. Layout yang jumlah barisnya ditentukan isi seperti ini tidak bisa dibereskan dengan mengejar angka tiga.
Percobaan pertama yang saya buang sendiri
Yang saya kerjakan duluan adalah memberi tombol itu lebih banyak ruang. Kalau satu baris tidak cukup untuk dua elemen, pecah barisnya di mobile: stepper di baris pertama, tombol add to cart selebar penuh di baris kedua.
Wrap-nya semestinya hilang, tapi bentuknya canggung. Stepper yang kecil berdiri sendirian di kiri dan menyisakan ruang kosong di sebelahnya, sementara tombol add to cart jadi gepeng di baris bawah. Versi itu saya tolak sendiri.
Alasannya bukan cuma soal rasa. Media query tadi tidak menyentuh sebab labelnya kepanjangan, dia cuma memindahkan akibatnya ke bentuk lain.
Harga yang sama, tiga kali dalam satu layar
Yang akhirnya membuka kasus ini bukan properti CSS baru, melainkan menghitung berapa kali harga produk itu muncul di layar yang sama.
Kemunculan pertama ada di baris harga di atas kotak beli, tempat harga memang seharusnya berada. Kedua ada di kartu pilihan pembelian, yang masing-masing mencetak harganya sendiri. Ketiga ada di dalam label tombol add to cart.
Kemunculan ketiga itu yang dicatat sebagai akar masalahnya, yaitu konten redundan yang memaksa layout jadi rapuh. Ruang sesempit tadi bukan sedang dipakai untuk informasi yang perlu, melainkan untuk angka yang sudah dibaca pengunjung dua kali di layar yang sama.
Perbaikan yang dikirim
Langkah pertamanya menghapus, bukan menulis. Span harga di dalam tombol dibuang dari templatenya sepenuhnya, dan layout satu barisnya dipertahankan apa adanya.
Sisanya CSS yang tinggal merapikan konsekuensinya:
.buy-row__cta {
flex: 1;
min-width: 0;
justify-content: center;
letter-spacing: 0.06em;
white-space: nowrap;
}
.buy-row__cta [data-label] {
white-space: nowrap;
}
.buy-row__stepper {
flex-shrink: 0;
}justify-content berganti dari space-between jadi center, karena mendorong dua elemen saling menjauh cuma masuk akal kalau elemennya memang dua. Dengan satu label, center yang benar. white-space: nowrap sendiri dipasang dua kali, di tombolnya dan sekali lagi di anak label di dalamnya.
Dua deklarasi sisanya menjaga pembagian ruang di baris itu tetap jelas. min-width: 0 di tombol melepas nilai auto bawaan flex item, yang menolak menciut lebih kecil dari isinya dan malah mendorong barisnya melebar. Sementara flex-shrink: 0 di stepper menyatakan bahwa lebar tetapnya memang tetap, jadi kalau ruangnya sempit yang menyesuaikan adalah tombol, dan stepper tidak ikut terseret jadi gepeng.
Aturan CSS untuk span harga tadi ikut dihapus karena elemennya sudah tidak ada. Sekarang mencari nama kelas itu di seluruh tema tidak menemukan apa pun, dan markup tombolnya benar-benar cuma menyisakan satu span label.
Perbaikannya didorong langsung ke theme yang live lewat Shopify CLI. Kedengarannya sembrono, tapi storefront-nya masih terkunci password waktu itu, dan theme live itu juga yang sedang saya preview. Saya periksa sendiri setelah masuk dan hasilnya beres. Balasan dari klien belum datang sampai sesi itu ditutup.
Menghapus duplikat lebih murah daripada menata ulang
Pelajaran yang saya bawa dari kasus ini bukan soal flexbox. Kalau sebuah informasi sudah muncul di konteks yang membungkusnya, jangan diulang lagi di label tombol. Pengulangan itu yang bikin layoutnya rapuh, dan menghapus duplikatnya lebih aman daripada menumpuk ulang layout mobile.
Urutan pemeriksaannya ikut berubah. Sebelum menambah breakpoint supaya sesuatu muat, hitung dulu berapa kali sesuatu itu sudah muncul di layar yang sama. Kalau jawabannya lebih dari sekali, yang perlu diperbaiki mungkin bukan lebarnya.