Zum Hauptinhalt springen
Echtzeit-Radar & Feeds
Alle RSS Feeds ➔
👥 Community & Social
IT Security NachrichtenHottest cybersecurity open-source tools of the month: September 2026(29.09.2026 um 06:30 Uhr)
•
IT Security NachrichtenFire TV Black Screen After Update? Fix Apps Not Opening(29.09.2026 um 06:20 Uhr)
••
AI & KI NachrichtenGitHub Release: openai/codex vrust-v0.160.0-alpha.4 (29.09.2026)(29.09.2026 um 06:31 Uhr)
•
IT Security DownloadsGitHub Release: anomalyco/opencode v2.0.19 (29.09.2026)(29.09.2026 um 06:30 Uhr)
••
IT NachrichtenClever fahren, weniger tanken: Die Segelfunktion erklärt(29.09.2026 um 06:28 Uhr)
•
IT NachrichtenDisney stellt Futurama schon wieder offiziell ein(29.09.2026 um 06:24 Uhr)
•••
IT Security NachrichtenHottest cybersecurity open-source tools of the month: September 2026(29.09.2026 um 06:30 Uhr)
•
IT Security NachrichtenFire TV Black Screen After Update? Fix Apps Not Opening(29.09.2026 um 06:20 Uhr)
••
AI & KI NachrichtenGitHub Release: openai/codex vrust-v0.160.0-alpha.4 (29.09.2026)(29.09.2026 um 06:31 Uhr)
•
IT Security DownloadsGitHub Release: anomalyco/opencode v2.0.19 (29.09.2026)(29.09.2026 um 06:30 Uhr)
••
IT NachrichtenClever fahren, weniger tanken: Die Segelfunktion erklärt(29.09.2026 um 06:28 Uhr)
•
IT NachrichtenDisney stellt Futurama schon wieder offiziell ein(29.09.2026 um 06:24 Uhr)
•••
Intelligence View
⚡ tsecurity.de Intelligence

A Fully-Local Placeholder Image Generator — No More Blocking via.placeholder.com

A Fully-Local Placeholder Image Generator — No More Blocking via.placeholder.com Placeholder image services go down, get rate-limited, or get blocked by corporate firewalls. And they're an unnecessary external dependency when Canvas can …

0
↗ Quelle (dev.to)
Reagiere als Erste:r — dein Feedback zählt!




A Fully-Local Placeholder Image Generator — No More Blocking via.placeholder.com




Placeholder image services go down, get rate-limited, or get blocked by corporate firewalls. And they're an unnecessary external dependency when Canvas can generate the same image in milliseconds, entirely in your browser. This tool gives you sized placeholders with colored backgrounds, 6 patterns, and PNG download — without touching a network.




Anyone who's built a UI with placeholder images has been burned by the hosted service going down. via.placeholder.com, placeholder.com, placehold.it — they all have uptime issues. The solution is obvious in retrospect: draw the image locally.



🔗 Live demo: https://sen.ltd/portfolio/placeholder-img/

📦 GitHub: https://github.com/sen-ltd/placeholder-img



Screenshot



Features:




  • Custom dimensions (W × H) or presets

  • 6 patterns: solid, checkerboard, grid, diagonal stripes, noise, gradient

  • Background and text color pickers

  • Custom text (default: dimensions)

  • Drag-to-resize preview

  • Bulk download (generate a set of sizes at once)

  • PNG download

  • Japanese / English UI

  • Zero dependencies, 32 tests





Contrast-aware text color



When the user picks a background color, the text should stay readable. Auto-choose white or black based on luminance:




export function getBrightness(hex) {
const { r, g, b } = parseHex(hex);
// Standard luminance formula
return Math.round((r * 299 + g * 587 + b * 114) / 1000);
}

export function contrastingColor(hex) {
return getBrightness(hex) > 128 ? '#000000' : '#ffffff';
}






The 299/587/114 coefficients come from NTSC luminance (approximation of human perception). 128 is the midpoint; above it the background is "bright" and black text reads better, below it the background is "dark" and white text reads better.






Proportional font size



A 32×32 favicon and a 1920×1080 banner both need readable text, but not the same font size. Scale by the smaller dimension:




export function calculateFontSize(width, height, ratio = 0.15) {
return Math.max(10, Math.round(Math.min(width, height) * ratio));
}






ratio = 0.15 means the text height is 15% of the smaller dimension. A 32×32 image gets 5px (clamped to 10), a 1920×1080 gets 162px. The minimum of 10px prevents unreadable tiny text on small placeholders.






Pattern: checkerboard






export function drawCheckerboard(ctx, w, h, size, color1, color2) {
for (let y = 0; y < h; y += size) {
for (let x = 0; x < w; x += size) {
const even = ((x / size) + (y / size)) % 2 === 0;
ctx.fillStyle = even ? color1 : color2;
ctx.fillRect(x, y, size, size);
}
}
}






The sum of cell coordinates being even or odd determines the color — same trick as a chessboard. For a 400×300 image with size=20, that's 300 cells total, each rendered in a single fillRect call. Milliseconds.






Pattern: diagonal stripes






export function drawDiagonalStripes(ctx, w, h, size, color1, color2) {
ctx.fillStyle = color1;
ctx.fillRect(0, 0, w, h);
ctx.fillStyle = color2;
// Draw stripes as parallelograms shifted along the diagonal
for (let offset = -h; offset < w + h; offset += size * 2) {
ctx.beginPath();
ctx.moveTo(offset, 0);
ctx.lineTo(offset + size, 0);
ctx.lineTo(offset + size + h, h);
ctx.lineTo(offset + h, h);
ctx.closePath();
ctx.fill();
}
}






Each stripe is a parallelogram. Start at offset on the top edge, go right by size, go down to h (with the same x-offset) — that's one stripe. Repeat every size * 2 pixels (stripe + gap = 2 × size).






Bulk generation



The killer feature for practical use: generate a full set of placeholder images at once. Needs a 400×400 Instagram, a 1200×630 OGP, and a 1280×720 YouTube thumbnail? Click "Social Media set" and get a ZIP of all three.



Actually, creating a ZIP requires a library. The simpler version: trigger multiple <a download> clicks in sequence:




async function bulkDownload(presets, options) {
for (const preset of presets) {
const canvas = document.createElement('canvas');
canvas.width = preset.w;
canvas.height = preset.h;
drawPlaceholder(canvas, { ...options, width: preset.w, height: preset.h });
const url = canvas.toDataURL('image/png');
const a = document.createElement('a');
a.href = url;
a.download = `placeholder-${preset.w}x${preset.h}.png`;
a.click();
await new Promise(r => setTimeout(r, 100));
}
}






The setTimeout(100) gives the browser time to register each download before the next one starts. Without it, browsers might deduplicate or cancel rapid downloads.






Series



This is entry #85 in my 100+ public portfolio series.



Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten A Fully-Local Placeholder Image Generator — No More Blocking via.placeholder.com

Thematisch verwandte Begriffe: FullyLocal, Placeholder, Image, Generator · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

💬 Kommentare werden geladen…
Zum Aktualisieren ziehen
ZERO-DAY CVE-2026-102367 | mall4j through 4.0 contains an insufficient session expiration vulnerab…
Advisory →
tsecurity.de Icon
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag