Hi All,
Demo here: QR Code generator
Note that the QR Code color, the QR code background-color, the QR code file type (image as Jpeg or PNG) and the QR code size are customizable.
It should also be responsive ().
Below is the full code. To be inserted in a custom code block
Made on top of qrcode.js library
Just Copy-Paste it
<html>
<head>
<style>
:root {
--container-bg-color: #ffffff;
--container-border-radius: 8px;
--box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.1);
--title-font-size: 20px;
--title-color: #333;
--input-font-size: 16px;
--input-border-color: #ccc;
--input-focus-border-color: #007bff;
--input-border-radius: 4px;
--button-bg-color: #007BFF;
--button-hover-bg-color: #0056b3;
--button-text-color: #fff;
--button-font-size: 16px;
--button-border-radius: 6px;
--label-font-size: 14px;
--label-color: #333;
--customization-label-font-size: 16px;
--customization-label-color: #333;
--color-group-gap: 16px;
--display-qr-size: 150px;
--download-qr-size: 300;
--placeholder-color: #aaaaaa;
--placeholder-font-size: 15px;
--placeholder-font-weight: 400;
}
.qr-generator-wrapper {
display: flex;
justify-content: center;
align-items: flex-start;
padding: 20px;
margin: 0 auto;
max-width: 320px;
}
.qr-generator-container {
text-align: left;
padding: 20px;
width: 100%;
background-color: var(--container-bg-color);
box-shadow: var(--box-shadow);
border-radius: var(--container-border-radius);
display: flex;
flex-direction: column;
gap: 20px;
}
.qr-generator-container h1 {
font-size: var(--title-font-size);
margin-bottom: 20px;
color: var(--title-color);
order: -1;
}
.qr-code-section {
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
order: 2;
}
.controls-section {
width: 100%;
order: 1;
}
.input-group {
display: flex;
gap: 8px;
margin-bottom: 20px;
}
.input-group input[type="text"] {
flex: 1;
padding: 10px;
font-size: var(--input-font-size);
border: 1px solid var(--input-border-color);
border-radius: var(--input-border-radius);
outline: none;
transition: border-color 0.2s ease;
}
.input-group input[type="text"]:focus {
border-color: var(--input-focus-border-color);
}
.customization-label {
font-size: var(--customization-label-font-size);
color: var(--customization-label-color);
margin-bottom: 10px;
font-weight: 500;
text-align: left;
}
.color-group {
display: flex;
flex-direction: column;
gap: var(--color-group-gap);
margin-bottom: 20px;
}
.color-group label {
display: flex;
flex-direction: column;
font-size: var(--label-font-size);
font-weight: 500;
color: var(--label-color);
}
.color-group input[type="color"],
.color-group input[type="number"],
.color-group select {
width: 100%;
height: 40px;
border: 1px solid var(--input-border-color);
border-radius: var(--input-border-radius);
padding: 8px;
font-size: var(--input-font-size);
outline: none;
transition: border-color 0.2s ease;
}
#qrcode {
margin-top: 20px;
width: var(--display-qr-size);
height: var(--display-qr-size);
position: relative;
display: inline-block;
}
.placeholder-text {
color: var(--placeholder-color);
font-size: var(--placeholder-font-size);
font-weight: var(--placeholder-font-weight);
margin-top: 20px;
display: block;
text-align: center;
}
.message {
margin-top: 10px;
color: green;
display: none;
font-size: 14px;
font-weight: 500;
text-align: center;
}
.copy-button {
background-color: #d3e8ff;
border: 1px solid #d3e8ff;
border-radius: 6px;
margin-top: 10px;
padding: 4px 8px;
display: none;
transition: background-color 0.4s ease;
}
.copy-button:hover {
background-color: #007bff;
color: #fff;
}
.button-container {
display: flex;
justify-content: center;
align-items: center;
gap: 10px;
margin-top: 20px;
width: 100%;
}
.generate-button {
background-color: var(--button-bg-color);
color: var(--button-text-color);
font-size: var(--button-font-size);
border-radius: var(--button-border-radius);
border: none;
padding: 10px 20px;
cursor: pointer;
transition: all 0.3s ease;
width: 100%;
}
.generate-button:disabled {
background-color: #cccccc !important;
cursor: not-allowed;
opacity: 0.7;
}
.generate-button:not(:disabled):hover {
background-color: var(--button-hover-bg-color);
}
.loading-spinner {
border: 4px solid #f3f3f3;
border-top: 4px solid var(--button-bg-color);
border-radius: 50%;
width: 20px;
height: 20px;
animation: spin 0.8s linear infinite;
display: none;
margin-left: 10px;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.download-button {
background-color: var(--button-bg-color);
color: var(--button-text-color);
font-size: 14px;
font-weight: 500;
border-radius: var(--button-border-radius);
border: none;
padding: 6px 12px;
cursor: pointer;
transition: background-color 0.3s;
margin-top: 1px;
display: none;
width: 100%;
}
.download-button:hover {
background-color: var(--button-hover-bg-color);
}
/* Desktop styles */
@media (min-width: 768px) {
.qr-generator-wrapper {
max-width: 600px;
}
.qr-generator-container {
display: grid;
grid-template-columns: auto 1fr;
}
.qr-code-section {
width: var(--display-qr-size);
order: 0;
}
.controls-section {
order: 0;
}
.color-group {
display: flex;
flex-direction: row;
}
.generate-button,
.download-button {
width: auto;
}
.placeholder-text {
margin-top: 80px;
}
}
@media (min-width: 1024px) {
.qr-generator-wrapper {
max-width: 780px;
}
}
</style>
</head>
<body>
<div class="qr-generator-wrapper">
<div class="qr-generator-container">
<div class="qr-code-section">
<span class="placeholder-text" id="placeholder-text">The QR code will appear here.</span>
<div id="qrcode"></div>
<div class="button-container">
<button id="download-button" class="download-button" onclick="downloadQRCode()">Instant Download</button>
</div>
<div class="message" id="copy-message">Downloaded!</div>
</div>
<div class="controls-section">
<h1>QR Code Generator</h1>
<div class="input-group">
<input type="text" id="text-input" placeholder="Enter the desired URL" oninput="validateInput()">
</div>
<div class="customization-label">Customization:</div>
<div class="color-group">
<label>
QR Code Color
<input type="color" id="qr-color" value="#000000">
</label>
<label>
Background Color
<input type="color" id="bg-color" value="#ffffff">
</label>
<label>
QR Code Size (px)
<input type="number" id="qr-size" value="300" min="100" max="1600">
</label>
<label>
Download Format
<select id="qr-format">
<option value="jpeg">JPEG</option>
<option value="png">PNG</option>
</select>
</label>
</div>
<button id="generate-button" class="generate-button" onclick="handleGenerateQRCode()" disabled>Generate</button>
<div class="loading-spinner" id="loading-spinner"></div>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js"></script>
<script>
let isFirstGeneration = true;
function validateInput() {
const input = document.getElementById('text-input');
const generateButton = document.getElementById('generate-button');
generateButton.disabled = !input.value.trim();
}
document.addEventListener('DOMContentLoaded', validateInput);
function handleGenerateQRCode() {
const generateButton = document.getElementById("generate-button");
const loadingSpinner = document.getElementById("loading-spinner");
const downloadButton = document.getElementById("download-button");
generateButton.disabled = true;
loadingSpinner.style.display = "inline-block";
if (isFirstGeneration) {
generateButton.textContent = "Re-Generate";
isFirstGeneration = false;
}
setTimeout(() => {
generateQRCode();
validateInput(); // Re-validate input after generation
loadingSpinner.style.display = "none";
downloadButton.style.display = "block";
}, 1000);
}
function generateQRCode() {
const input = document.getElementById("text-input").value;
const qrCodeContainer = document.getElementById("qrcode");
const qrColor = document.getElementById("qr-color").value;
const bgColor = document.getElementById("bg-color").value;
// Clear previous QR code
qrCodeContainer.innerHTML = "";
const qrcode = new QRCode(qrCodeContainer, {
text: input,
width: 150,
height: 150,
colorDark: qrColor,
colorLight: bgColor,
});
const placeholderText = document.getElementById("placeholder-text");
placeholderText.style.display = "none";
}
function downloadQRCode() {
const qrCodeContainer = document.getElementById("qrcode");
const qrCodeCanvas = qrCodeContainer.querySelector("canvas");
const qrSize = parseInt(document.getElementById("qr-size").value) || 300;
const format = document.getElementById("qr-format").value;
if (!qrCodeCanvas) {
alert("Please generate a QR code before downloading.");
return;
}
const downloadQRCodeContainer = document.createElement("div");
const downloadQRCode = new QRCode(downloadQRCodeContainer, {
text: document.getElementById("text-input").value,
width: qrSize,
height: qrSize,
colorDark: document.getElementById("qr-color").value,
colorLight: document.getElementById("bg-color").value,
});
const downloadCanvas = downloadQRCodeContainer.querySelector("canvas");
if (downloadCanvas) {
const tempCanvas = document.createElement("canvas");
const ctx = tempCanvas.getContext("2d");
tempCanvas.width = qrSize;
tempCanvas.height = qrSize;
// Fill background (important for JPEG format)
ctx.fillStyle = document.getElementById("bg-color").value;
ctx.fillRect(0, 0, qrSize, qrSize);
ctx.drawImage(downloadCanvas, 0, 0, qrSize, qrSize);
const link = document.createElement("a");
const mimeType = format === 'jpeg' ? 'image/jpeg' : 'image/png';
const fileExtension = format === 'jpeg' ? 'jpg' : 'png';
const dataURL = format === 'jpeg'
? tempCanvas.toDataURL(mimeType, 0.9)
: tempCanvas.toDataURL(mimeType);
link.href = dataURL;
link.download = `qrcode.${fileExtension}`;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
tempCanvas.remove();
downloadQRCodeContainer.remove();
}
const copyMessage = document.getElementById("copy-message");
copyMessage.style.display = "block";
setTimeout(() => {
copyMessage.style.display = "none";
}, 3000);
}
</script>
</body>
</html>