Skip to content

Instantly share code, notes, and snippets.

@fedir
Last active May 9, 2025 05:17
Show Gist options
  • Save fedir/1d4271814e33fb8fdba2e4bf7fc81168 to your computer and use it in GitHub Desktop.
Save fedir/1d4271814e33fb8fdba2e4bf7fc81168 to your computer and use it in GitHub Desktop.
Simple one-page HTML/JS QR Code Generator using qrcodejs // Demo: https://www.fedir.fr/tools/qrcode.html // Made with Claude Code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>QR Code Generator</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
background-color: #f7f7f7;
}
h1 {
color: #333;
text-align: center;
}
.container {
background-color: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.form-group {
margin-bottom: 20px;
}
textarea {
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
min-height: 100px;
margin-bottom: 10px;
font-family: inherit;
box-sizing: border-box;
}
button {
background-color: #4CAF50;
color: white;
border: none;
padding: 10px 15px;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
}
button:hover {
background-color: #45a049;
}
.result {
margin-top: 20px;
text-align: center;
display: none;
max-width: 100%;
}
.qr-code {
margin: 20px auto;
text-align: center;
max-width: 100%;
overflow: hidden;
display: flex;
justify-content: center;
align-items: center;
}
.qr-code canvas, .qr-code img {
max-width: 100%;
height: auto;
display: block;
margin: 0 auto;
}
.error {
color: red;
margin-top: 10px;
display: none;
}
.download-btn {
margin-top: 15px;
background-color: #2196F3;
display: none; /* Hidden */
}
.controls {
display: flex;
flex-direction: column;
gap: 15px;
margin-top: 15px;
}
.size-control {
display: flex;
align-items: center;
}
.size-control label {
margin-right: 10px;
}
/* Responsive adjustments */
@media (min-width: 480px) {
.controls {
flex-direction: row;
justify-content: space-between;
}
}
</style>
</head>
<body>
<div class="container">
<h1>QR Code Generator</h1>
<div class="form-group">
<label for="text"><strong>Enter text for QR code:</strong></label>
<textarea id="text" placeholder="Enter URL, text, or contact information here..."></textarea>
<div class="controls">
<div class="size-control">
<label for="size">Size:</label>
<select id="size">
<option value="128">Small (128×128)</option>
<option value="256" selected>Medium (256×256)</option>
<option value="512">Large (512×512)</option>
<option value="800">Extra Large (800×800)</option>
</select>
</div>
<div>
<button id="generate-btn" onclick="generateQRCode()">Generate QR Code</button>
</div>
</div>
</div>
<div id="error-message" class="error"></div>
<div id="result" class="result">
<h2>Your QR Code:</h2>
<div id="qrcode" class="qr-code"></div>
<p>Scan this QR code with a QR code reader to access the content.</p>
</div>
</div>
<!-- qrcodejs library -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js"></script>
<script>
// QR code object
let qrcode = null;
// Function to validate input
function validateInput(text) {
if (!text || text.trim() === '') {
return "Please enter some text to generate a QR code.";
}
if (text.length > 1000) {
return "Text is too long. Please limit to 1000 characters.";
}
return "";
}
// Function to generate QR code
function generateQRCode() {
// Get the input text and size
const textInput = document.getElementById('text').value;
const size = parseInt(document.getElementById('size').value);
const errorElement = document.getElementById('error-message');
const resultElement = document.getElementById('result');
// Validate input
const error = validateInput(textInput);
if (error) {
errorElement.textContent = error;
errorElement.style.display = 'block';
resultElement.style.display = 'none';
return;
}
// Clear any previous errors
errorElement.style.display = 'none';
// Clear previous QR code
const qrcodeElement = document.getElementById('qrcode');
qrcodeElement.innerHTML = '';
// Calculate appropriate size based on container width
const containerWidth = document.querySelector('.container').offsetWidth - 40; // Subtract padding
const actualSize = Math.min(size, containerWidth);
// Generate new QR code
qrcode = new QRCode(qrcodeElement, {
text: textInput,
width: actualSize,
height: actualSize,
colorDark: "#000000",
colorLight: "#ffffff",
correctLevel: QRCode.CorrectLevel.H
});
// Center the QR code if it's smaller than the container
if (actualSize < containerWidth) {
// Add additional styling to ensure proper centering
setTimeout(() => {
const qrCanvas = qrcodeElement.querySelector('canvas');
const qrImg = qrcodeElement.querySelector('img');
if (qrCanvas) {
qrCanvas.style.margin = '0 auto';
}
if (qrImg) {
qrImg.style.margin = '0 auto';
}
}, 100); // Small delay to ensure elements are rendered
}
// Show the result
resultElement.style.display = 'block';
}
// Function to download QR code as image
function downloadQRCode() {
if (!qrcode) return;
// Get the canvas element
const canvas = document.querySelector('#qrcode canvas');
if (!canvas) return;
// Get the selected size
const selectedSize = parseInt(document.getElementById('size').value);
// If we want to download at the original (full) size, we need to recreate the QR code
// at the original size on a temporary canvas
const tempCanvas = document.createElement('canvas');
tempCanvas.width = selectedSize;
tempCanvas.height = selectedSize;
const ctx = tempCanvas.getContext('2d');
// Fill with white background
ctx.fillStyle = '#ffffff';
ctx.fillRect(0, 0, selectedSize, selectedSize);
// Draw the QR code at full size
// Get the QR code image
const img = document.querySelector('#qrcode img');
if (img) {
// Create a new QRCode instance at full size
const tempDiv = document.createElement('div');
tempDiv.style.display = 'none';
document.body.appendChild(tempDiv);
const tempQR = new QRCode(tempDiv, {
text: document.getElementById('text').value,
width: selectedSize,
height: selectedSize,
colorDark: "#000000",
colorLight: "#ffffff",
correctLevel: QRCode.CorrectLevel.H
});
// Get the canvas from the temporary QR code
const fullSizeCanvas = tempDiv.querySelector('canvas');
if (fullSizeCanvas) {
// Use the full-size canvas for the download
const dataURL = fullSizeCanvas.toDataURL('image/png');
// Create download link
const link = document.createElement('a');
link.download = 'qrcode.png';
link.href = dataURL;
// Trigger download
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
// Clean up
document.body.removeChild(tempDiv);
} else {
// Fallback to the displayed canvas if there's an issue
const dataURL = canvas.toDataURL('image/png');
// Create download link
const link = document.createElement('a');
link.download = 'qrcode.png';
link.href = dataURL;
// Trigger download
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
}
// Add event listener for Enter key
document.getElementById('text').addEventListener('keypress', function(event) {
if (event.key === 'Enter' && !event.shiftKey) {
event.preventDefault();
generateQRCode();
}
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment