Fonts control the appearance of text in Skia. You can use system fonts or load custom font files.
Creating Fonts
Using matchFont
Match system fonts by family, weight, and style:
import { matchFont } from "@shopify/react-native-skia";
const font = matchFont({
fontFamily: "Helvetica",
fontSize: 24,
fontWeight: "bold",
fontStyle: "italic",
});
Using Skia.Font
Create fonts imperatively:
import { Skia } from "@shopify/react-native-skia";
// System font
const font = Skia.Font(null, 24);
// Custom typeface
const typeface = Skia.Typeface.MakeFreeTypeFaceFromData(
require("./fonts/MyFont.ttf")
);
const customFont = Skia.Font(typeface, 24);
Loading Custom Fonts
Using useFonts Hook
import { useFonts, matchFont } from "@shopify/react-native-skia";
export default function CustomFonts() {
const fontsLoaded = useFonts({
"Roboto-Regular": [require("./fonts/Roboto-Regular.ttf")],
"Roboto-Bold": [require("./fonts/Roboto-Bold.ttf"), require("./fonts/Roboto-BoldItalic.ttf")],
});
if (!fontsLoaded) {
return null; // Or loading indicator
}
const regularFont = matchFont({ fontFamily: "Roboto", fontSize: 16 });
const boldFont = matchFont({ fontFamily: "Roboto", fontSize: 16, fontWeight: "bold" });
return (
<Canvas style={{ flex: 1 }}>
<Text x={50} y={100} text="Regular" font={regularFont} />
<Text x={50} y={150} text="Bold" font={boldFont} />
</Canvas>
);
}
Font Configuration
FontStyle Options
Font family name (e.g., “Helvetica”, “Arial”, “Roboto”)
Font weight:
"normal" or 400
"bold" or 700
- Numeric values:
100, 200, 300, 400, 500, 600, 700, 800, 900
fontStyle
'normal' | 'italic' | 'oblique'
Font style
Font width/stretch:
UltraCondensed, ExtraCondensed, Condensed
SemiCondensed, Normal
SemiExpanded, Expanded, ExtraExpanded, UltraExpanded
Font Methods
Measurement
measureText
(text: string, paint?: SkPaint) => SkRect
Gets the bounding box of textconst bounds = font.measureText("Hello");
console.log(bounds); // { x, y, width, height }
getTextWidth
(text: string, paint?: SkPaint) => number
Gets the width of textconst width = font.getTextWidth("Hello World");
getGlyphWidths
(glyphs: number[], paint?: SkPaint) => number[]
Gets widths for specific glyphsconst glyphIDs = font.getGlyphIDs("Hello");
const widths = font.getGlyphWidths(glyphIDs);
Gets font metrics (ascent, descent, leading)const metrics = font.getMetrics();
console.log(metrics);
// {
// ascent: -18.5,
// descent: 4.5,
// leading: 0,
// bounds: { x, y, width, height }
// }
Glyphs
getGlyphIDs
(text: string, numCodePoints?: number) => number[]
Gets glyph IDs for text charactersconst glyphIDs = font.getGlyphIDs("Hello");
console.log(glyphIDs); // [72, 101, 108, 108, 111]
getGlyphIntercepts
(glyphs: number[], positions: SkPoint[], top: number, bottom: number) => number[]
Gets glyph intersections with a horizontal lineconst glyphs = font.getGlyphIDs("Hello");
const positions = glyphs.map((_, i) => ({ x: i * 20, y: 0 }));
const intercepts = font.getGlyphIntercepts(glyphs, positions, -5, 5);
Properties
Gets the font size in pointsconst size = font.getSize();
Gets horizontal scale factor
Gets horizontal skew factor
Checks if emboldening is enabled
Modification
Sets horizontal scalefont.setScaleX(1.2); // 120% width
Sets horizontal skewfont.setSkewX(0.2); // Italic effect
setEmbolden
(embolden: boolean) => void
Enables/disables emboldeningfont.setEmbolden(true); // Make bold
setTypeface
(typeface: SkTypeface | null) => void
Sets the typeface
setEdging
(edging: FontEdging) => void
Sets edge rendering:
FontEdging.Alias: No anti-aliasing
FontEdging.AntiAlias: Standard anti-aliasing
FontEdging.SubpixelAntiAlias: Subpixel anti-aliasing
setHinting
(hinting: FontHinting) => void
Sets hinting level:
FontHinting.None
FontHinting.Slight
FontHinting.Normal
FontHinting.Full
setSubpixel
(subpixel: boolean) => void
Enables/disables subpixel positioning
setLinearMetrics
(linear: boolean) => void
Enables/disables linear metrics
setEmbeddedBitmaps
(embedded: boolean) => void
Enables/disables embedded bitmaps
Font Families
iOS System Fonts
- San Francisco (default)
- Helvetica
- Helvetica Neue
- Arial
- Courier
- Georgia
- Times New Roman
- Verdana
Android System Fonts
- Roboto (default)
- sans-serif
- serif
- monospace
- Droid Sans
- Droid Serif
Examples
Responsive Font Size
import { useWindowDimensions } from "react-native";
import { Canvas, Text, matchFont } from "@shopify/react-native-skia";
export default function ResponsiveText() {
const { width } = useWindowDimensions();
const fontSize = width * 0.05; // 5% of screen width
const font = matchFont({ fontSize });
return (
<Canvas style={{ flex: 1 }}>
<Text x={20} y={100} text="Responsive" font={font} />
</Canvas>
);
}
Font Variations
const thin = matchFont({ fontSize: 24, fontWeight: 100 });
const light = matchFont({ fontSize: 24, fontWeight: 300 });
const regular = matchFont({ fontSize: 24, fontWeight: 400 });
const medium = matchFont({ fontSize: 24, fontWeight: 500 });
const semiBold = matchFont({ fontSize: 24, fontWeight: 600 });
const bold = matchFont({ fontSize: 24, fontWeight: 700 });
const black = matchFont({ fontSize: 24, fontWeight: 900 });
Measuring Text for Layout
const text = "Hello, World!";
const font = matchFont({ fontSize: 24 });
const bounds = font.measureText(text);
const padding = 10;
const boxWidth = bounds.width + padding * 2;
const boxHeight = bounds.height + padding * 2;
<Canvas style={{ flex: 1 }}>
<Rect
x={50 - padding}
y={100 - bounds.height - padding}
width={boxWidth}
height={boxHeight}
color="lightblue"
/>
<Text x={50} y={100} text={text} font={font} color="black" />
</Canvas>
- Load fonts once and reuse font objects
- Use
useMemo to cache font creation
- Prefer system fonts when possible (faster)
- Load only the font weights/styles you need
- Use TextBlob for static text that doesn’t change