The following example is a working browser-based bulk image generator.
It doesn’t just display HTML cards. It uses the HTML Canvas API to create actual image files that can be downloaded as PNG images.
You can enter multiple titles, select an image ratio, choose a font, adjust the font size, select a design style, and generate multiple images.
Complete HTML Code
Create a file called:
bulk-image-generator.html
Then paste the complete code below into it and open the file in your browser.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Bulk Image Generator</title>
<style>
* {
box-sizing: border-box;
}
body {
margin: 0;
font-family: Arial, sans-serif;
background: #f3f4f6;
color: #111827;
}
.container {
max-width: 1200px;
margin: auto;
padding: 30px 20px;
}
h1 {
margin-bottom: 8px;
}
.subtitle {
color: #6b7280;
margin-bottom: 25px;
}
.panel {
background: #ffffff;
padding: 22px;
border-radius: 14px;
margin-bottom: 25px;
box-shadow: 0 5px 20px rgba(0,0,0,0.06);
}
textarea {
width: 100%;
min-height: 160px;
padding: 15px;
border: 1px solid #d1d5db;
border-radius: 10px;
resize: vertical;
font-size: 16px;
}
.controls {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
gap: 15px;
margin-top: 20px;
}
.control label {
display: block;
font-size: 14px;
font-weight: 600;
margin-bottom: 7px;
}
select,
input[type="number"],
input[type="color"] {
width: 100%;
height: 42px;
border: 1px solid #d1d5db;
border-radius: 8px;
padding: 8px;
background: white;
}
input[type="range"] {
width: 100%;
}
button {
border: none;
padding: 12px 18px;
border-radius: 8px;
cursor: pointer;
font-weight: 600;
margin-top: 18px;
margin-right: 8px;
}
.generate {
background: #111827;
color: white;
}
.download-all {
background: #2563eb;
color: white;
}
.preview-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 20px;
}
.image-item {
background: white;
padding: 12px;
border-radius: 12px;
box-shadow: 0 5px 18px rgba(0,0,0,0.07);
}
.image-item img {
width: 100%;
display: block;
border-radius: 8px;
}
.image-title {
font-size: 14px;
margin-top: 10px;
font-weight: 600;
}
.download-one {
width: 100%;
margin-top: 10px;
background: #e5e7eb;
color: #111827;
}
.status {
margin-top: 15px;
color: #6b7280;
}
</style>
</head>
<body>
<div class="container">
<h1>Bulk Image Generator</h1>
<p class="subtitle">
Create multiple images from a list of titles directly in your browser.
</p>
<div class="panel">
<h2>1. Enter Your Text</h2>
<p>
Enter one title or phrase per line.
</p>
<textarea id="textInput"
placeholder="Example:
10 Writing Tips
How to Start a Blog
SEO Basics
Content Marketing
Social Media Tips"></textarea>
<div class="controls">
<div class="control">
<label>Image Ratio</label>
<select id="ratio">
<option value="landscape">16:9 Landscape</option>
<option value="square">1:1 Square</option>
<option value="portrait">4:5 Portrait</option>
<option value="story">9:16 Story</option>
</select>
</div>
<div class="control">
<label>Font</label>
<select id="font">
<option value="Arial">Arial</option>
<option value="Georgia">Georgia</option>
<option value="Verdana">Verdana</option>
<option value="Trebuchet MS">Trebuchet MS</option>
<option value="Courier New">Courier New</option>
</select>
</div>
<div class="control">
<label>Font Size</label>
<input
type="number"
id="fontSize"
value="52"
min="20"
max="120">
</div>
<div class="control">
<label>Text Alignment</label>
<select id="alignment">
<option value="center">Center</option>
<option value="left">Left</option>
<option value="right">Right</option>
</select>
</div>
<div class="control">
<label>Design Style</label>
<select id="style">
<option value="modern">Modern</option>
<option value="minimal">Minimal</option>
<option value="dark">Dark</option>
<option value="gradient">Gradient</option>
<option value="bold">Bold</option>
</select>
</div>
<div class="control">
<label>Custom Background</label>
<input
type="color"
id="background"
value="#2563eb">
</div>
</div>
<button class="generate" onclick="generateImages()">
Generate Images
</button>
<button class="download-all" onclick="downloadAll()">
Download All
</button>
<div id="status" class="status"></div>
</div>
<div class="panel">
<h2>Generated Images</h2>
<div id="preview" class="preview-grid"></div>
</div>
</div>
<script>
let generatedImages = [];
/* -------------------------
IMAGE SIZE
------------------------- */
function getImageSize() {
const ratio = document.getElementById("ratio").value;
if (ratio === "square") {
return {
width: 1080,
height: 1080
};
}
if (ratio === "portrait") {
return {
width: 1080,
height: 1350
};
}
if (ratio === "story") {
return {
width: 1080,
height: 1920
};
}
return {
width: 1200,
height: 675
};
}
/* -------------------------
TEXT WRAPPING
------------------------- */
function wrapText(ctx, text, maxWidth) {
const words = text.split(" ");
const lines = [];
let line = "";
words.forEach(word => {
const testLine = line
? line + " " + word
: word;
const width = ctx.measureText(testLine).width;
if (width > maxWidth && line) {
lines.push(line);
line = word;
} else {
line = testLine;
}
});
if (line) {
lines.push(line);
}
return lines;
}
/* -------------------------
BACKGROUND
------------------------- */
function drawBackground(ctx, width, height, style, customColor) {
if (style === "modern") {
ctx.fillStyle = customColor;
ctx.fillRect(0, 0, width, height);
ctx.fillStyle = "rgba(255,255,255,0.12)";
ctx.beginPath();
ctx.arc(
width * 0.85,
height * 0.2,
height * 0.25,
0,
Math.PI * 2
);
ctx.fill();
}
else if (style === "minimal") {
ctx.fillStyle = "#ffffff";
ctx.fillRect(0, 0, width, height);
ctx.fillStyle = customColor;
ctx.fillRect(0, 0, 18, height);
}
else if (style === "dark") {
ctx.fillStyle = "#111111";
ctx.fillRect(0, 0, width, height);
ctx.fillStyle = customColor;
ctx.fillRect(
0,
height - 18,
width,
18
);
}
else if (style === "gradient") {
const gradient = ctx.createLinearGradient(
0,
0,
width,
height
);
gradient.addColorStop(0, customColor);
gradient.addColorStop(1, "#111827");
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, width, height);
}
else if (style === "bold") {
ctx.fillStyle = "#000000";
ctx.fillRect(0, 0, width, height);
ctx.fillStyle = customColor;
ctx.fillRect(
40,
40,
width - 80,
height - 80
);
}
}
/* -------------------------
GENERATE SINGLE IMAGE
------------------------- */
function createImage(text) {
const size = getImageSize();
const canvas = document.createElement("canvas");
canvas.width = size.width;
canvas.height = size.height;
const ctx = canvas.getContext("2d");
const style =
document.getElementById("style").value;
const font =
document.getElementById("font").value;
const fontSize =
parseInt(
document.getElementById("fontSize").value
);
const alignment =
document.getElementById("alignment").value;
const customColor =
document.getElementById("background").value;
/* Background */
drawBackground(
ctx,
size.width,
size.height,
style,
customColor
);
/* Text color */
if (style === "minimal") {
ctx.fillStyle = "#111111";
} else if (style === "bold") {
ctx.fillStyle = "#ffffff";
} else {
ctx.fillStyle = "#ffffff";
}
/* Font */
let weight = "700";
if (style === "minimal") {
weight = "600";
}
ctx.font =
weight +
" " +
fontSize +
"px " +
font;
ctx.textAlign = alignment;
ctx.textBaseline = "middle";
/* Text position */
let x = size.width / 2;
if (alignment === "left") {
x = 90;
}
if (alignment === "right") {
x = size.width - 90;
}
/* Wrap text */
const maxWidth =
size.width - 180;
const lines =
wrapText(
ctx,
text,
maxWidth
);
const lineHeight =
fontSize * 1.25;
const totalHeight =
lines.length * lineHeight;
let y =
(size.height - totalHeight) / 2;
/* Draw lines */
lines.forEach(line => {
ctx.fillText(
line,
x,
y + lineHeight / 2
);
y += lineHeight;
});
return canvas.toDataURL(
"image/png"
);
}
/* -------------------------
GENERATE ALL IMAGES
------------------------- */
function generateImages() {
const input =
document.getElementById("textInput").value;
const items =
input
.split("\n")
.map(item => item.trim())
.filter(item => item !== "");
const preview =
document.getElementById("preview");
preview.innerHTML = "";
generatedImages = [];
if (items.length === 0) {
document.getElementById("status").textContent =
"Please enter at least one title.";
return;
}
items.forEach((text, index) => {
const image =
createImage(text);
generatedImages.push({
name: text,
data: image
});
const item =
document.createElement("div");
item.className =
"image-item";
item.innerHTML = `
<img src="${image}" alt="${escapeHtml(text)}">
<div class="image-title">
${escapeHtml(text)}
</div>
<button
class="download-one"
onclick="downloadImage(${index})">
Download PNG
</button>
`;
preview.appendChild(item);
});
document.getElementById("status").textContent =
items.length +
" image(s) generated successfully.";
}
/* -------------------------
DOWNLOAD ONE IMAGE
------------------------- */
function downloadImage(index) {
const image =
generatedImages[index];
const link =
document.createElement("a");
link.download =
createFileName(image.name) +
".png";
link.href =
image.data;
link.click();
}
/* -------------------------
DOWNLOAD ALL
------------------------- */
function downloadAll() {
if (generatedImages.length === 0) {
alert(
"Generate some images first."
);
return;
}
generatedImages.forEach(
(image, index) => {
setTimeout(() => {
downloadImage(index);
}, index * 400);
}
);
}
/* -------------------------
FILE NAME
------------------------- */
function createFileName(text) {
return text
.toLowerCase()
.replace(/[^a-z0-9]+/g, "-")
.replace(/^-|-$/g, "")
.substring(0, 60);
}
/* -------------------------
HTML ESCAPE
------------------------- */
function escapeHtml(text) {
return text
.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/"/g, """)
.replace(/'/g, "'");
}
</script>
</body>
</html>
What This Example Can Do
This small application already provides several useful controls.
Font Controls
Users can select:
- Arial
- Georgia
- Verdana
- Trebuchet MS
- Courier New
They can also change the font size.
For example:
20px → 120px
Image Ratio Controls
The tool supports four common formats:
| Ratio | Size | Useful For |
|---|---|---|
| 16:9 | 1200 × 675 | Blog / website |
| 1:1 | 1080 × 1080 | Square posts |
| 4:5 | 1080 × 1350 | Portrait posts |
| 9:16 | 1080 × 1920 | Stories / vertical content |
This makes the same generator useful for different types of content.
Five Simple Design Styles
The example includes five basic styles.
1. Modern
A clean colored background with a subtle decorative circle.
2. Minimal
A white background with a simple colored accent.
3. Dark
A dark background with a colored bottom accent.
4. Gradient
A gradient background combining the selected color with a dark shade.
5. Bold
A strong high-contrast design with a large colored panel.
These styles can later be expanded into much more sophisticated templates.
How the Bulk Generation Works
The user enters:
10 Writing Tips
How to Start a Blog
SEO Basics
Content Marketing
Social Media Tips
The JavaScript splits the text at each new line.
It then creates an image for every line.
The result is:
Image 1 → 10 Writing Tips
Image 2 → How to Start a Blog
Image 3 → SEO Basics
Image 4 → Content Marketing
Image 5 → Social Media Tips
Each image is generated using the Canvas API and converted into a PNG data URL.
That means the browser is creating an actual image file, rather than simply displaying an HTML preview.
How You Can Expand the Tool
This basic version can become a much more powerful application.
You could add:
- Custom logo upload
- Custom background image
- Multiple text fields
- Subtitle support
- Brand colors
- Custom fonts
- Font weight controls
- Text spacing
- Image filters
- Templates
- CSV upload
- Excel upload
- ZIP download
- Drag-and-drop design editor
- AI-generated images
- AI-generated text
- Database storage
- User accounts
For example, a CSV could contain hundreds of titles and the tool could automatically generate hundreds of images.
From HTML Tool to Real Web Application
A simple HTML tool is a good starting point.
But if you want users to access the tool from your website, you can turn it into a proper web application.
For example:
User → Upload CSV → Select Template → Select Font → Select Ratio → Generate → Download ZIP
This is where a simple browser experiment can become a useful online product.
Want to Build Your Own Tool?
If you have an idea for a bulk image generator or another custom online tool, you don’t necessarily need to start with a large application.
Start with the basic workflow, test whether people find it useful, and then add advanced features.
Want to build your own custom web tool?
Contact Glira at:
9150999566
We can help turn your idea into a practical web-based tool.
Try Now
Bulk Image Generator
Create multiple images from a list of titles directly in your browser.
1. Enter Your Text
Enter one title or phrase per line.