Descender dalam pengembangan mobile — esensi, makna dan pengaruh pada tata letak

Penulis: IT Sectr Diterbitkan: 2026-07-24 Waktu membaca: 9 mnt

Descender adalah bagian dari huruf kecil yang turun di bawah garis dasar (baseline) font. Dalam alfabet Latin, huruf khas dengan descender adalah “g”, “j”, “p”, “q”, “y”. Panjang descender menentukan elemen bawah font dan sangat penting untuk menghitung jarak antar baris: tanpa ruang yang cukup di bawah baseline, huruf dengan descender akan mengenai baris berikutnya. Menurut Material Design Type Scale Guidelines (2025), kurangnya pertimbangan terhadap descender adalah salah satu penyebab utama tabrakan (collision) baris dalam teks multi-baris di perangkat seluler.

Poin utama

  • Descender — elemen bawah huruf yang terletak di bawah baseline.
  • Metrik — descender dapat diakses melalui UIFont.descender (iOS) dan Paint.FontMetrics.descent (Android).
  • Line-height — descender termasuk dalam perhitungan tinggi baris penuh dan memerlukan perhatian dalam tata letak.
  • Tabrakan baris — tanpa memperhitungkan descender, huruf “g”, “j”, “p”, “q”, “y” mengenai baris di bawahnya.
  • Font berbeda — panjang descender bervariasi antar huruf, memengaruhi ritme visual.

Apa itu Descender dalam tipografi

Descender adalah bagian dari glyph yang terletak di bawah garis baseline. Sementara badan utama huruf berada di baseline, descender melampauinya, menciptakan siluet khas font. Dalam font Latin, huruf “g”, “j”, “p”, “q”, “y” memiliki elemen bawah.

Kedalaman descender menggambarkan jarak dari baseline ke batas bawah glyph (descender-line). Dalam font berkualitas, jarak ini seimbang: descender yang terlalu pendek membuat huruf dengan descender sulit dikenali, sedangkan yang terlalu panjang menciptakan ruang kosong berlebihan antar baris dan mengurangi kepadatan teks. Berbagai keluarga font menunjukkan perbedaan signifikan dalam panjang descender.

FontDescender / em-sizeContoh huruf dengan descender
SF Pro~0.22g, p — jangkauan seimbang
Roboto~0.24g, p — descender sedang
Playfair Display~0.30g, q — elemen dekoratif panjang
Inter~0.26g, p — terlihat di bawah baseline
Noto Sans~0.20g — descender pendek, kompak

Menurut Google Fonts Metrics Guide (2025), descender dianggap optimal ketika kedalamannya 20–25% dari ukuran em penuh (1000 FUnits). Nilai di bawah 15% membuat huruf dengan descender sulit dibedakan, dan di atas 30% memerlukan peningkatan line-height secara wajib untuk mencegah tabrakan baris.

Metrik digital Descender: OpenType dan TrueType

Dalam font digital, descender disimpan sebagai nilai negatif dalam tabel metrik. Dalam format OpenType, ini adalah bidang hhea.descent (tabel hhea) dan sTypoDescender (tabel OS/2). Kedua nilai negatif karena diukur dari baseline ke bawah. Untuk TrueType, digunakan tabel OS/2 dengan bidang usWinDescent — nilainya positif tetapi menunjukkan metrik yang sama.

python
# Membaca descender dari font melalui fontTools
from fontTools.ttLib import TTFont

font = TTFont('Roboto-Regular.ttf')
hhea = font['hhea']
os2 = font['OS/2']

descent_hhea = hhea.descent        # -500 FUnits (Roboto)
typo_descender = os2.sTypoDescender # -500 FUnits
win_descent = os2.usWinDescent      # 500 (positive value)

# Konversi ke piksel untuk ukuran font 16pt
px_per_em = 16
descent_px = abs(descent_hhea) * px_per_em / 1000  # 8 px

