/* Complete self-contained CSS */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: Arial, sans-serif;
}
body {
background: #f0f0f0;
padding: 20px;
}
.meme-container {
max-width: 900px;
margin: 0 auto;
background: white;
border-radius: 10px;
box-shadow: 0 0 20px rgba(0,0,0,0.1);
overflow: hidden;
}
/* Header */
.header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 20px;
text-align: center;
}
.header h1 {
margin: 0;
font-size: 24px;
}
/* Main Content */
.main-content {
display: flex;
flex-wrap: wrap;
padding: 20px;
gap: 20px;
}
@media (max-width: 768px) {
.main-content {
flex-direction: column;
}
}
/* Canvas Section */
.canvas-section {
flex: 1;
min-width: 300px;
}
.canvas-container {
background: #f8f8f8;
border: 2px dashed #ddd;
border-radius: 8px;
padding: 20px;
text-align: center;
margin-bottom: 20px;
}
#meme-canvas {
width: 100%;
max-width: 400px;
height: 400px;
background: white;
display: block;
margin: 0 auto;
}
.upload-area {
background: white;
border: 2px dashed #ccc;
border-radius: 8px;
padding: 30px;
text-align: center;
cursor: pointer;
margin-top: 20px;
}
.upload-area:hover {
border-color: #667eea;
background: #f5f3ff;
}
.upload-text {
font-size: 18px;
color: #666;
margin-bottom: 10px;
}
.upload-subtext {
font-size: 14px;
color: #999;
}
/* Controls Section */
.controls-section {
flex: 1;
min-width: 300px;
}
.control-group {
background: #f8f8f8;
border-radius: 8px;
padding: 20px;
margin-bottom: 20px;
}
.control-group h3 {
margin-bottom: 15px;
color: #333;
border-bottom: 2px solid #667eea;
padding-bottom: 5px;
}
.control-row {
display: flex;
align-items: center;
margin-bottom: 15px;
}
.control-label {
width: 120px;
font-weight: bold;
color: #555;
}
select, input[type=”range”] {
flex: 1;
padding: 8px;
border: 1px solid #ddd;
border-radius: 4px;
}
.color-options {
display: flex;
gap: 10px;
flex-wrap: wrap;
}
.color-option {
width: 30px;
height: 30px;
border-radius: 50%;
cursor: pointer;
border: 2px solid transparent;
}
.color-option.active {
border-color: #333;
transform: scale(1.1);
}
textarea {
width: 100%;
height: 100px;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 14px;
resize: vertical;
}
/* Buttons */
.buttons {
display: flex;
gap: 10px;
margin-top: 20px;
}
.btn {
padding: 12px 24px;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 16px;
font-weight: bold;
transition: all 0.3s;
}
.btn-primary {
background: #667eea;
color: white;
flex: 1;
}
.btn-primary:hover {
background: #5a67d8;
transform: translateY(-2px);
}
.btn-secondary {
background: #e2e8f0;
color: #333;
}
.btn-secondary:hover {
background: #cbd5e0;
}
/* Footer */
.footer {
text-align: center;
padding: 20px;
color: #666;
font-size: 14px;
border-top: 1px solid #eee;
}
/* Modal */
.modal {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.5);
z-index: 1000;
justify-content: center;
align-items: center;
}
.modal-content {
background: white;
padding: 30px;
border-radius: 10px;
max-width: 500px;
width: 90%;
max-height: 80vh;
overflow-y: auto;
}
.modal h2 {
margin-bottom: 20px;
color: #333;
}
.modal-close {
position: absolute;
top: 10px;
right: 10px;
background: none;
border: none;
font-size: 24px;
cursor: pointer;
color: #666;
}
/* Toast */
.toast {
position: fixed;
bottom: 20px;
right: 20px;
background: #48bb78;
color: white;
padding: 15px 25px;
border-radius: 5px;
display: none;
z-index: 1001;
}
// Meme Generator Script – Self-contained
(function() {
// Initialize when page loads
document.addEventListener(‘DOMContentLoaded’, function() {
// Get elements
const canvas = document.getElementById(‘meme-canvas’);
const ctx = canvas.getContext(‘2d’);
const textInput = document.getElementById(‘text-input’);
const fontSelect = document.getElementById(‘font-select’);
const colorOptions = document.querySelectorAll(‘.color-option’);
const outlineSlider = document.getElementById(‘outline-slider’);
const outlineValue = document.getElementById(‘outline-value’);
const sizeSlider = document.getElementById(‘size-slider’);
const sizeValue = document.getElementById(‘size-value’);
const fileInput = document.getElementById(‘file-input’);
const uploadArea = document.getElementById(‘upload-area’);
const downloadBtn = document.getElementById(‘download-btn’);
const helpBtn = document.getElementById(‘help-btn’);
const sampleBtn = document.getElementById(‘sample-btn’);
const clearBtn = document.getElementById(‘clear-btn’);
const helpModal = document.getElementById(‘help-modal’);
const toast = document.getElementById(‘toast’);
// State
let currentImage = null;
let currentText = “TOP TEXT\nBOTTOM TEXT”;
let currentFont = “Impact”;
let currentColor = “white”;
let currentOutline = 2;
let currentSize = 36;
// Initialize
function init() {
setupEventListeners();
createSampleImage();
drawMeme();
}
// Setup event listeners
function setupEventListeners() {
// Text input
textInput.addEventListener(‘input’, function() {
currentText = this.value;
drawMeme();
});
// Font selection
fontSelect.addEventListener(‘change’, function() {
currentFont = this.value;
drawMeme();
});
// Color selection
colorOptions.forEach(option => {
option.addEventListener(‘click’, function() {
colorOptions.forEach(opt => opt.classList.remove(‘active’));
this.classList.add(‘active’);
currentColor = this.getAttribute(‘data-color’);
drawMeme();
});
});
// Outline slider
outlineSlider.addEventListener(‘input’, function() {
currentOutline = parseInt(this.value);
outlineValue.textContent = this.value + ‘px’;
drawMeme();
});
// Size slider
sizeSlider.addEventListener(‘input’, function() {
currentSize = parseInt(this.value);
sizeValue.textContent = this.value + ‘px’;
drawMeme();
});
// File upload
uploadArea.addEventListener(‘click’, function() {
fileInput.click();
});
fileInput.addEventListener(‘change’, function(e) {
if (e.target.files[0]) {
loadImage(e.target.files[0]);
}
});
// Drag and drop
uploadArea.addEventListener(‘dragover’, function(e) {
e.preventDefault();
this.style.borderColor = ‘#667eea’;
this.style.background = ‘#f5f3ff’;
});
uploadArea.addEventListener(‘dragleave’, function() {
this.style.borderColor = ‘#ccc’;
this.style.background = ‘white’;
});
uploadArea.addEventListener(‘drop’, function(e) {
e.preventDefault();
this.style.borderColor = ‘#ccc’;
this.style.background = ‘white’;
if (e.dataTransfer.files[0]) {
loadImage(e.dataTransfer.files[0]);
}
});
// Buttons
downloadBtn.addEventListener(‘click’, downloadMeme);
helpBtn.addEventListener(‘click’, function() {
helpModal.style.display = ‘flex’;
});
sampleBtn.addEventListener(‘click’, createSampleImage);
clearBtn.addEventListener(‘click’, function() {
textInput.value = ”;
currentText = ”;
drawMeme();
showToast(‘Text cleared!’);
});
}
// Load image from file
function loadImage(file) {
// Check file size
if (file.size > 5 * 1024 * 1024) {
showToast(‘File too large (max 5MB)’, ‘error’);
return;
}
// Check file type
if (!file.type.match(‘image.*’)) {
showToast(‘Please select an image file’, ‘error’);
return;
}
const reader = new FileReader();
reader.onload = function(e) {
const img = new Image();
img.onload = function() {
currentImage = img;
drawMeme();
showToast(‘Image loaded!’);
};
img.src = e.target.result;
};
reader.readAsDataURL(file);
}
// Create sample image
function createSampleImage() {
// Create a simple gradient image
const tempCanvas = document.createElement(‘canvas’);
tempCanvas.width = 400;
tempCanvas.height = 400;
const tempCtx = tempCanvas.getContext(‘2d’);
// Draw gradient
const gradient = tempCtx.createLinearGradient(0, 0, 400, 400);
gradient.addColorStop(0, ‘#667eea’);
gradient.addColorStop(1, ‘#764ba2’);
tempCtx.fillStyle = gradient;
tempCtx.fillRect(0, 0, 400, 400);
// Add sample text
tempCtx.fillStyle = ‘white’;
tempCtx.font = ‘bold 30px Arial’;
tempCtx.textAlign = ‘center’;
tempCtx.fillText(‘SAMPLE MEME TEMPLATE’, 200, 150);
tempCtx.font = ’20px Arial’;
tempCtx.fillText(‘Add your own text!’, 200, 200);
// Create image from canvas
const img = new Image();
img.onload = function() {
currentImage = img;
drawMeme();
showToast(‘Sample image loaded!’);
};
img.src = tempCanvas.toDataURL();
}
// Draw the meme
function drawMeme() {
// Clear canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Draw background (white)
ctx.fillStyle = ‘white’;
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Draw image if exists
if (currentImage) {
// Calculate dimensions to fit
const scale = Math.min(
canvas.width / currentImage.width,
canvas.height / currentImage.height
);
const width = currentImage.width * scale;
const height = currentImage.height * scale;
const x = (canvas.width – width) / 2;
const y = (canvas.height – height) / 2;
ctx.drawImage(currentImage, x, y, width, height);
}
// Draw text
if (currentText) {
const lines = currentText.split(‘\n’);
const lineHeight = currentSize + 10;
const startY = canvas.height / 2 – ((lines.length – 1) * lineHeight) / 2;
for (let i = 0; i < lines.length; i++) {
if (lines[i].trim()) {
drawTextLine(lines[i], canvas.width / 2, startY + (i * lineHeight));
}
}
}
}
// Draw a single line of text
function drawTextLine(text, x, y) {
ctx.font = `bold ${currentSize}px ${currentFont}`;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
// Draw outline
ctx.strokeStyle = 'black';
ctx.lineWidth = currentOutline;
ctx.lineJoin = 'round';
ctx.strokeText(text, x, y);
// Draw fill
ctx.fillStyle = currentColor;
ctx.fillText(text, x, y);
}
// Download meme
function downloadMeme() {
// Create a higher resolution version
const tempCanvas = document.createElement('canvas');
tempCanvas.width = 1200;
tempCanvas.height = 1200;
const tempCtx = tempCanvas.getContext('2d');
// Scale factor
const scale = tempCanvas.width / canvas.width;
// Draw background
tempCtx.fillStyle = 'white';
tempCtx.fillRect(0, 0, tempCanvas.width, tempCanvas.height);
// Draw image
if (currentImage) {
const imgScale = Math.min(
tempCanvas.width / currentImage.width,
tempCanvas.height / currentImage.height
);
const width = currentImage.width * imgScale;
const height = currentImage.height * imgScale;
const x = (tempCanvas.width – width) / 2;
const y = (tempCanvas.height – height) / 2;
tempCtx.drawImage(currentImage, x, y, width, height);
}
// Draw text (scaled)
if (currentText) {
const lines = currentText.split('\n');
const scaledSize = currentSize * scale;
const lineHeight = scaledSize + (10 * scale);
const startY = tempCanvas.height / 2 – ((lines.length – 1) * lineHeight) / 2;
tempCtx.font = `bold ${scaledSize}px ${currentFont}`;
tempCtx.textAlign = 'center';
tempCtx.textBaseline = 'middle';
tempCtx.strokeStyle = 'black';
tempCtx.lineWidth = currentOutline * scale;
tempCtx.lineJoin = 'round';
tempCtx.fillStyle = currentColor;
for (let i = 0; i < lines.length; i++) {
if (lines[i].trim()) {
const y = startY + (i * lineHeight);
tempCtx.strokeText(lines[i], tempCanvas.width / 2, y);
tempCtx.fillText(lines[i], tempCanvas.width / 2, y);
}
}
}
// Create download link
const link = document.createElement('a');
link.download = 'meme-' + Date.now() + '.png';
link.href = tempCanvas.toDataURL('image/png');
// Trigger download
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
showToast('Meme downloaded!');
}
// Show toast message
function showToast(message, type = 'success') {
toast.textContent = message;
toast.style.display = 'block';
toast.style.background = type === 'error' ? '#f56565' : '#48bb78';
setTimeout(function() {
toast.style.display = 'none';
}, 3000);
}
// Global functions for modal
window.closeModal = function() {
helpModal.style.display = 'none';
};
// Close modal when clicking outside
helpModal.addEventListener('click', function(e) {
if (e.target === helpModal) {
closeModal();
}
});
// Initialize the app
init();
});
})();
🖼️ Meme Generator
📤 Click to upload image
or drag and drop (JPG, PNG, GIF up to 5MB)
✏️ Text Editor
Text:
Font:
Impact
Arial Black
Comic Sans
Georgia
Times New Roman
Color:
Outline:
2px
Size:
36px
