August 28, 2024
Export Font Emoji As Image With Custom OS Design Using CSS And Client-side JavaScript
Save any smiley or icon as a PNG file independent of platform or device designs in-browser. Include full code implementation.

By Charmaine Chui
3 min read
Emoji designs and uses in modern digital age have evolved and diversified significantly over time. Presently emojis have expanded beyond the originally intended role as communication tools on text messaging platforms such as WhatsApp or Telegram and are applied in other areas inclusive of graphics design and infographics for visual storytelling.
Rationale: A follow-up to previous pet project
Some time ago in year 2022 I have implemented a client-side web application as a convenient means to retrieve emoji images for use (please refer to implementation details in below post).
Convert Font Emojis to Image Files with Custom Dimensions using Vanilla JavaScript 👩💻 W th full code implementation. Export any smiley or symbol as image files for use.me
However, following the release of Windows 11, it became apparent that the emoji designs have been updated as well and emojis rendered are different as compared to the time of the post.
Emoji Designs — Windows 10 vs Windows 11
As such, I thought it would be useful to develop an additional feature onto the web application to toggle the OS version design specific to the font emojis rendered. This would therefore enable images of emojis to be exported independent of browser platform.
Implementation Details
Prerequisite step: Append the following CSS between 2 style tags at the top of the HTML document.
<style>
body {
padding: 5% 15%;
}
.emoji {
font-family:Segoe UI Emoji !important;
}
</style><style>
body {
padding: 5% 15%;
}
.emoji {
font-family:Segoe UI Emoji !important;
}
</style>Step 1: Initialise a HTML Canvas via JavaScript
var emojiClass='emoji'; // default CSS class
var icon = '😀'; // default smiley displayed
var _scale=window.devicePixelRatio*2;
var w=96, h=96, fontSize,canvas,ctx,_x,_y,faviconTag;
canvas=document.createElement('canvas');
document.body.appendChild(canvas);
canvas.width=w;
canvas.height=h;
fontSize = h/_scale;
canvas['style']['margin']='1px auto';
canvas['style']['width']=`${w/_scale}px`;
canvas['style']['height']=`${h/_scale}px`;
var ctx=canvas.getContext('2d');
ctx.scale(_scale,_scale);var emojiClass='emoji'; // default CSS class
var icon = '😀'; // default smiley displayed
var _scale=window.devicePixelRatio*2;
var w=96, h=96, fontSize,canvas,ctx,_x,_y,faviconTag;
canvas=document.createElement('canvas');
document.body.appendChild(canvas);
canvas.width=w;
canvas.height=h;
fontSize = h/_scale;
canvas['style']['margin']='1px auto';
canvas['style']['width']=`${w/_scale}px`;
canvas['style']['height']=`${h/_scale}px`;
var ctx=canvas.getContext('2d');
ctx.scale(_scale,_scale);Important: When working with Canvas elements, ensure that the correct scaling is used so as not to render low resolution images.
Note: canvas['style']['height']is NOT equivalent to canvas.height
Step 2: Assign properties and values to Canvas
ctx.font = `${fontSize}px ${ (emojiClass=='emoji') ? 'Segoe UI Emoji' : emojiClass }`;
ctx.textAlign = 'center';
ctx.textBaseline='middle';
ctx.direction='ltr';
ctx.globalAlpha=1.0;
ctx.fontVariantCaps='unicase';
ctx.fontKerning='auto';
ctx.fontStretch='normal';
ctx.filter='none';
ctx.globalCompositeOperation='source-over';
ctx.imageSmoothingEnabled=true;
ctx.imageSmoothingQuality='high';
ctx.lineCap='butt';
ctx.lineDashOffset=0;
ctx.lineJoin='miter';
ctx.miterLimit=10;
ctx.shadowBlur=0;
ctx.shadowColor='rgba(0, 0, 0, 0)';
ctx.shadowOffsetX=0;
ctx.shadowOffsetY=0;
ctx.textRendering='auto';
_x=((canvas.width/_scale)/2);
_y=((canvas.height/_scale)/2);
ctx.fillText(icon, _x, _y);ctx.font = `${fontSize}px ${ (emojiClass=='emoji') ? 'Segoe UI Emoji' : emojiClass }`;
ctx.textAlign = 'center';
ctx.textBaseline='middle';
ctx.direction='ltr';
ctx.globalAlpha=1.0;
ctx.fontVariantCaps='unicase';
ctx.fontKerning='auto';
ctx.fontStretch='normal';
ctx.filter='none';
ctx.globalCompositeOperation='source-over';
ctx.imageSmoothingEnabled=true;
ctx.imageSmoothingQuality='high';
ctx.lineCap='butt';
ctx.lineDashOffset=0;
ctx.lineJoin='miter';
ctx.miterLimit=10;
ctx.shadowBlur=0;
ctx.shadowColor='rgba(0, 0, 0, 0)';
ctx.shadowOffsetX=0;
ctx.shadowOffsetY=0;
ctx.textRendering='auto';
_x=((canvas.width/_scale)/2);
_y=((canvas.height/_scale)/2);
ctx.fillText(icon, _x, _y);To render custom emoji onto the canvas, append an input element assigned to a variable is named inputIcon:
const inputIcon = document.createElement('input');
inputIcon.value=icon;
document.body.appendChild(inputIcon);
inputIcon.addEventListener('input', (evt)=> {
icon=evt.target.value;
canvas.getContext('2d').clearRect(0, 0,canvas.width,canvas.height);
canvas.getContext('2d').fillText(icon, _x, _y);
});const inputIcon = document.createElement('input');
inputIcon.value=icon;
document.body.appendChild(inputIcon);
inputIcon.addEventListener('input', (evt)=> {
icon=evt.target.value;
canvas.getContext('2d').clearRect(0, 0,canvas.width,canvas.height);
canvas.getContext('2d').fillText(icon, _x, _y);
});
Step 3. Import other font emoji files and specify custom class in CSS markup.
Retrieve an older Windows OS version of the font emoji from here and download the TrueType Font File. Rename it to seguiemj-win8.ttf and place file into a nested folder (within folder css) named fonts.
Include the following CSS markup between the 2 style tags from step 1:
@font-face {
font-family: EmojiFontWin8;
src: url(css/fonts/seguiemj-win8.ttf);
}
.EmojiFontWin8 {
font-family:EmojiFontWin8 !important;
}@font-face {
font-family: EmojiFontWin8;
src: url(css/fonts/seguiemj-win8.ttf);
}
.EmojiFontWin8 {
font-family:EmojiFontWin8 !important;
}Modify default emojiClass from previous step to 'EmojiFontWin8' instead:
var emojiClass='EmojiFontWin8'; // default CSS classvar emojiClass='EmojiFontWin8'; // default CSS classTo showcase how the emoji display changes from default platform to match the custom font file, use utility function triggerEvent:
function triggerEvent(el, type) {
let e = (('createEvent' in document) ? document.createEvent('HTMLEvents') : document.createEventObject());
if ('createEvent' in document) {
e.initEvent(type, false, true);
el.dispatchEvent(e);
} else {
e.eventType = type;
el.fireEvent('on' + e.eventType, e);
}
}function triggerEvent(el, type) {
let e = (('createEvent' in document) ? document.createEvent('HTMLEvents') : document.createEventObject());
if ('createEvent' in document) {
e.initEvent(type, false, true);
el.dispatchEvent(e);
} else {
e.eventType = type;
el.fireEvent('on' + e.eventType, e);
}
}Append below JavaScript code —
(async()=> {
// in 2000ms = 2s, 'input' event shall be emitted to input form field
await new Promise((resolve, reject) => setTimeout(resolve, 2000));
triggerEvent(inputIcon,'input');
})();(async()=> {
// in 2000ms = 2s, 'input' event shall be emitted to input form field
await new Promise((resolve, reject) => setTimeout(resolve, 2000));
triggerEvent(inputIcon,'input');
})();Demo:
Preview of final web application
FYI: For the full source code of the web application, please 🔱fork or ⭐star it at my GitHub repo — emoji2image or try it out at demo!
And there you have it! Many thanks for persisting to the end of this article! ❤ Hope you have found this article useful and feel free to follow me on Medium if you would like more Geographic Information Systems (GIS), Data Analytics & Web application-related content. Would really appreciate it — 😀
— 🌮 Please buy me a Taco ξ(🎀˶❛◡❛)
For other related articles, feel free to check out the below —
Render and export symbols:
Generate Icon Images From Font Symbols Using Vanilla JavaScript With full code implementation. Export any text symbol as image files for use. No plugins. Just HTML5 Canvas.
Extract TTF files from PDF:
How To Extract Embedded Fonts From A PDF As Valid Font Files In Java Uses Apache PDFBox to output PDF fonts as reusable TTF files. No cost. No quota.
In Plain English 🚀
Thank you for being a part of the In Plain English community! Before you go:
- Be sure to clap and follow the writer ️👏️️
- Follow us: X | LinkedIn | YouTube | Discord | Newsletter
- Visit our other platforms: CoFeed | Differ
- More content at PlainEnglish.io