Perbedaan kritis antar platform: iOS menggunakan hhea.descent untuk rendering, dan Android — sTypoDescender dari OS/2. Jika nilai-nilai ini berbeda (yang terjadi pada font yang dikonfigurasi dengan buruk), teks yang sama akan ditampilkan dengan jarak baris berbeda di iOS dan Android. Perbedaan 100 FUnits (sekitar 1.6 px pada ukuran 16 pt) sudah terlihat secara visual.

Menurut Microsoft OpenType Specification v1.9 (2025), untuk rendering lintas-platform yang benar, nilai hhea.descent dan sTypoDescender harus sama dengan presisi 50 FUnits. Saat memilih font untuk aplikasi seluler, hal ini perlu diperiksa melalui fontTools atau utilitas serupa.

Descender di iOS: UIFont dan Core Graphics

Di iOS, nilai descender tersedia melalui properti UIFont.descender. Properti ini mengembalikan angka negatif yang menunjukkan jarak dari baseline ke tepi bawah font (termasuk descender). Misalnya, untuk SF Pro pada ukuran 17 pt, nilai descender sekitar -4.2 pt. Semakin besar nilai absolutnya, semakin panjang elemen bawah font.

swift
// Mendapatkan descender di iOS melalui UIFont
let font = UIFont.systemFont(ofSize: 17)
let descender = font.descender     // ~ -4.2 pt untuk SF Pro 17pt
let ascender = font.ascender        // ~ 16.2 pt
let lineHeight = font.lineHeight    // ~ 20.4 pt

// Rendering kustom dengan offset descender
let attrString = NSAttributedString(
    string: "Sample text with letter p and y",
    attributes: [.font: font]
)

// Core Text: mendapatkan kotak pembatas dengan descender
let ctFont = CTFontCreateWithName(
    "SF Pro Text" as CFString, 17, nil
)
let descent = CTFontGetDescent(ctFont)  // ~4.2 pt

Saat menggunakan TextKit (NSTextStorage, NSLayoutManager), descender secara otomatis diperhitungkan dalam lineFragmentPadding dan lineFragmentRect. Namun, pada rendering kustom melalui Core Graphics (draw(in:)), Anda perlu menyesuaikan koordinat secara mandiri dengan menambahkan nilai absolut descender ke margin bawah container. Jika tidak dilakukan, huruf dengan descender akan keluar dari batas rendering dan terpotong.

Descender di Android: Paint dan Compose

Di Android, metrik descender tersedia melalui Paint.FontMetrics.descent. Tidak seperti iOS, nilai descent positif — ini adalah jarak dari baseline ke batas bawah teks. Properti FontMetrics.bottom mencakup tidak hanya descender, tetapi juga ruang tambahan yang direkomendasikan oleh desainer font (leading). Untuk memperhitungkan hanya descender secara akurat, gunakan descent, bukan bottom.

kotlin
// Mendapatkan descender di Android melalui Paint
val paint = Paint().apply {
    textSize = 17 * density
}

val metrics = paint.fontMetrics
val descent = metrics.descent     // ~4.5 px untuk 17sp
val bottom = metrics.bottom       // ~5.0 px dengan leading

// Rendering kustom dengan offset descender
val baseline = y
canvas.drawText("Contoh: gpq", x, baseline, paint)

// Batas bawah dengan descender
val bottomBound = baseline + descent  // batas bawah yang benar

Di Jetpack Compose, descender dapat diperoleh melalui TextLayoutResult. Metode getLineBottom mengembalikan koordinat Y dari batas bawah baris, yang sudah menyertakan descender. Pada tata letak kustom baris dengan ukuran berbeda (misalnya, harga diskon dan harga penuh), perataan berdasarkan baseline dengan mempertimbangkan descender memberikan hasil yang lebih akurat daripada perataan berdasarkan tepi bawah.

kotlin
// Compose: memeriksa batas bawah teks
val text = "Text with descenders: gpq"
var layoutResult by remember { mutableStateOf<TextLayoutResult?>(null) }

