Use Quran fonts in your app
Three recipes cover most apps: (1) Unicode text fonts — drop in @font-face and render ayat directly. (2) Page-glyph fonts — one font per page, paired with a PUA codepoint map. (3) Tajweed images — no font at all, just PNGs.
Recipe 1 · Unicode text font
Unicode text fonts render any ayah directly — no paired data required.
/* 1. Load the font */
@font-face {
font-family: 'UthmanicHafs';
src: url('https://fonts.quran.ws/assets/fonts/uthmanic-hafs-v22.woff2') format('woff2');
font-display: swap;
}
/* 2. Use it on any Arabic text */
.quran {
font-family: 'UthmanicHafs', 'Amiri', serif;
direction: rtl;
font-size: 2rem;
line-height: 2.3;
}
Recipe 2 · Page-glyph font
Page-glyph fonts do not render Unicode. You must load the paired data file (mushaf.txt for v1/v1.5/v2, quran.json for v4) to know which PUA codepoints go on which page.
<!-- 1. Load the font for the specific page you want -->
<style>
@font-face {
font-family: 'QCF_P001';
src: url('https://fonts.quran.ws/assets/fonts/qpc-hafs-v1/QCF_P001.woff2') format('woff2');
}
.page-glyph {
font-family: 'QCF_P001';
unicode-bidi: bidi-override; /* PUA defaults to LTR; override to RTL */
direction: rtl;
font-size: 2rem;
}
</style>
<!-- 2. Fetch the paired ayah-keyed glyph data -->
<script>
const data = await fetch('https://fonts.quran.ws/bundles/qpc-hafs-v1/quran-glyphs.json').then(r => r.json());
// Each ayah is {surah, ayah, chunks: [{p, family, file, text}]} — render the first chunk
const ayah = data.ayat[0];
document.querySelector('.page-glyph').textContent = ayah.chunks.map(c => c.text).join('');
</script>
<!-- 3. Render -->
<div class="page-glyph"></div>
Recipe 3 · Tajweed images
Tajweed data carries rule tags per word. Pair with a tajweed-aware font (QPC V4) or render with coloured spans.
<!-- No font needed — pair the tajweed-coloured mushaf text with any renderer. -->
<!-- Grab the ready-to-use bundle from https://fonts.quran.ws/bundles/hafs-tajweed/ -->
<script>
const r = await fetch('https://fonts.quran.ws/bundles/hafs-tajweed/quran.json').then(r => r.json());
const ayah = r.ayat.find(a => a.surah === 2 && a.ayah === 255);
document.querySelector('.ayah').textContent = ayah.text;
</script>
<span class="ayah"></span>
Font ↔ data pairing
| Version | Font name | Page → font | Data file |
|---|---|---|---|
v1 |
QCF_P{page:03d} |
QCF_P{page:03d} |
hafs-glyphs/v1/data/mushaf.txt |
v1.5 |
page_{page} |
page_{page} |
hafs-glyphs/v1.5/data/mushaf.txt |
v2 |
QCF2{page:03d} |
QCF2{page:03d} |
hafs-glyphs/v2/data/mushaf.txt |
v4 Hafs |
QCF4_Hafs_{range:02d}_W |
per-word p field |
hafs-glyphs/v4/data/quran.json |
v4 Warsh |
QCF4_Warsh_{range:02d}_W |
per-word p field |
warsh-glyphs/v4/data/quran.json |