← Back to Course

Module -02

Unicode & Global Typography

Every character you see on screen has a number. Understanding Unicode explains why fonts break, why some text shows boxes, and how to design for 7+ billion people who don't all use the Latin alphabet.

From ASCII (128 characters) to Unicode (150,000+ characters). Font editors, character maps, and encoding converters evolved to handle the world's writing systems.

Variable fonts with extended language support, Noto font family covering all scripts, emoji as a design language, internationalization-first design approaches.

Every character is a number. Fonts are just drawings mapped to numbers. If the font doesn't have a drawing for a number, you get tofu (□). This never changes.

Part A

Core Concepts

01

What is Unicode?

Unicode is a universal numbering system for every character in every language. Before Unicode, different computers used different numbers for the same letters — chaos.

THE SAME NUMBER, DIFFERENT MEANINGS:
200
US Computer
È
Russian Computer
И
Greek Computer
Θ
Result: Send a file from Russia to USA → garbled text
"Привет" becomes "Ïðèâåò" or worse
Before Unicode: Encoding Chaos

In the 1980s, each country/company created their own character encoding. The number 200 meant different characters on different systems. Sharing files across countries was a nightmare of corrupted text.

UNICODE: EVERY CHARACTER HAS ONE UNIQUE NUMBER
AU+0041Latin Capital Letter A
中U+4E2DCJK Unified Ideograph ("middle")
אU+05D0Hebrew Letter Alef
∞U+221EInfinity Symbol
Unicode: One Number Per Character

Unicode assigns a unique number (called a "code point") to every character. U+0041 is ALWAYS the letter A, on every computer, in every country, forever. Problem solved.

UTF-8: VARIABLE-LENGTH ENCODING
A
41
1 byte (ASCII compatible)
é
C3
A9
2 bytes (European accents)
中
E4
B8
AD
3 bytes (CJK characters)
☺
F0
9F
98
8A
4 bytes (emoji, rare scripts)
UTF-8: How Unicode is Stored

UTF-8 is how Unicode numbers are stored in files. Simple ASCII letters use 1 byte (efficient for English). Complex characters use more bytes. This is why <meta charset="UTF-8"> is in every HTML file.

154,998
Characters defined (Unicode 15.1)
161
Scripts (writing systems)
3,790
Emoji characters
1,114,112
Maximum possible code points
Covers: Latin, Greek, Cyrillic, Arabic, Hebrew, CJK, Devanagari, Thai, Ethiopian, Cherokee, Braille, Musical notation, Mathematical symbols, and more...
How Big is Unicode?

Unicode includes virtually every writing system humans have ever used — from ancient Egyptian hieroglyphs to modern emoji. No font contains all 155,000 characters. That's why font selection matters.

02

The Tofu Problem

When a font doesn't have a drawing for a Unicode character, you see a box (□), a question mark (?), or nothing. Designers call this "tofu" because the boxes look like blocks of tofu.

WHAT THE DATA SAYS:
Hello 你好 مرحبا
WHAT YOU SEE (if font only supports Latin):
Hello □□ □□□□□
□
Empty box
�
Replacement char
?
Question mark
Missing Glyphs = Tofu

A font is just a collection of drawings ("glyphs") mapped to Unicode numbers. If the font doesn't include a drawing for a character, the system shows a placeholder. This is "tofu."

CHARACTERS IN POPULAR FONTS:
Arial~3,000 glyphs
Source Sans Pro~2,000 glyphs
Noto Sans~77,000 glyphs
Full Unicode Coverage154,998 glyphs
Most fonts cover less than 2% of Unicode
Font Coverage Varies Wildly

Font designers choose which characters to include. A typical "web font" has 200-500 glyphs (Latin + accents). Comprehensive fonts like Noto have 77,000+. No single font file covers everything.

CSS FONT STACK:
font-family:
"Inter", /* Your pretty font */
"Noto Sans", /* Fallback with more scripts */
"Segoe UI", /* Windows system font */
"Roboto", /* Android system font */
sans-serif; /* Ultimate fallback */
How it works:
Browser tries Inter first. If character missing, tries Noto Sans. Then Segoe UI. Then Roboto. Finally generic sans-serif.
The Solution: Font Stacks

Font stacks provide fallbacks. When your primary font lacks a glyph, the browser automatically tries the next font. This is why font-family lists multiple fonts — it's not just preference, it's protection.

Noto
"No Tofu" — Google's mission to eliminate □
A
Latin
Ж
Cyrillic
あ
Japanese
한
Korean
中
Chinese
ع
Arabic
א
Hebrew
θ
Greek
Noto family covers 150+ scripts. Use as fallback: font-family: "YourFont", "Noto Sans", sans-serif;
Google's "No Tofu" Font Family

Google created Noto to cover all of Unicode. It's split into sub-families (Noto Sans, Noto Sans JP, Noto Sans Arabic, etc.) so you only load what you need. Include Noto in your font stack as a safety net.

03

Writing Systems of the World

The Latin alphabet (A-Z) is used by ~40% of the world. The other 60% use scripts that look, behave, and require completely different typography rules.

