';
DOMURL.revokeObjectURL(png);
};
img.src = url;
</script>
My workflow starts with designing the thumbnail in Figma, then exporting as SVG replacing the SVG fonts that were exported by Figma and converting those into <text>
blocks with specific CSS classes to set the font family. Then, rendering content into the text block with ERB.
<svg width="1920" height="1080" viewBox="0 0 1920 1080" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<style>
/* this bit doesn't work while converting to png: */
@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@300;900');
.subhead {
fill: #C2F7EB;
font-family: Roboto;
font-weight: 300;
font-size: 60px;
text-transform: uppercase;
}
.title {
fill: #F72585;
font-family: Roboto;
font-weight: 900;
font-size: 144px;
}
</style>
<g clip-path="url(#clip0)">
<rect width="1920" height="1080" fill="white"/>
<rect width="1920" height="1080" fill="#1B1725"/>
<text x="77" y="250" class="subhead">Ruby Metaprogramming</text>
<text x="77" y="420" class="title">Object#send</text>
</g>
<defs>
<clipPath id="clip0">
<rect width="1920" height="1080" fill="white"/>
</clipPath>
</defs>
</svg>
An SVG will load fine with the correct fonts when loaded in the browser using an @import statement pointing at a font CDN like the one for Google fonts, however when converting the SVG into a PNG those remote font faces are lost.
The next trick to get this bit working was to base64 encode the font file and use a data url to embed the full content of the font into the CSS for styling the text blocks.
If you download a font family from Google fonts, you'll get a set of .tff
files.
Using the built in base64
tool on Mac, you can convert the file into base64 and paste that into the font family like so:
<svg width="1920" height="1080" viewBox="0 0 1920 1080" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<style>
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 300;
font-display: swap;
src: url(data:font/truetype;charset=utf-8;base64,AAEAAAASAQAABAAgR0RFRnBqbY4AAaOkAAAB6kdQT1PZc2ujAAGlkAAATrpHU1VC0HjTzgAB9EwAAAoCT1MvMpcesZEA...)
}
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 900;
font-display: swap;
src: url(data:font/truetype;charset=utf-8;base64,AAEAAAASAQAABAAgR0RFRnBqbY4AAaAMAAAB6kdQT1MfGyUBAAGh+AAAVhxHU1VC0HjTzgAB+BQAAAoCT1MvMpl2sdgA...)
}
.subhead {
fill: #C2F7EB;
font-family: Roboto;
font-weight: 300;
font-size: 60px;
text-transform: uppercase;
}
.title {
fill: #F72585;
font-family: Roboto;
font-weight: 900;
font-size: 144px;
}
</style>
<g clip-path="url(#clip0)">
<rect width="1920" height="1080" fill="white"/>
<rect width="1920" height="1080" fill="#1B1725"/>
<text x="77" y="250" class="subhead">Ruby Metaprogramming</text>
<text x="77" y="420" class="title">Object#send</text>
</g>
<defs>
<clipPath id="clip0">
<rect width="1920" height="1080" fill="white"/>
</clipPath>
</defs>
</svg>