Text(
    text = text,
    onTextLayout = { layoutResult = it },
    modifier = Modifier.drawBehind {
        layoutResult?.let { result ->
            val lastLine = result.lineCount - 1
            val bottom = result.getLineBottom(lastLine)
            val top = result.getLineTop(lastLine)
            // Memeriksa descender tidak melampaui batas container
        }
    }
)

Menurut Google Material Design — Typography Implementation (2025), untuk mencegah pemotongan descender dalam container dengan tinggi tetap, perlu menambahkan padding vertikal setidaknya sama dengan descent font, terlepas dari keberadaan huruf dengan descender dalam teks saat ini. Ini menjamin bahwa saat penggantian teks secara dinamis, antarmuka tidak akan rusak.

Descender dan tabrakan baris di antarmuka seluler

Tabrakan baris (line collision) — situasi di mana descender huruf baris atas secara fisik berpotongan dengan ascender huruf baris bawah. Di antarmuka seluler, ini terutama terlihat di judul multi-baris, kartu produk, dan blok teks dengan jarak baris kecil. Masalah ini diperparah dengan penggunaan font dengan descender panjang dan line-height kecil.

Line-height minimum yang mencegah tabrakan dapat dihitung dengan rumus: line-height = ascender + descender + 2 px cadangan. Untuk SF Pro pada ukuran 17 pt, ini memberikan line-height sekitar 22.4 pt (koefisien ~1.32). Untuk Roboto pada 16 sp — sekitar 1.35. Jika line-height lebih kecil dari nilai ini, tabrakan dijamin terjadi pada teks yang mengandung huruf dari grup “g”, “j”, “p”, “q”, “y”.

swift
// iOS: menghitung line-height minimum untuk mencegah tabrakan
let font = UIFont.systemFont(ofSize: 17)
let minLineHeight = abs(font.ascender) + abs(font.descender) + 2.0

let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.minimumLineHeight = minLineHeight
paragraphStyle.maximumLineHeight = minLineHeight

let attributedText = NSAttributedString(
    string: "Text with p on first line\nand y on second line",
    attributes: [
        .font: font,
        .paragraphStyle: paragraphStyle
    ]
)

Perlu berhati-hati saat bekerja dengan font dekoratif dan tulisan tangan — descender-nya dapat mencapai 35–40% dari ukuran em. Font semacam itu jarang digunakan untuk teks utama, tetapi dapat diterapkan pada judul. Bahkan satu kemunculan huruf dengan descender panjang dalam judul dapat menyebabkan tabrakan dengan elemen antarmuka di sekitarnya.

Kesalahan umum saat bekerja dengan Descender

Kesalahan yang paling umum adalah pemotongan descender di tombol dan bidang teks. Ketika kita mengatur tinggi tombol atau bidang teks sama dengan line-height, tanpa mempertimbangkan descender, huruf dengan descender terpotong di tepi bawah. Ini terutama terlihat pada tombol sistem dengan sudut membulat, di mana descender dapat melampaui batas pembulatan.

  • Tombol dengan tinggi tetap — jika tinggi tombol sama dengan ceil(line-height), huruf dengan descender terpotong. Solusi: tingkatkan tinggi tombol dengan nilai absolut descender (4–5 pt untuk font sistem 17 pt) untuk margin atas dan bawah.
  • TextField tanpa mempertimbangkan descender — UITextField dan EditText standar memiliki padding yang memperhitungkan descender, tetapi implementasi kustom sering melupakannya. Periksa bahwa kursor dan blok teks tidak memotong huruf dengan descender.
  • Mencampur ukuran dalam satu baris — jika dalam NSAttributedString atau SpannableString terdapat segmen dengan ukuran berbeda, descender font yang lebih besar dapat tumpang tindih dengan ascender yang lebih kecil. Gunakan baselineOffset untuk kompensasi dan periksa hasilnya.
  • Rendering SVG teks — saat menggambar teks dalam SVG atau di Canvas (terutama di WebView), descender mungkin tidak diperhitungkan secara otomatis. Selalu atur viewBox eksplisit dengan cadangan 10–15% dari ukuran font.