Aa Éé
LATIN (LTR)
English, Spanish, French, German, Vietnamese...
中文 漢字
CJK (LTR/TTB)
Chinese, Japanese Kanji, Korean Hanja — 80,000+ chars
مرحبا עברית
RTL (Right-to-Left)
Arabic, Hebrew, Persian, Urdu — text flows right to left
हिन्दी தமிழ்
INDIC (LTR)
Hindi, Tamil, Bengali, Thai — complex ligatures
あいう アイウ
JAPANESE SYLLABARIES
Hiragana, Katakana — phonetic scripts mixed with Kanji
Major Script Categories

Each script family has unique characteristics. Latin is simple (26 letters). CJK has thousands of characters. Arabic letters change shape based on position. Thai has no spaces between words. Design must adapt.

LTR (English)
→
Logo left, nav right, text flows →
RTL (Arabic)
←
Logo right, nav left, text flows ←
Right-to-Left Languages

RTL isn't just text direction — the entire layout mirrors. Logos move right. Navigation flips. Scroll direction may change. CSS has direction: rtl and logical properties (margin-inline-start instead of margin-left).

NO WORD SPACING
中文没有单词之间的空格所以断行很复杂
Chinese has no spaces between words — line breaks can happen almost anywhere
MONOSPACE GRID
漢字は同じ幅
CJK characters are typically set on a square grid — each char same width
VERTICAL TEXT (OPTIONAL)
縦書きも可能
Traditional CJK can be written top-to-bottom, right-to-left
Chinese/Japanese/Korean Typography

CJK typography differs from Latin: no word spacing, monospace character grids, optional vertical writing mode. Font files are huge (10,000+ glyphs minimum). Always subset or use system fonts for CJK.

CONJUNCTS / LIGATURES
क + ् + त = क्त
Characters combine into complex ligatures — font must support these
VOWEL MARKS (MATRAS)
क + ा = का    क + ि = कि
Vowels attach above, below, before, or after consonants
LINE HEIGHT NEEDS
Indic scripts need more line-height (1.8-2.0) to accommodate marks above/below
Complex Shaping Scripts

Indic scripts (Hindi, Tamil, Thai, Khmer) have complex shaping rules. Characters change form, combine, and stack. Simple fonts won't render them correctly. Use fonts specifically designed for these scripts.

04

Practical Implementation

How to actually implement multilingual typography in your projects — the HTML, CSS, and font choices that make it work.

<!DOCTYPE html>
<html lang="ar" dir="rtl">
<head>
  <meta charset="UTF-8">
  <!-- lang: helps browsers, screen readers, search engines -->
  <!-- dir: sets text direction (rtl/ltr) -->
  <!-- charset: UTF-8 supports all Unicode -->
</head>
Essential HTML for i18n

Three critical attributes: charset="UTF-8" for character encoding, lang for language (helps screen readers, search engines, and hyphenation), dir for text direction (rtl or ltr).

body {
  font-family:
    /* Primary: Your brand font */
    "Inter",
    /* System UI fonts (fast, good coverage) */
    system-ui,
    -apple-system,
    "Segoe UI",
    /* Noto for missing scripts */
    "Noto Sans",
    /* CJK fallback */
    "Noto Sans CJK SC",
    /* Arabic fallback */
    "Noto Sans Arabic",
    /* Generic fallback */
    sans-serif;
}
Building a Global Font Stack

A robust font stack has layers: your brand font, system fonts for performance, Noto for Unicode coverage, and script-specific fallbacks for languages you expect. Order matters — browsers try each font in sequence.

OLD (Physical)
margin-left: 20px;
padding-right: 10px;
text-align: left;
border-left: 1px solid;
Breaks in RTL layouts
NEW (Logical)
margin-inline-start: 20px;
padding-inline-end: 10px;
text-align: start;
border-inline-start: 1px solid;
Auto-flips for RTL
CSS Logical Properties

Logical properties (inline-start/end, block-start/end) adapt to text direction automatically. margin-inline-start is left in LTR, right in RTL. Use these instead of physical properties for i18n-ready CSS.

PASTE THIS TEST STRING INTO YOUR UI:
Hello 你好 مرحبا שלום สวัสดี Привет → € £ ¥ ₹
✓If you see all characters clearly, fonts are working
□If you see boxes, add Noto fonts to your stack
?If you see question marks, check charset="UTF-8"
Testing Multilingual Support

Always test with real multilingual content. This test string includes Latin, Chinese, Arabic (RTL), Hebrew (RTL), Thai, Russian, an arrow, and currency symbols. If any show as boxes or question marks, your font stack needs work.

Key Takeaways

Every character has a unique number
A
U+0041
中
U+4E2D
α
U+03B1

Unicode assigns a unique code point to every character in every language. U+0041 is always 'A', everywhere. UTF-8 is how these numbers are stored in files.

Missing glyphs show as boxes
Hello □□

When a font doesn't have a glyph for a character, you see tofu (□). Fix with font stacks: list multiple fonts so browsers can fall back when characters are missing.

Different scripts, different rules
Latin
LTR →
Arabic
← RTL
CJK
No spaces
Indic
Ligatures

Latin is one of 161 scripts in Unicode. Arabic reads right-to-left. CJK has no word spacing. Indic scripts have complex ligatures. One typography rule doesn't fit all.

Three essentials for global text
charset="UTF-8"
lang="en"
dir="ltr"

Every HTML document needs: charset (UTF-8 for Unicode), lang (for accessibility/SEO), and dir (for text direction). Use CSS logical properties (inline-start) instead of physical (left).