What is satori?
Satori is an npm package designed to generate SVG images from HTML and CSS. It is particularly useful for creating dynamic, server-side rendered graphics that can be used in various applications such as social media previews, charts, and more.
What are satori's main functionalities?
Generate SVG from HTML
This feature allows you to convert HTML content into an SVG image. The code sample demonstrates how to generate an SVG from a simple HTML string.
const satori = require('satori');
const html = '<div>Hello, World!</div>';
const svg = satori(html, { width: 200, height: 100 });
console.log(svg);
Support for CSS Styling
Satori supports CSS styling within the HTML content. The code sample shows how to apply CSS styles to the HTML content before converting it to an SVG.
const satori = require('satori');
const html = '<div style="color: red;">Hello, World!</div>';
const svg = satori(html, { width: 200, height: 100 });
console.log(svg);
Custom Fonts
You can use custom fonts in your HTML content when generating SVGs. The code sample demonstrates how to include a custom font in the SVG generation process.
const satori = require('satori');
const html = '<div style="font-family: CustomFont;">Hello, World!</div>';
const svg = satori(html, { width: 200, height: 100, fonts: [{ name: 'CustomFont', data: 'base64-encoded-font-data' }] });
console.log(svg);
Other packages similar to satori
html-to-image
The 'html-to-image' package allows you to convert HTML content to various image formats, including PNG and JPEG. Unlike Satori, which focuses on SVG generation, 'html-to-image' provides more flexibility in terms of output formats.
puppeteer
Puppeteer is a Node library that provides a high-level API to control Chrome or Chromium over the DevTools Protocol. It can be used to generate screenshots and PDFs of web pages, making it a more versatile but heavier alternative to Satori for generating images from HTML content.
dom-to-image
The 'dom-to-image' package allows you to convert DOM nodes to images in various formats. It is similar to Satori in that it can generate images from HTML content, but it supports more output formats like PNG and JPEG.
Satori
API
Satori translates the layout and styles of HTML & CSS based elements into an SVG image.
import satori from 'satori'
satori(
<div style={{ color: 'black' }}>hello, world</div>,
{
width: 600,
height: 400,
fonts: [
{
name: 'Roboto',
data: robotoArrayBuffer,
weight: 400,
style: 'normal',
},
...
],
embedFont: true,
debug: false,
graphemeImages: {}
},
)
Which yields:
'<svg ...><path d="..." fill="black"></path></svg>'
Text (with font data) will be embedded in the SVG as paths.
Playground
https://satori-playground.vercel.app
Documentation
JSX
Satori only accepts JSX elements that are pure and stateless. You can use a subset of HTML
elements (see section below), or custom React components, but React APIs such as useState
and
useEffect
are not supported.
Use without JSX
If you don't have JSX transpiler enabled, you can simply pass React-elements-like objects that have type
, props.children
and props.style
(and other properties too) directly:
satori(
{
type: 'div',
props: {
children: 'hello, world',
style: { color: 'black' },
},
},
options
)
HTML Elements
Satori supports a limited subset of HTML and CSS features, due to its special use cases. In general, only these static and visible elements and properties that are implemented.
For example, the <input>
HTML element, the cursor
CSS property are not in consideration. And you can't use <style>
tags or external resources via <link>
or <script>
.
Also, Satori does not guarantee that the SVG will 100% match the browser-rendered HTML output since Satori implements its own layout engine based on the SVG 1.1 spec.
You can find the list of supported HTML elements and their preset styles here.
Images
You can use <img>
to embed images but src
, width
, and height
attributes are all required.
satori(
<img src="https://picsum.photos/200/300" width={200} height={300} />,
options
)
When using background-image
, the image will be stretched to fit the element by default if you don't specify the size.
If you want to render the generated SVG to another image format such as PNG, it would be better to use base64 encoded image data directly as props.src
so no extra I/O is needed.
Emojis
To render custom images for specific graphemes, you can use graphemeImages
option to map the grapheme to an image source:
satori(
<div>Next.js is 🤯!</div>,
{
...,
graphemeImages: {
'🤯': 'https://twemoji.maxcdn.com/v/13.1.0/svg/1f92f.svg',
},
}
)
The image will be resized to the current font-size (both width and height), so it must be a square.
CSS Properties
Property | Supported Values |
---|
display | none , flex |
position | relative , absolute |
margin , padding | Supported |
top , right , bottom , left | Supported |
width , height | Supported |
max-width , max-height | Supported |
min-width , min-height | Supported |
border | Supported |
flex-direction | Supported |
flex-wrap | Supported |
flex-grow | Supported |
flex-shrink | Supported |
flex-basis | Supported except for auto |
align-items | Supported |
align-content | Supported |
align-self | Supported |
justify-content | Supported |
font-family | Support single value |
font-size | Supported |
font-weight | Supported |
font-style | Supported |
text-align | Supported |
letter-spacing | Supported |
box-shadow | All supported except spread-radius and inset (works like drop-shadow ) |
border-radius | Supported |
overflow | visible , hidden |
color | Supported |
transform | Support absolute values |
object-fit | contain , cover , none |
opacity | Supported |
background-color | Supported |
background-image | Support linear-gradient , url |
word-break | Supported |
text-shadow | Supported |
text-transform | Support lowercase , uppercase , capitalize |
background-position | Supported |
background-size | Support two-value size string such as 10px 20% |
background-clip | TBD |
background-repeat | TBD |
background-origin | TBD |
text-decoration | TBD |
transform-origin | TBD |
line-height | TBD |
white-space | TBD |
Note:
- Three-dimensional transforms are not supported.
- There is no
z-index
support in SVG. Elements that come later in the document will be painted on top. box-sizing
is set to border-box
for all elements.
Contribute
This project uses pnpm. To install dependencies, run:
pnpm install
To start the playground locally, run:
cd playground
pnpm dev
And visit localhost:3000/test.
To start the development mode, run pnpm dev
in the root directory (can be used together with the playground to view it in live).
To start and live-watch the tests, run:
pnpm dev:test
Author