Descender în dezvoltarea mobile — esența, importanța și influența asupra layout-ului

Autor: IT Sectr Publicat: 2026-07-24 Timp de citire: 9 min

Descender este partea unei litere mici care se extinde sub linia de bază (baseline) a fontului. În alfabetul latin, literele tipice cu descender sunt „g", „j", „p", „q", „y". Lungimea descender-ului determină elementul inferior al fontului și este critică pentru calcularea spațierii liniilor: fără spațiu suficient sub baseline, literele cu descender vor atinge rândul următor. Conform Material Design Type Scale Guidelines (2025), ignorarea descender-ului este una dintre principalele cauze ale coliziunii liniilor în textul multi-rând pe dispozitivele mobile.

Principalele idei

  • Descender — elementul inferior al literei, situat sub baseline.
  • Metrică — descender este accesibil prin UIFont.descender (iOS) și Paint.FontMetrics.descent (Android).
  • Line-height — descender intră în calculul înălțimii totale a rândului și necesită atenție la layout.
  • Coliziuni de rânduri — fără a ține cont de descender, literele „g", „j", „p", „q", „y" ating rândul de dedesubt.
  • Fonturi diferite — lungimea descender-ului variază între caractere, influențând ritmul vizual.

Ce este Descender în tipografie

Descender este partea unui glif situată sub linia baseline. În timp ce corpul principal al literei stă pe baseline, descender se extinde dincolo de acesta, creând un siluet caracteristic al fontului. În fonturile latine, literele „g", „j", „p", „q", „y" au elemente inferioare.

Adâncimea descender-ului descrie distanța de la baseline până la marginea inferioară a glifului (descender-line). În fonturile de calitate, această distanță este echilibrată: un descender prea scurt face literele cu descender greu de recunoscut, iar unul prea lung creează spațiu gol excesiv între rânduri și reduce densitatea textului. Diferite familii de fonturi prezintă diferențe semnificative în lungimea descender-ului.

FontDescender / em-sizeExemple de litere cu descender
SF Pro~0.22g, p — extensie echilibrată
Roboto~0.24g, p — descender moderat
Playfair Display~0.30g, q — elemente decorative lungi
Inter~0.26g, p — vizibil sub baseline
Noto Sans~0.20g — descender scurt, compact

Conform Google Fonts Metrics Guide (2025), descender-ul este considerat optim atunci când adâncimea sa este de 20–25% din dimensiunea completă em (1000 FUnits). Valorile sub 15% fac literele cu descender greu de distins, iar peste 30% necesită creșterea obligatorie a line-height pentru a preveni coliziunile rândurilor.

Metricile digitale ale Descender-ului: OpenType și TrueType

În fonturile digitale, descender este stocat ca o valoare negativă în tabelele de metrice. În formatul OpenType, acesta este câmpul hhea.descent (tabela hhea) și sTypoDescender (tabela OS/2). Ambele valori sunt negative, deoarece sunt măsurate de la baseline în jos. Pentru TrueType se utilizează tabela OS/2 cu câmpul usWinDescent — valoarea sa este pozitivă, dar desemnează aceeași metrică.

python
# Citirea descender-ului din font prin 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)

# Convertirea în pixeli pentru dimensiunea fontului de 16pt
px_per_em = 16
descent_px = abs(descent_hhea) * px_per_em / 1000  # 8 px

Diferența critică între platforme: iOS utilizează hhea.descent pentru randare, iar Android — sTypoDescender din OS/2. Dacă aceste valori diferă (ceea ce se întâmplă în fonturile configurate necorespunzător), același text va fi afișat cu spațieri diferite între rânduri pe iOS și Android. O diferență de 100 FUnits (aproximativ 1.6 px la dimensiunea de 16 pt) este deja vizibilă.

Conform Microsoft OpenType Specification v1.9 (2025), pentru o randare cross-platform corectă, valorile hhea.descent și sTypoDescender ar trebui să fie egale cu o precizie de 50 FUnits. La alegerea unui font pentru o aplicație mobilă, acest lucru merită verificat prin fontTools sau o unealtă similară.

Descender în iOS: UIFont și Core Graphics

În iOS, valoarea descender-ului este disponibilă prin proprietatea UIFont.descender. Această proprietate returnează un număr negativ, indicând distanța de la baseline până la marginea inferioară a fontului (inclusiv descender). De exemplu, pentru SF Pro la dimensiunea de 17 pt, valoarea descender-ului este de aproximativ -4.2 pt. Cu cât modulul numărului este mai mare, cu atât elementele inferioare ale fontului sunt mai lungi.

