A meme generator creates image macros — images with overlaid text in a recognizable format. The classic style uses white Impact font with black outline at the top and bottom of an image. Modern memes use a much wider variety of layouts and styles, but the core mechanic is the same: take an image, add text, share.
How browser-based meme generation works
Meme generation in the browser uses the HTML Canvas API:
- Draw the image onto a canvas element
- Configure text style: font, size, alignment, color, stroke
- Call
ctx.strokeText()thenctx.fillText()for the classic outlined text effect - Export the canvas to an image file via
canvas.toDataURL()
const canvas = document.getElementById('meme-canvas')
const ctx = canvas.getContext('2d')
// Draw image
ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
// Classic meme text style
ctx.font = 'bold 48px Impact, Arial'
ctx.textAlign = 'center'
ctx.lineWidth = 4
// Stroke first (outline), then fill (white text on top)
ctx.strokeStyle = 'black'
ctx.strokeText('TOP TEXT', canvas.width / 2, 60)
ctx.fillStyle = 'white'
ctx.fillText('TOP TEXT', canvas.width / 2, 60)
The strokeText + fillText layering is essential — drawing the fill first and then the stroke would cover part of the white fill.
Text placement patterns
Different meme formats use different text placement conventions:
| Format | Top text | Bottom text | Notes |
|---|---|---|---|
| Classic macro | Label/setup | Punchline | Most common format |
| Drake pointing | Left panel text | Right panel text | Two-panel format |
| Distracted boyfriend | Caption on each figure | None | Multi-label format |
| Expanding brain | Label per panel | None | 4-panel vertical |
| Two buttons | Label each button | Character sweat | Complex layout |
The classic two-text macro (top and bottom) is the most versatile and works with virtually any image.
Image scaling and aspect ratio
When drawing images to canvas, you need to decide how to handle aspect ratio mismatches:
Contain: The entire image is visible, with letterboxing (bars) if the aspect ratio doesn't match the canvas Cover: The canvas is fully covered, with the image cropped if needed Stretch: The image is distorted to fill the canvas exactly
For meme generation, contain is usually correct — you want to see the whole image without distortion. The canvas size should match the image's natural dimensions.
// Scale image to fit within max dimensions while preserving aspect ratio
const maxWidth = 600
const maxHeight = 600
const scale = Math.min(maxWidth / img.naturalWidth, maxHeight / img.naturalHeight)
const w = img.naturalWidth * scale
const h = img.naturalHeight * scale
canvas.width = w
canvas.height = h
ctx.drawImage(img, 0, 0, w, h)
Font considerations
Impact font
The classic meme font. Impact is a condensed sans-serif typeface — its narrow width allows more text per line than most fonts at the same point size. It's pre-installed on Windows and macOS.
font: bold 48px Impact, Haettenschweiler, 'Arial Narrow Bold', sans-serif
The fallback chain ensures similar condensed appearance on systems without Impact.
Font size scaling
Fixed font sizes look wrong at different image resolutions. A better approach is to scale font size relative to canvas width:
const fontSize = Math.max(20, Math.round(canvas.width * 0.07))
ctx.font = `bold ${fontSize}px Impact`
7% of canvas width gives roughly proportional text for most image sizes.
Text wrapping
Canvas has no native text wrapping. Long text must be manually broken into lines:
function wrapText(ctx, text, maxWidth) {
const words = text.split(' ')
const lines = []
let current = ''
for (const word of words) {
const test = current ? `${current} ${word}` : word
if (ctx.measureText(test).width > maxWidth && current) {
lines.push(current)
current = word
} else {
current = test
}
}
if (current) lines.push(current)
return lines
}
Exporting memes
Canvas provides two export options:
// PNG — lossless, larger file, supports transparency
const pngUrl = canvas.toDataURL('image/png')
// JPEG — lossy, smaller file, no transparency
const jpegUrl = canvas.toDataURL('image/jpeg', 0.92) // quality 0-1
// Copy to clipboard (modern browsers only)
canvas.toBlob(blob => {
navigator.clipboard.write([new ClipboardItem({ 'image/png': blob })])
})
PNG is better for sharing (no JPEG compression artifacts on the text), but JPEG is smaller for platforms that don't mind compression.
Common meme text rules
ALL CAPS is traditional for the classic macro format. Mixed case feels more conversational and is common in modern formats.
Keep it short: Each text panel should ideally fit in 1–2 lines. Memes are visual — if you need three sentences, the text is too long.
Contrast matters: White text with black outline works on any image background. Dark text with light outline works too but is less common.
Alignment: Top text is typically top-centered, bottom text is bottom-centered. Some formats (like Distracted Boyfriend labels) use left, center, or right alignment per panel.
How to create a meme free
- Go to Meme Generator
- Choose a template from the gallery, or click Upload Image to use your own
- Type your top and bottom text — live preview updates instantly
- Adjust font size and style if needed
- Click Download PNG to save, or Copy Image to paste directly into chat
- Use the Swap button to quickly swap top and bottom text
No watermarks are added. Your image never leaves your browser.