Images and Fonts
By Syncfusion®, Inc. · Last updated
Images in public/ and src/, the Image and Picture components, local and remote images, authorized domains, image sizes, responsive layouts, fit and position, images in Markdown and collections, getImage(), SVG components, image services and the Fonts API.
Images in Astro
- Images are often the heaviest part of a page. A large photo can be bigger than all the HTML, CSS and JavaScript together.
- Astro has built-in tools that make images smaller and load them at the right time.
- Image optimisation = making an image file smaller (resize, compress, modern format) without visible loss.
- In this lesson, you will add optimised images to Asha's site, and load a custom font.
Simple lesson: use Astro's image tools, and your images get smaller and safer to load.
A Real-World Example
- Asha adds a 4000 × 3000 photo from her phone as a post cover. The file is 4 MB.
- On the page, the photo is only shown 800 pixels wide.
- With a plain
<img>, every reader downloads all 4 MB. - With Astro's
<Image />, the build makes an 800-pixel-wide version in a modern format, often under 100 KB.
Press ▶ Run. Then open HTML sent to browser and look at the <img> tag.
What happened:
import cover from "../assets/cover.svg"gave Astro the image's file and its size.width={300}was given. Astro worked outheight="200", to keep the shape.- Astro added
loading="lazy"anddecoding="async"for you.
What You Will Learn
In this lesson, you will learn:
- Where to keep images:
public/orsrc/. - How
<Image />and<Picture />work. - How to show remote images, and allow their domains.
- How image sizes and responsive layouts work.
- How to use images in Markdown and collections.
- What
getImage(), SVG components and image services are. - How to load fonts with the Fonts API.
Images in public/ vs src/
src/ Images
- Keep most images in
src/, such assrc/assets/. - Import them:
import cover from "../assets/cover.jpg";. - Astro knows their size and optimises them at build time.
- The file name gets a hash, such as
cover.B2x9a.webp, so browsers can cache it for a long time.
public/ Images
- Images in
public/are copied as they are. They are not optimised. - Use them with a plain path:
src="/photo.jpg". - Use
public/only when a file must keep its exact name, such asfavicon.svgor a social image.
Default to src/assets/ for images. Only move an image to public/ when something outside your code needs its exact address.
Simple lesson: images in src/ are optimised. Images in public/ are copied as they are.
The Image and Picture Components
The Image Component
<Image />comes fromastro:assets.- It needs
srcandalt. - alt = a short text that describes the image, for screen readers and search engines. Use
alt=""for a purely decorative image. - Astro stops the build if
altis missing. This protects your readers.
Image Dimensions
widthandheightset the size of the image Astro makes.- For a local image, give one of them and Astro works out the other. Give none, and Astro uses the file's own size.
- The browser uses both values to keep space for the image before it loads. The page does not jump.
The Picture Component
<Picture />makes a<picture>element with several formats.formats={["avif", "webp"]}lists the formats to offer, best first.- Each browser picks the first format it supports. Older browsers fall back to the
<img>inside.
Animation: a 4 MB photo goes through astro build and comes out as a 90 KB WebP and a 60 KB AVIF.
photo.jpg 4000 × 3000 · 4 MB
astro build resize + compress
photo.webp 800 × 600 · 90 KB
photo.avif 800 × 600 · 60 KB
Example sizes. Real savings depend on the photo.
The build makes small, modern copies of each image.
Press ▶ Run. Compare the <img> from <Image /> with the <picture> from <Picture />.
On your computer, Astro uses the Sharp library to turn photos into small WebP and AVIF files. This lab runs in the browser, so it keeps the original file and only writes the same HTML attributes. SVG files are already small, so the labs use them.
Simple lesson: <Image /> for one optimised image, <Picture /> to offer several formats.
Local and Remote Images
Remote Images
- Remote image = an image from another website, used with a full URL.
- Astro cannot read its size from your project, so give
widthandheight. - Or add
inferSizeand Astro downloads the image once to find its size.
Authorizing Remote Image Domains
- By default, Astro does not optimise images from other websites. It shows them as they are.
- To allow it, list the trusted domains in the config:
export default defineConfig({
image: {
domains: ["images.unsplash.com"],
},
});
image.remotePatternsallows wider rules, such as every sub-domain of a site.- This protects your build from being used to process images from anywhere.
Simple lesson: remote images need a size, and their domain must be allowed before Astro optimises them.
Responsive Images
The layout Property
- Responsive image = an image that adapts to the screen size, so phones download small files and big screens get sharp ones.
Add
layoutto<Image />or<Picture />:"constrained"= shrinks on small screens, never grows past its width. Good for most images."full-width"= always fills the width of its container. Good for banners."fixed"= keeps the exact size. Good for avatars and icons."none"= no responsive behaviour.
- Astro then adds
srcsetandsizes. The browser picks the best file for the screen. - Set a default for the whole site with
image: { layout: "constrained" }in the config.
fit and position
fit= how the image fills its box:"cover"(crop to fill),"contain"(show it all) and others, like CSSobject-fit.position= which part to keep when it is cropped:"top","center","left bottom"and so on.
Responsive Image Styles
- With a
layout, Astro adds a small set of styles that make the image behave correctly. image.responsiveStylesin the config turns them on or off.
Press ▶ Run. Make the preview narrower by dragging the bar. The constrained image shrinks. The fixed one does not.
Simple lesson: pick a layout, and Astro makes the image fit every screen.
Images in Content
Images in Markdown and MDX
- In Markdown, write
. - A path starting with
./or../is a local image. Astro optimises it like an<Image />. - A path starting with
/is frompublic/and is not optimised.
The image() Helper in Collection Schemas
- A post's cover image can be a frontmatter field:
cover: ./cover.jpg. - In the schema, use the
image()helper. The schema becomes a function that receives it:
schema: ({ image }) =>
z.object({
title: z.string(),
cover: image(),
}),
image()checks that the file exists and turns the path into image data you can pass to<Image />.- The path is relative to the Markdown file.
[TS] ImageMetadata
- The type of an imported image is
ImageMetadata:src,width,heightandformat. - Use it for a component prop:
interface Props { cover: ImageMetadata }. - [JS] You do not need the type. The object is the same.
Simple lesson: use image() in a schema for cover images. Pass the result straight to <Image />.
Advanced Image Handling
getImage()
getImage()makes an optimised image without an<img>tag.- Use it when you need just the URL, such as for a CSS background or an Open Graph image.
const og = await getImage({ src: cover, width: 1200 });then useog.src.
Importing SVG Files as Components
- An imported
.svgfile can also be used as a component:<Logo width={48} />. - Astro puts the SVG code straight into the HTML. No extra file is downloaded.
- Props you pass, such as
width,heightandclass, are added to the<svg>tag.
Image Services
- Image service = the tool that does the optimising.
- The default is Sharp, which runs on your computer at build time.
passthroughImageService()turns optimisation off. Use it on hosts where Sharp cannot run.
Press ▶ Run. The logo is drawn inline. The banner URL comes from getImage().
Simple lesson: getImage() gives you just the optimised URL. SVG imports can be inline components.
Fonts
The Fonts API Overview
- Web font = a font file the browser downloads, so your text looks the same on every device.
- Astro's Fonts API downloads font files at build time and serves them from your own site.
- It is faster and more private than loading fonts from another website on every visit.
Configuring Fonts
- List fonts in
astro.config.mjsunderfonts:
import { defineConfig, fontProviders } from "astro/config";
export default defineConfig({
fonts: [
{
provider: fontProviders.google(),
name: "Poppins",
cssVariable: "--font-poppins",
weights: [400, 700],
fallbacks: ["sans-serif"],
},
],
});
Font Providers
- Font provider = where the font files come from.
- Built-in providers include Google Fonts, Fontsource, Bunny and Fontshare.
fontProviders.local()uses font files you keep in your project.
Using Fonts in Layouts
- Add
<Font cssVariable="--font-poppins" />fromastro:assetsinside your layout's<head>. - Use the variable in CSS:
font-family: var(--font-poppins);.
Font Fallbacks and Preloading
fallbacks= fonts to show while the web font loads, or if it fails.- Astro adjusts the fallback's size to match the web font, so text does not jump when it loads.
<Font cssVariable="--font-poppins" preload />adds preload links: the browser starts downloading the font early.- Preload only the fonts used at the top of the page. Each preload competes with other downloads.
Press ▶ Run. The <Font /> component defines the CSS variable. The body uses it.
In this lab, no font file is downloaded. <Font /> only sets the variable, so the text shows the fallback (Georgia). On your computer, the real Poppins files are downloaded at build time and served from your site.
Simple lesson: list fonts in the config, add <Font /> to the layout, and use the CSS variable.
TL;DR
- src/ images = optimised. public/ images = copied as they are.
<Image />= needssrcandalt. Adds width, height, lazy loading.<Picture />= several formats withformats={["avif", "webp"]}.- Remote images = need
widthandheight(orinferSize). Allow domains withimage.domains. - layout =
constrained,full-width,fixedornone.fitandpositioncontrol cropping. - image() = image fields in collection schemas, relative to the Markdown file.
- getImage() = an optimised URL without a tag.
- SVG import = can be a component:
<Logo width={48} />. - Fonts API =
fontsin the config,<Font cssVariable="..." />in the head.
Common mistakes
| Mistake | Wrong idea | Correct idea | What goes wrong |
|---|---|---|---|
No alt | alt is optional | Always add alt, or alt="" for decoration | The build stops |
| Remote image with no size | Astro measures every image | Give width and height, or inferSize | The build stops |
src="../assets/x.jpg" as a string | Strings work like imports | Import the image, then pass the import | The image is not found or not optimised |
Big photos in public/ | Every image is optimised | Keep photos in src/ | Readers download huge files |
Forgetting image.domains | Remote images are always optimised | List the domain in the config | The image is shown at full size |
| Preloading every font weight | More preloads load faster | Preload only what is used first | Slower first paint |
Check Yourself
Exercises
What to Remember
- Keep images in
src/and import them.public/images are not optimised. <Image />needsalt.<Picture />offers several formats.- Remote images need a size and an allowed domain.
layoutmakes images responsive.image()adds images to collections.- The Fonts API serves fonts from your own site, with smart fallbacks.
Next: External Data and Environment Variables, where Asha's site reads data from an API.