swift
// Obținerea descender-ului pe iOS prin UIFont
let font = UIFont.systemFont(ofSize: 17)
let descender = font.descender     // ~ -4.2 pt pentru SF Pro 17pt
let ascender = font.ascender        // ~ 16.2 pt
let lineHeight = font.lineHeight    // ~ 20.4 pt

// Randare personalizată cu offset descender
let attrString = NSAttributedString(
    string: "Sample text with letter p and y",
    attributes: [.font: font]
)

// Core Text: obținerea căsuței de delimitare cu descender
let ctFont = CTFontCreateWithName(
    "SF Pro Text" as CFString, 17, nil
)
let descent = CTFontGetDescent(ctFont)  // ~4.2 pt

La utilizarea TextKit (NSTextStorage, NSLayoutManager), descender-ul este luat automat în considerare în lineFragmentPadding și lineFragmentRect. Totuși, la randarea personalizată prin Core Graphics (draw(in:)), este necesar să ajustați manual coordonatele, adăugând modulul descender-ului la marginea inferioară a containerului. Dacă acest lucru nu se face, literele cu descender vor ieși din limita de randare și vor fi tăiate.

Descender în Android: Paint și Compose

În Android, metricele descender-ului sunt disponibile prin Paint.FontMetrics.descent. Spre deosebire de iOS, valoarea descent este pozitivă — reprezintă distanța de la baseline până la marginea inferioară a textului. Proprietatea FontMetrics.bottom include nu doar descender, ci și spațiul suplimentar recomandat de designerul fontului (leading). Pentru a lua în considerare doar descender-ul, utilizați descent, nu bottom.

kotlin
// Obținerea descender-ului pe Android prin Paint
val paint = Paint().apply {
    textSize = 17 * density
}

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

// Randare personalizată cu offset descender
val baseline = y
canvas.drawText("Exemplu: gpq", x, baseline, paint)

// Marginea inferioară cu descender
val bottomBound = baseline + descent  // marginea inferioară corectă

În Jetpack Compose, descender-ul poate fi obținut prin TextLayoutResult. Metoda getLineBottom returnează coordonata Y a marginii inferioare a rândului, care include deja descender-ul. La layout-ul personalizat al rândurilor cu dimensiuni diferite (de exemplu, preț redus și preț întreg), alinierea pe baseline ținând cont de descender oferă un rezultat mai precis decât alinierea pe marginea inferioară.

kotlin
// Compose: verificarea marginii inferioare a textului
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)
            // Verificarea că descender-ul nu depășește limitele containerului
        }
    }
)

Conform Google Material Design — Typography Implementation (2025), pentru a preveni tăierea descender-ului în containerele cu înălțime fixă, este necesar să adăugați un padding vertical egal cel puțin cu descent-ul fontului, indiferent de prezența literelor cu descender în textul curent. Acest lucru garantează că, la înlocuirea dinamică a textului, interfața nu se va strica.

Descender și coliziunile rândurilor în interfețele mobile

Coliziunea rândurilor (line collision) este situația în care descender-ul literei de pe rândul superior se intersectează fizic cu ascender-ul literei de pe rândul inferior. În interfețele mobile, acest lucru este vizibil mai ales în titlurile multi-rând, cardurile de produse și blocurile de text cu spațiere redusă între rânduri. Problema se agravează la utilizarea fonturilor cu descender lungi și line-height mic.

Line-height-ul minim care previne coliziunile poate fi calculat după formula: line-height = ascender + descender + 2 px marjă. Pentru SF Pro la dimensiunea de 17 pt, aceasta oferă un line-height de aproximativ 22.4 pt (coeficient ~1.32). Pentru Roboto la 16 sp — aproximativ 1.35. Dacă line-height-ul este mai mic decât această valoare, coliziunile sunt garantate în textele care conțin litere din grupul „g", „j", „p", „q", „y".

swift
// iOS: calculul line-height-ului minim pentru a preveni coliziunile
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
    ]
)

O atenție deosebită trebuie acordată la lucrul cu fonturi decorative și scrise de mână — descender-ul lor poate atinge 35–40% din dimensiunea em. Astfel de fonturi sunt rareori utilizate pentru textul principal, dar pot fi folosite în titluri. Chiar și o singură apariție a unei litere cu descender lung într-un titlu poate provoca o coliziune cu elementul vecin al interfeței.

Greșeli tipice la lucrul cu Descender

