Skip to main content

Custom branded QR code with specific colors

Create branded QR codes that match your company’s visual identity using the color customization features.
const [fgColor, setFgColor] = useState('#0f172a');
const [bgColor, setBgColor] = useState('#ffffff');

// Users can customize through color pickers (line 180-190)
<input 
  type="color" 
  value={fgColor} 
  onChange={(e) => setFgColor(e.target.value)} 
/>
The component displays the hex color value next to each picker for precise color matching (line 181, 188).

Color application in QR generation

Colors are applied directly to the QRCodeSVG component:
<QRCodeSVG
  value={qrValue}
  size={size}
  level={logoUrl ? 'H' : level}
  bgColor={bgColor === 'transparent' ? '#ffffff' : bgColor}
  fgColor={fgColor}
  includeMargin={true}
/>
The component automatically handles transparent backgrounds by falling back to white to ensure proper QR code rendering (line 234).

QR code with logo overlay

Add a centered logo to your QR codes using the imageSettings prop. The component handles logo upload and proper QR code excavation.
1

Upload logo image

The component uses FileReader API to handle image uploads (line 77-84):
const [logoUrl, setLogoUrl] = useState('');

const handleLogoUpload = (e) => {
  const file = e.target.files[0];
  if (file) {
    const reader = new FileReader();
    reader.onload = (event) => setLogoUrl(event.target.result);
    reader.readAsDataURL(file);
  }
};
2

Configure image settings

When a logo is present, the component automatically configures proper sizing and excavation (line 237-244):
imageSettings={logoUrl ? {
  src: logoUrl,
  x: undefined,
  y: undefined,
  height: size * 0.22, // 22% of QR size
  width: size * 0.22,
  excavate: true, // Cuts away QR behind logo
} : undefined}
3

Force high error correction

The component automatically sets error correction to level H when a logo is present:
level={logoUrl ? 'H' : level}
This ensures the QR code remains scannable even with 30% covered by the logo.

Complete logo implementation

// Upload button with hidden file input (line 197-201)
<label className="btn btn-secondary upload-btn">
  <ImageIcon size={16} /> Subir Imagen
  <input 
    type="file" 
    accept="image/*" 
    onChange={handleLogoUpload} 
    style={{ display: 'none' }} 
  />
</label>

// Remove logo button (line 201-205)
{logoUrl && (
  <button 
    className="btn-icon" 
    onClick={() => setLogoUrl('')} 
    title="Quitar logo"
  >
    <Trash2 size={16} color="var(--error-color)" />
  </button>
)}
Logo images should be square or nearly square for best results. The component sizes them to 22% of the QR code size (line 241-242).

High error correction for damaged QR codes

Understand and leverage the four error correction levels to create QR codes that work even when partially damaged.
The component offers four levels through a select dropdown (line 211-216):
const [level, setLevel] = useState('H');

<select value={level} onChange={(e) => setLevel(e.target.value)}>
  <option value="L">Normal</option>      // ~7% damage tolerance
  <option value="M">Buena</option>       // ~15% damage tolerance
  <option value="Q">Alta</option>        // ~25% damage tolerance
  <option value="H">Máxima (Logo)</option> // ~30% damage tolerance
</select>

Complex vCard with all fields populated

Create comprehensive contact cards with all available vCard 3.0 fields.
// Full vCard state (line 12)
const [vcardData, setVcardData] = useState({ 
  firstName: '', 
  lastName: '', 
  phone: '', 
  email: '', 
  company: '' 
});

// vCard generation with all fields (line 35-36)
const vcard = `BEGIN:VCARD
VERSION:3.0
N:${vcardData.lastName};${vcardData.firstName};;;
FN:${vcardData.firstName} ${vcardData.lastName}
ORG:${vcardData.company}
TEL;TYPE=CELL:${vcardData.phone}
EMAIL:${vcardData.email}
END:VCARD`;

Complete contact card example

firstName: "María"
lastName: "García"
phone: "+34 612 345 678"
email: "[email protected]"
company: "TechCorp Solutions"
The vCard format follows the VERSION 3.0 specification with proper field structure. The phone type is set to CELL for mobile compatibility.

SVG export for print materials

Export QR codes as scalable vector graphics (SVG) for unlimited scaling without quality loss.
1

Component uses QRCodeSVG for display

The visible QR code is rendered using QRCodeSVG from qrcode.react (line 230-245):
<QRCodeSVG
  value={qrValue}
  size={size}
  level={logoUrl ? 'H' : level}
  bgColor={bgColor === 'transparent' ? '#ffffff' : bgColor}
  fgColor={fgColor}
  includeMargin={true}
  imageSettings={logoUrl ? {
    src: logoUrl,
    height: size * 0.22,
    width: size * 0.22,
    excavate: true,
  } : undefined}
/>
2

SVG download handler serializes the element

The download function extracts and serializes the SVG (line 60-75):
const handleDownloadSVG = () => {
  const svg = qrRef.current?.querySelector('svg');
  if (!svg) return;

  const svgData = new XMLSerializer().serializeToString(svg);
  const blob = new Blob([svgData], { 
    type: "image/svg+xml;charset=utf-8" 
  });
  const url = URL.createObjectURL(blob);

  let downloadLink = document.createElement("a");
  downloadLink.href = url;
  downloadLink.download = "qr-premium-vector.svg";
  document.body.appendChild(downloadLink);
  downloadLink.click();
  document.body.removeChild(downloadLink);
  URL.revokeObjectURL(url);
};
3

Click the SVG button

<button 
  className="btn btn-secondary" 
  onClick={handleDownloadSVG} 
  title="Vectores infinitamente escalables"
>
  SVG (Vector)
</button>
The file is saved as qr-premium-vector.svg with all styling preserved.
SVG exports are perfect for print materials because they scale to any size without pixelation. Use SVG for banners, billboards, and professional print jobs.

Multiple format exports workflow

Implement a workflow that exports QR codes in both PNG and SVG formats for different use cases.
// Both export functions are available in the component
const handleDownloadPNG = () => { /* PNG export logic */ };
const handleDownloadSVG = () => { /* SVG export logic */ };

// UI provides both options (line 262-270)
<div className="download-section">
  <div className="download-group">
    <button className="btn btn-primary" onClick={handleDownloadPNG}>
      <Download size={18} /> PNG
    </button>
    <button 
      className="btn btn-secondary" 
      onClick={handleDownloadSVG} 
      title="Vectores infinitamente escalables"
    >
      SVG (Vector)
    </button>
  </div>
</div>

PNG for digital, SVG for print

  1. PNG exports at 560x560px (2x resolution) are ideal for:
    • Website integration
    • Social media posts
    • Digital documents and presentations
    • Mobile app assets
  2. SVG exports are ideal for:
    • Print materials (business cards, flyers, posters)
    • Large format printing (banners, billboards)
    • Professional branding materials
    • Situations requiring infinite scaling
The component renders both a visible SVG (for display and SVG export) and a hidden high-resolution canvas (for PNG export) to provide optimal quality for each format.

Build docs developers (and LLMs) love