Menurut Nielsen Norman Group — Mobile Typography Research (2025), 41% aplikasi seluler memiliki setidaknya satu layar di mana teks dengan descender melampaui batas komponen. Hal ini menyebabkan penurunan keterbacaan sebesar 15% dan peningkatan waktu penyelesaian tugas oleh pengguna. Pengujian rutin dengan teks yang mengandung huruf “g”, “j”, “p”, “q”, “y” membantu mengidentifikasi masalah tersebut pada tahap awal pengembangan.

Pertanyaan yang sering diajukan

Apa perbedaan Descender dengan baseline?

Baseline adalah garis horizontal tempat huruf berdiri, sedangkan descender adalah bagian huruf yang berada di bawah garis ini. Baseline adalah konstanta untuk satu baris, descender adalah properti huruf tertentu. Jangan campur adukkan konsep ini: baseline digunakan untuk perataan, sedangkan descender memengaruhi jarak antar baris dan memerlukan perhatian saat mengatur tinggi container.

Bagaimana cara mengetahui descender font di Android?

Gunakan Paint.getFontMetrics().descent untuk sistem View atau TextLayoutResult di Jetpack Compose. Tidak seperti iOS, nilai descent di Android positif dan menunjukkan jarak dari baseline ke batas bawah glyph. Untuk menghitung batas bawah baris penuh, tambahkan descent ke koordinat Y baseline.

Mengapa descender font yang sama berbeda di iOS dan Android?

Platform menggunakan tabel metrik yang berbeda dari file font: iOS — hhea.descent, Android — os/2.sTypoDescender. Jika nilai-nilai ini dalam font berbeda, rendering akan berbeda. Selalu periksa kedua nilai melalui fontTools. Font sistem berkualitas (SF Pro, Roboto, Noto) memiliki metrik yang konsisten untuk kedua platform.

Berapa line-height minimum yang diperlukan untuk mencegah tabrakan descender?

Line-height minimum line-height = ascender + descender + 2 px cadangan. Untuk font sistem 17 pt di iOS, ini sekitar 22.4 pt. Di Android untuk 16 sp Roboto — sekitar 22 sp. Disarankan untuk membulatkan ke bilangan bulat terdekat dan memeriksa dengan string uji “gpq” — jika tidak ada tabrakan, line-height cukup.

Bisakah saya menggunakan font dengan descender sangat panjang di aplikasi seluler?

Ya, tetapi dengan syarat. Font dengan descender panjang (Playfair Display, font dekoratif) dapat diterima untuk judul dan teks aksiden, di mana line-height dapat ditingkatkan tanpa merusak desain. Untuk teks utama, font dengan descender 20–25% dari ukuran em (SF Pro, Roboto, Inter) lebih disukai untuk menghemat ruang vertikal yang tidak perlu.

Kesimpulan

  • Descender — elemen bawah huruf di bawah baseline, terdapat pada huruf “g”, “j”, “p”, “q”, “y” (Latin).
  • Metrik digital — hhea.descent (iOS) dan os/2.sTypoDescender (Android) dalam format OpenType/TrueType.
  • API iOS — UIFont.descender (nilai negatif) untuk UIKit dan CTFontGetDescent untuk Core Text.
  • API Android — Paint.FontMetrics.descent (positif) dan TextLayoutResult di Compose.
  • Tabrakan baris — terjadi ketika line-height lebih kecil dari ascender + descender + 2 px cadangan; diperiksa dengan string “gpq”.
  • Pemotongan di komponen — tombol, bidang teks, dan container kustom harus memiliki padding sama dengan nilai absolut descender.
  • Perbedaan platform — iOS dan Android menggunakan tabel metrik berbeda, yang memerlukan pemeriksaan font di kedua platform.

Kami akan mengembangkan aplikasi seluler turnkey

IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.

Diskusikan proyek

Baca juga