# Typography — The Voice of Glass > *"Typography is the craft of endowing human language with a durable visual form."* > — Robert Bringhurst, *The Elements of Typographic Style* --- ## 🎯 Filosofi Tipografi Tipografi BETE dibangun di atas tiga pilar: 1. **Hierarki melalui weight & size** — Bukan sekadar memperbesar heading, tapi memberi bobot makna 2. **Ritme vertikal yang konsisten** — Setiap elemen teks berada dalam grid ritme 4px 3. **Keterbacaan sebagai prioritas utama** — Sebelum estetika, sebelum gaya --- ## 📐 Type Scale: Fluid Modular Scale Kita menggunakan **modular scale** 1.25 (major third) yang **fluid** — menyesuaikan antara viewport. ```css /* Font size scale — fluid, minor third (1.125) hingga major third (1.25) */ --fs-xs: clamp(0.69rem, 0.69rem + 0.01vw, 0.75rem); /* 11–12px */ --fs-sm: clamp(0.81rem, 0.81rem + 0.02vw, 0.88rem); /* 13–14px */ --fs-base: clamp(0.94rem, 0.94rem + 0.03vw, 1.00rem); /* 15–16px ★ */ --fs-md: clamp(1.06rem, 1.06rem + 0.04vw, 1.13rem); /* 17–18px */ --fs-lg: clamp(1.19rem, 1.19rem + 0.06vw, 1.25rem); /* 19–20px */ --fs-xl: clamp(1.31rem, 1.31rem + 0.08vw, 1.50rem); /* 21–24px */ --fs-2xl: clamp(1.50rem, 1.50rem + 0.12vw, 1.88rem); /* 24–30px */ --fs-3xl: clamp(1.69rem, 1.69rem + 0.18vw, 2.25rem); /* 27–36px */ --fs-4xl: clamp(1.88rem, 1.88rem + 0.26vw, 2.81rem); /* 30–45px */ --fs-5xl: clamp(2.25rem, 2.25rem + 0.38vw, 3.50rem); /* 36–56px */ --fs-6xl: clamp(2.50rem, 2.50rem + 0.50vw, 4.00rem); /* 40–64px */ ``` > **Mengapa clamp()?** Font size yang terlalu besar di mobile dan terlalu kecil di desktop adalah masalah UX klasik. Dengan `clamp()`, kita dapatkan ukuran yang optimal di setiap viewport tanpa media query. ### Line Height ```css --lh-tight: 1.15; /* Heading besar, display text */ --lh-normal: 1.50; /* Body text, paragraphs */ --lh-relaxed: 1.65; /* Long-form reading */ --lh-compact: 1.25; /* UI labels, badges, small text */ ``` ### Font Weight Tokens ```css --fw-light: 300; --fw-regular: 400; --fw-medium: 500; --fw-semibold: 600; --fw-bold: 700; --fw-extrabold: 800; ``` --- ## 🔤 Font Family ### Primary: "Outfit" — Modern Geometric Sans ```css --ff-sans: 'Outfit', system-ui, -apple-system, sans-serif; --ff-display: 'Outfit', system-ui, -apple-system, sans-serif; ``` Mengapa **Outfit** menggantikan Poppins? - **Geometric precision** — Bentuk huruf yang bersih, cocok untuk UI modern - **Low x-height** — Memberi kesan elegan dan lega - **Variable font support** — Satu file untuk semua weight, performa lebih baik - **Open-source** — SIL Open Font License ### Monospace: "JetBrains Mono" ```css --ff-mono: 'JetBrains Mono', 'Fira Code', 'Cascadia Code', monospace; ``` Untuk: ID, timestamp, kode, data teknis, metrik. ### Loading Strategy ```html ``` ```css /* Fallback font stack dengan @font-face untuk cache lokal */ @font-face { font-family: 'Outfit Fallback'; src: local('Segoe UI'), local('Roboto'), local('Helvetica Neue'); size-adjust: 95%; /* Mengurangi layout shift (CLS) */ ascent-override: 90%; } ``` --- ## 📋 Type Styles — The Complete Catalog ### Display / Hero ```css .display-1 { font-family: var(--ff-display); font-size: var(--fs-6xl); font-weight: var(--fw-extrabold); line-height: var(--lh-tight); letter-spacing: -0.03em; } .display-2 { font-family: var(--ff-display); font-size: var(--fs-5xl); font-weight: var(--fw-bold); line-height: var(--lh-tight); letter-spacing: -0.02em; } ``` ### Headings ```css .h1 { font-family: var(--ff-sans); font-size: var(--fs-4xl); font-weight: var(--fw-bold); line-height: var(--lh-tight); letter-spacing: -0.02em; } .h2 { font-family: var(--ff-sans); font-size: var(--fs-3xl); font-weight: var(--fw-semibold); line-height: var(--lh-tight); letter-spacing: -0.015em; } .h3 { font-family: var(--ff-sans); font-size: var(--fs-2xl); font-weight: var(--fw-semibold); line-height: var(--lh-tight); letter-spacing: -0.01em; } .h4 { font-family: var(--ff-sans); font-size: var(--fs-xl); font-weight: var(--fw-medium); line-height: var(--lh-normal); letter-spacing: -0.005em; } ``` ### Body ```css .body-large { font-family: var(--ff-sans); font-size: var(--fs-md); font-weight: var(--fw-regular); line-height: var(--lh-relaxed); } .body { font-family: var(--ff-sans); font-size: var(--fs-base); font-weight: var(--fw-regular); line-height: var(--lh-normal); } .body-small { font-family: var(--ff-sans); font-size: var(--fs-sm); font-weight: var(--fw-regular); line-height: var(--lh-normal); } .body-compact { font-family: var(--ff-sans); font-size: var(--fs-sm); font-weight: var(--fw-medium); line-height: var(--lh-compact); } ``` ### UI / Label ```css .label { font-family: var(--ff-sans); font-size: var(--fs-xs); font-weight: var(--fw-semibold); line-height: var(--lh-compact); letter-spacing: 0.06em; /* UPPERCASE labels get wider tracking */ text-transform: uppercase; } .caption { font-family: var(--ff-sans); font-size: var(--fs-xs); font-weight: var(--fw-regular); line-height: var(--lh-normal); color: var(--clr-text-secondary); } .mono { font-family: var(--ff-mono); font-size: var(--fs-sm); font-weight: var(--fw-regular); line-height: var(--lh-normal); } .badge { font-family: var(--ff-sans); font-size: var(--fs-xs); font-weight: var(--fw-medium); line-height: 1; } ``` --- ## 📊 Type Table — Mapping ke Penggunaan | Token | Penggunaan | Contoh | |-------|-----------|--------| | `.display-1` | Halaman kosong, 404, hero section | "Nothing to see here" | | `.display-2` | Empty state utama | "No messages yet" | | `.h1` | Judul halaman | "Dashboard", "Messages" | | `.h2` | Judul section panel | "Voice Connections", "Analytics" | | `.h3` | Judul card | Nama user, channel | | `.h4` | Sub-section, tab content | "Active Speakers", "Filters" | | `.body` | Paragraf, konten utama | Pesan teks, deskripsi | | `.body-small` | Metadata, secondary info | Timestamp, username | | `.body-compact` | Dense lists | Daftar items compact | | `.label` | Form label, section header | "CHANNEL", "USERNAME" | | `.caption` | Hint, footnote, helper | "Click to expand" | | `.mono` | ID, kode, data teknis | "Channel #12345" | | `.badge` | Chip, status indicator | "AI Analysis", "Flagged" | --- ## 🎭 Rich Text & Emphatic Styles ```css /* Links */ a, .link { color: var(--clr-primary-400); text-decoration: none; transition: opacity var(--dur-fast) var(--ease-out); } a:hover, .link:hover { opacity: 0.8; text-decoration: underline; text-underline-offset: 2px; } /* Code inline */ code, .code-inline { font-family: var(--ff-mono); font-size: 0.9em; padding: 0.125em 0.375em; background: var(--clr-surface-sunken); border-radius: var(--rd-xs); } /* Truncation */ .text-truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } /* Multi-line truncation */ .text-clamp-2 { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; } .text-clamp-3 { display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; } ``` --- ## 📏 Vertical Rhythm Menggunakan sistem baseline 4px (bukan 8px default) untuk tipografi: ```css :root { --baseline: 4px; } /* Heading margin */ .h1 { margin-bottom: calc(var(--baseline) * 4); } /* 16px */ .h2 { margin-bottom: calc(var(--baseline) * 3); } /* 12px */ .h3 { margin-bottom: calc(var(--baseline) * 3); } /* 12px */ .h4 { margin-bottom: calc(var(--baseline) * 2); } /* 8px */ /* Paragraph spacing */ p, .body { margin-bottom: calc(var(--baseline) * 4); /* 16px */ } p + p { margin-top: calc(var(--baseline) * 2); /* 8px — reduced between consecutive paragraphs */ } ``` --- ## ⚠️ Anti-Patterns Tipografi ### ❌ Ukuran absolut tanpa fluid ```css /* ❌ JANGAN — title 32px di mobile terlalu besar */ .page-title { font-size: 32px; } /* ✅ clamp menyesuaikan viewport */ .page-title { font-size: var(--fs-4xl); } ``` ### ❌ Line height terlalu kecil untuk body text ```css /* ❌ JANGAN — crowded, sulit dibaca */ .body-text { font-size: 16px; line-height: 1.2; } /* ✅ Line height yang cukup untuk readability */ .body-text { font-size: var(--fs-base); line-height: var(--lh-normal); } ``` ### ❌ Terlalu banyak type scale ```css /* ❌ JANGAN — 29px, 28px, 27px, 26px adalah noise */ .custom-1 { font-size: 29px; } .custom-2 { font-size: 28px; } /* ✅ Gunakan scale yang terdefinisi */ .custom { font-size: var(--fs-4xl); } ``` --- ## 🔗 Referensi | Sumber | Konsep | |--------|--------| | [Type Scale Calculator](https://typescale.com/) | Modular scale generation | | [Outfit on Google Fonts](https://fonts.google.com/specimen/Outfit) | Font spesifikasi | | [Utopia.fyi](https://utopia.fyi/) | Fluid type scale calculator | | [JetBrains Mono](https://www.jetbrains.com/lp/mono/) | Font monospace | --- *"Huruf adalah jejak ingatan yang tak kasatmata — ia berbicara tanpa suara."* ❄️🩵