Cea mai frecventă greșeală este tăierea descender-ului în butoane și câmpuri text. Când setăm înălțimea unui buton sau câmp text egală cu line-height, fără a ține cont de descender, literele cu descender sunt tăiate la marginea inferioară. Acest lucru este vizibil mai ales pe butoanele sistemului cu colțuri rotunjite, unde descender-ul poate ieși dincolo de limita rotunjirii.

  • Butoane cu înălțime fixă — dacă înălțimea butonului este egală cu ceil(line-height), literele cu descender sunt tăiate. Soluție: măriți înălțimea butonului cu modulul descender-ului (4–5 pt pentru fontul de sistem de 17 pt) pentru marginea superioară și inferioară.
  • TextField fără a ține cont de descender — UITextField și EditText standard au padding care ia în considerare descender-ul, dar implementările personalizate uită adesea de el. Verificați ca cursorul și blocul de text să nu taie literele cu descender.
  • Amestecarea dimensiunilor pe același rând — dacă în NSAttributedString sau SpannableString există segmente cu dimensiuni diferite, descender-ul fontului mai mare se poate suprapune peste ascender-ul celui mai mic. Utilizați baselineOffset pentru compensare și verificați rezultatul.
  • Randarea SVG a textului — la desenarea textului în SVG sau pe Canvas (mai ales în WebView), descender-ul poate să nu fie luat automat în considerare. Stabiliți întotdeauna un viewBox explicit cu o marjă de 10–15% din dimensiunea fontului.

Conform Nielsen Norman Group — Mobile Typography Research (2025), 41% dintre aplicațiile mobile au cel puțin un ecran în care textul cu descender iese din limitele componentei. Aceasta duce la o scădere a lizibilității cu 15% și la o creștere a timpului de executare a sarcinii de către utilizator. Testarea regulată cu text care conține literele „g", „j", „p", „q", „y" ajută la identificarea acestor probleme în fazele incipiente ale dezvoltării.

Întrebări frecvente

Cu ce se deosebește Descender-ul de baseline?

Baseline este linia orizontală pe care stau literele, iar descender-ul este partea literei aflată sub această linie. Baseline este o constantă pentru rând, descender-ul este o proprietate a unei litere specifice. Nu confundați aceste concepte: baseline este utilizat pentru aliniere, iar descender-ul influențează spațierea dintre rânduri și necesită atenție la setarea înălțimii containerului.

Cum aflu descender-ul unui font pe Android?

Utilizați Paint.getFontMetrics().descent pentru sistemul View sau TextLayoutResult în Jetpack Compose. Spre deosebire de iOS, valoarea descent pe Android este pozitivă și arată distanța de la baseline până la marginea inferioară a glifului. Pentru a calcula marginea inferioară completă a rândului, adăugați descent la coordonata Y a baseline-ului.

De ce descender-ul aceluiași font diferă pe iOS și Android?

Platformele utilizează tabele de metrice diferite din fișierul fontului: iOS — hhea.descent, Android — os/2.sTypoDescender. Dacă aceste valori în font diferă, randarea va fi diferită. Verificați întotdeauna ambele valori prin fontTools. Fonturile sistemice de calitate (SF Pro, Roboto, Noto) au metrice consistente pentru ambele platforme.

Care este line-height-ul minim pentru a preveni coliziunile descender-ului?

Line-height-ul minim este line-height = ascender + descender + 2 px marjă. Pentru fontul de sistem de 17 pt pe iOS, aceasta este de aproximativ 22.4 pt. Pe Android, pentru 16 sp Roboto — aproximativ 22 sp. Se recomandă rotunjirea la cel mai apropiat întreg și verificarea cu șirul de testare „gpq" — dacă nu există coliziuni, line-height-ul este suficient.

Pot folosi un font cu descender foarte lung într-o aplicație mobilă?

Da, dar cu condiții. Fonturile cu descender lung (Playfair Display, caractere decorative) sunt acceptabile pentru titluri și text accentual, unde line-height-ul poate fi mărit fără a afecta designul. Pentru textul principal, sunt preferate fonturile cu descender de 20–25% din dimensiunea em (SF Pro, Roboto, Inter) pentru a nu pierde spațiu vertical inutil.

Concluzii

  • Descender — elementul inferior al literei situat sub baseline, prezent la literele „g", „j", „p", „q", „y" (latină).
  • Metrici digitale — hhea.descent (iOS) și os/2.sTypoDescender (Android) în formatele OpenType/TrueType.
  • API iOS — UIFont.descender (valoare negativă) pentru UIKit și CTFontGetDescent pentru Core Text.
  • API Android — Paint.FontMetrics.descent (pozitiv) și TextLayoutResult în Compose.
  • Coliziuni de rânduri — apar când line-height este mai mic decât ascender + descender + 2 px marjă; se verifică cu șirul „gpq".
  • Tăierea în componente — butoanele, câmpurile text și containerele personalizate trebuie să aibă padding egal cu modulul descender-ului.
  • Diferența între platforme — iOS și Android utilizează tabele de metrice diferite, ceea ce necesită verificarea fontului pe ambele platforme.

Vom dezvolta o aplicație mobilă la cheie

IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.

Discutați proiectul

Citiți și