DevToolBoxฟรี
บล็อก

ฝังรูปภาพ Base64 ใน HTML, CSS & อีเมล: คู่มือฉบับสมบูรณ์

6 นาทีในการอ่านโดย DevToolBox

Embedding images directly into HTML, CSS, and email using Base64 data URIs eliminates extra HTTP requests and simplifies asset management. This complete guide covers everything from the data URI syntax to real-world use cases, performance trade-offs, and conversion methods across multiple languages and tools.

Try our Base64 Encoder/Decoder tool →

1. What Is a Data URI?

A data URI (Uniform Resource Identifier) allows you to embed file content directly inside a document using a special URL scheme. Instead of pointing to an external file, the data is encoded inline — most commonly using Base64.

The general syntax is:

data:[<mediatype>][;base64],<data>

# Examples:
data:image/png;base64,iVBORw0KGgo...
data:image/svg+xml;base64,PHN2ZyB4...
data:image/jpeg;base64,/9j/4AAQSk...
data:text/html;base64,PGgxPkhlbGx...
data:text/plain;charset=utf-8,Hello%20World

Each component serves a specific purpose:

  • data: — The URI scheme identifier
  • [mediatype] — The MIME type (e.g., image/png, image/svg+xml, text/html)
  • ;base64 — Indicates the data is Base64-encoded (omit for plain text/percent-encoded data)
  • ,data — The actual encoded content

Data URIs are defined in RFC 2397 and are supported by all modern browsers. They work anywhere a URL is expected: src attributes, url() in CSS, href attributes, and more.

2. HTML img Tag: Embedding Base64 Images

The most common use of Base64 image embedding is within the HTML <img> tag. Instead of referencing an external file, you place the entire encoded image in the src attribute:

<!-- Basic Base64 image in HTML -->
<img
  src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAB
       CAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII="
  alt="1x1 red pixel"
  width="100"
  height="100"
/>

A real-world example with a tiny 1x1 transparent pixel (commonly used for tracking or layout):

<!-- 1x1 transparent pixel — commonly used for tracking -->
<img
  src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"
  alt=""
  width="1"
  height="1"
/>

<!-- 1x1 transparent PNG -->
<img
  src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg=="
  alt=""
/>

You can also use Base64 images in <picture> elements, <source> tags, and <input type="image"> — anywhere that accepts a src URL.

Tip: Always include the alt attribute for accessibility, even for decorative images (use alt="" for decorative ones).

3. CSS background-image: Embedding Base64 in Stylesheets

Base64 data URIs work inside the CSS url() function, making them ideal for background images, icons, and decorative elements:

/* PNG background image */
.notification-badge {
  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEU...);
  background-size: 16px 16px;
  background-repeat: no-repeat;
  width: 16px;
  height: 16px;
}

/* Multiple Base64 backgrounds */
.decorated-box {
  background-image:
    url(data:image/png;base64,iVBORw0KG...),  /* top-left corner */
    url(data:image/png;base64,iVBORw0KG...);   /* bottom-right corner */
  background-position: top left, bottom right;
  background-repeat: no-repeat;
}

SVG images are particularly well-suited for CSS embedding because they are typically small, scalable, and can be further optimized:

/* SVG as Base64 in CSS */
.arrow-icon {
  background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiI+PHBhdGggZD0iTTQgNmw0IDQgNC00IiBmaWxsPSJub25lIiBzdHJva2U9IiMzMzMiIHN0cm9rZS13aWR0aD0iMiIvPjwvc3ZnPg==);
}

/* SVG as URL-encoded in CSS (often smaller) */
.arrow-icon-alt {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Cpath d='M4 6l4 4 4-4' fill='none' stroke='%23333' stroke-width='2'/%3E%3C/svg%3E");
}

For SVG in CSS, you have two encoding options:

  • Base64: url(data:image/svg+xml;base64,...) — Universal, works in all browsers
  • URL-encoded: url("data:image/svg+xml,%3Csvg...") — Smaller output, no Base64 overhead, but requires careful escaping of special characters

Tip: For CSS, prefer URL-encoding SVGs over Base64 when possible — the output is smaller since SVG is already text-based and does not need binary-to-text conversion.

4. HTML Email: Why Base64 Is Essential

Email is one of the most important use cases for Base64 image embedding. Email clients have severe limitations compared to web browsers:

  • Many email clients block external images by default (Gmail, Outlook, Yahoo)
  • CSS background-image is not supported in most email clients
  • External image references require the user to "load images" manually
  • Corporate firewalls may block external image requests

There are two primary approaches for embedding images in email:

Approach A: Inline Base64 Data URI

You can embed the image directly in the src attribute, just like in HTML:

<!-- Data URI in email (limited client support) -->
<table>
  <tr>
    <td>
      <img
        src="data:image/png;base64,iVBORw0KGgoAAAANSUhEU..."
        alt="Company Logo"
        width="200"
        height="50"
        style="display: block;"
      />
    </td>
  </tr>
</table>

Support: Works in Apple Mail, Thunderbird, and some webmail clients. Does NOT work in Gmail (Gmail strips data URIs). Outlook support is inconsistent.

Approach B: CID (Content-ID) Embedding

The more widely supported approach uses MIME multipart messages with Content-ID references:

// Node.js with nodemailer — CID embedding
const nodemailer = require('nodemailer');

await transporter.sendMail({
  from: 'noreply@company.com',
  to: 'user@example.com',
  subject: 'Welcome!',
  html: `
    <h1>Welcome to Our Service</h1>
    <img src="cid:company-logo" alt="Company Logo" width="200" />
    <p>Thank you for signing up!</p>
  `,
  attachments: [
    {
      filename: 'logo.png',
      path: './assets/logo.png',
      cid: 'company-logo',  // Referenced in <img src="cid:company-logo">
    },
  ],
});

CID embedding is supported by virtually all email clients including Gmail, Outlook, Apple Mail, and Thunderbird. This is the recommended approach for production email.

Comparison:

MethodGmailOutlookApple MailThunderbird
Data URINoPartialYesYes
CIDYesYesYesYes
External URLYes*Yes*YesYes

* Blocked by default; requires user to "load images"

5. Converting Images to Base64

There are multiple ways to convert images to Base64 across different platforms and languages:

Command Line (Linux/macOS)

# Using base64 command (Linux/macOS)
base64 < image.png | tr -d '\n'

# Using openssl
openssl base64 -in image.png -out image.b64

# Full data URI with MIME type
echo -n "data:image/png;base64,$(base64 < image.png | tr -d '\n')"

# Pipe to clipboard (macOS)
echo -n "data:image/png;base64,$(base64 < image.png | tr -d '\n')" | pbcopy

# Decode Base64 back to image
base64 --decode < image.b64 > decoded.png

Command Line (Windows PowerShell)

# PowerShell: Convert image to Base64
$bytes = [System.IO.File]::ReadAllBytes("image.png")
$base64 = [Convert]::ToBase64String($bytes)
$dataUri = "data:image/png;base64,$base64"

# Copy to clipboard
$dataUri | Set-Clipboard

# Decode back to file
$bytes = [Convert]::FromBase64String($base64)
[System.IO.File]::WriteAllBytes("decoded.png", $bytes)

JavaScript (Browser)

Use the FileReader API to convert files selected via an <input> element:

// Browser: FileReader API
const input = document.querySelector('input[type="file"]');

input.addEventListener('change', (event) => {
  const file = event.target.files[0];
  const reader = new FileReader();

  reader.onload = () => {
    const dataUri = reader.result; // "data:image/png;base64,iVBOR..."
    console.log(dataUri);

    // Use it directly
    document.getElementById('preview').src = dataUri;

    // Extract just the Base64 part
    const base64Only = dataUri.split(',')[1];
  };

  reader.readAsDataURL(file);
});

JavaScript (Canvas — Cross-Origin Images)

For images already loaded in the DOM, use the Canvas API:

// Canvas API: Convert a loaded image to Base64
function imageToBase64(imgElement, format = 'image/png', quality = 0.92) {
  const canvas = document.createElement('canvas');
  canvas.width = imgElement.naturalWidth;
  canvas.height = imgElement.naturalHeight;

  const ctx = canvas.getContext('2d');
  ctx.drawImage(imgElement, 0, 0);

  // Returns full data URI
  return canvas.toDataURL(format, quality);
}

// Usage
const img = document.querySelector('#my-image');
const dataUri = imageToBase64(img, 'image/jpeg', 0.8);

// For WebP (smaller output)
const webpUri = imageToBase64(img, 'image/webp', 0.8);

JavaScript (Node.js)

// Node.js: Convert image file to Base64
const fs = require('fs');
const path = require('path');

function imageToDataUri(filePath) {
  const absolutePath = path.resolve(filePath);
  const ext = path.extname(filePath).slice(1);
  const mimeTypes = {
    png: 'image/png',
    jpg: 'image/jpeg',
    jpeg: 'image/jpeg',
    gif: 'image/gif',
    svg: 'image/svg+xml',
    webp: 'image/webp',
    ico: 'image/x-icon',
  };
  const mime = mimeTypes[ext] || 'application/octet-stream';
  const base64 = fs.readFileSync(absolutePath).toString('base64');
  return `data:${mime};base64,${base64}`;
}

console.log(imageToDataUri('icon.png'));
// → data:image/png;base64,iVBORw0KGgoAAAAN...

Python

import base64
import mimetypes

def image_to_data_uri(file_path: str) -> str:
    """Convert an image file to a Base64 data URI."""
    mime_type, _ = mimetypes.guess_type(file_path)
    if mime_type is None:
        mime_type = 'application/octet-stream'

    with open(file_path, 'rb') as f:
        encoded = base64.b64encode(f.read()).decode('utf-8')

    return f'data:{mime_type};base64,{encoded}'

# Usage
data_uri = image_to_data_uri('logo.png')
print(data_uri[:80] + '...')
# → data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA...

# Decode back to file
def data_uri_to_file(data_uri: str, output_path: str):
    """Convert a data URI back to a file."""
    header, data = data_uri.split(',', 1)
    binary = base64.b64decode(data)
    with open(output_path, 'wb') as f:
        f.write(binary)

data_uri_to_file(data_uri, 'output.png')

Convert images to Base64 instantly with our tool →

6. Supported Image Formats

Data URIs support any MIME type, but here are the most commonly used image formats with their trade-offs:

FormatMIME TypeTransparencyAnimationBest For
PNGimage/pngYesNoIcons, screenshots, UI elements
JPEGimage/jpegNoNoPhotos (not ideal for Base64 due to size)
SVGimage/svg+xmlYesYesIcons, logos, illustrations
GIFimage/gifYesYesSimple animations, tiny icons
WebPimage/webpYesYesModern replacement for PNG/JPEG
ICOimage/x-iconYesNoFavicons (legacy)

7. Size Impact: The 33% Overhead

Base64 encoding converts every 3 bytes of binary data into 4 ASCII characters. This means the encoded output is always approximately 33% larger than the original file:

# The math behind 33% overhead:
# Base64 encodes 3 bytes → 4 characters (6 bits each)
# Ratio: 4/3 = 1.333... → ~33% increase

# Example:
# Original:  3 bytes  → [0x48, 0x65, 0x6C]
# Binary:    01001000 01100101 01101100
# Split 6:   010010 000110 010101 101100
# Base64:    S      G      V      s
# Result:    4 characters for 3 bytes

Here is a real-world comparison:

Original SizeBase64 SizeOverheadWorth It?
1 KB1.37 KB+370 BYes — saves HTTP request
5 KB6.67 KB+1.67 KBMarginal — depends on context
10 KB13.3 KB+3.3 KBUsually no
50 KB66.7 KB+16.7 KBNo — use external file

When it is still worth it: The 33% overhead is offset when it eliminates an HTTP request. Each HTTP request adds latency (DNS lookup, TCP handshake, TLS negotiation). For images under ~5KB, the saved request is almost always worth the extra bytes. Above 10KB, use external files.

Good news about gzip: Base64 data compresses reasonably well with gzip/brotli. The actual transfer size increase over the wire is typically 10-15% rather than the full 33%, since the server compresses the response.

8. Performance: When to Use vs When Not to Use

Base64 embedding is a performance trade-off. Here is a definitive guide:

Use Base64 When:

  • Small images under 5KB (icons, logos, simple graphics)
  • Critical above-the-fold images that must render without waiting for additional requests
  • Single-file distribution (HTML emails, portable documents, self-contained widgets)
  • Reducing HTTP/1.1 connection overhead (less relevant with HTTP/2 multiplexing)
  • Inlining in CSS to avoid render-blocking image requests during stylesheet parsing

Avoid Base64 When:

  • Images larger than 10KB — the size overhead outweighs the saved request
  • Images that change frequently — you lose the benefit of browser caching (each HTML/CSS change invalidates the cache)
  • Multiple identical images across pages — external files get cached once, Base64 is re-downloaded on every page
  • Server-side rendering with many images — bloats the initial HTML payload, delaying First Contentful Paint
  • HTTP/2 or HTTP/3 — multiplexing makes parallel small file requests nearly as fast as inline

Rule of thumb: If the image is small enough that you would not bother creating a separate file for it, embed it. Otherwise, serve it externally.

9. Real-World Use Cases

Here are the most common production scenarios where Base64 image embedding shines:

Favicons in HTML

Embed your favicon directly in HTML to eliminate a separate request:

<!-- Inline favicon — no extra HTTP request -->
<link
  rel="icon"
  type="image/png"
  href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAB..."
/>

<!-- SVG favicon with dark mode support -->
<link
  rel="icon"
  type="image/svg+xml"
  href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmci..."
/>

Small Icons in CSS

UI icons, arrows, checkmarks, and other small decorative elements are ideal Base64 candidates:

/* Checkmark icon */
.success::before {
  content: '';
  display: inline-block;
  width: 16px;
  height: 16px;
  background: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiI+PHBhdGggZD0iTTMgOGw0IDQgNi02IiBmaWxsPSJub25lIiBzdHJva2U9IiMyMmMwNWUiIHN0cm9rZS13aWR0aD0iMiIvPjwvc3ZnPg==) no-repeat center;
}

/* Loading spinner */
.loading {
  background: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCI+PGNpcmNsZSBjeD0iMTIiIGN5PSIxMiIgcj0iMTAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzMzMyIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtZGFzaGFycmF5PSI0NyIgc3Ryb2tlLWRhc2hvZmZzZXQ9IjE1Ij48YW5pbWF0ZVRyYW5zZm9ybSBhdHRyaWJ1dGVOYW1lPSJ0cmFuc2Zvcm0iIHR5cGU9InJvdGF0ZSIgZnJvbT0iMCAxMiAxMiIgdG89IjM2MCAxMiAxMiIgZHVyPSIxcyIgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiLz48L2NpcmNsZT48L3N2Zz4=) no-repeat center;
}

Email Signatures

Company email signatures with logos are a perfect use case — the logo travels with the email:

<!-- Email signature with embedded logo -->
<table cellpadding="0" cellspacing="0" style="font-family: Arial, sans-serif;">
  <tr>
    <td style="padding-right: 15px; vertical-align: top;">
      <img
        src="data:image/png;base64,iVBORw0KGgoAAAANSUhEU..."
        alt="Company Logo"
        width="80"
        height="80"
        style="display: block; border-radius: 8px;"
      />
    </td>
    <td style="vertical-align: top;">
      <strong>Jane Smith</strong><br />
      Senior Developer<br />
      <a href="mailto:jane@company.com">jane@company.com</a>
    </td>
  </tr>
</table>

Single-File HTML Documents

For portable reports, documentation, or widgets that need to work as a single .html file:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Self-Contained Report</title>
  <link rel="icon" href="data:image/svg+xml;base64,PHN2Zy..." />
  <style>
    body { font-family: system-ui; max-width: 800px; margin: 0 auto; }
    .logo { background: url(data:image/png;base64,iVBORw...) no-repeat; }
    .chart { /* embedded chart image */ }
  </style>
</head>
<body>
  <img src="data:image/png;base64,iVBOR..." alt="Company Logo" />
  <h1>Monthly Report — January 2026</h1>
  <img src="data:image/png;base64,iVBOR..." alt="Revenue Chart" />
  <!-- Entire document is self-contained in one .html file -->
</body>
</html>

Placeholder Images and Loading States

Tiny blurred placeholder images (LQIP — Low Quality Image Placeholder) for lazy loading:

<!-- LQIP: Low Quality Image Placeholder -->
<!-- Tiny 10x7 blurred placeholder (~200 bytes as Base64) -->
<img
  src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgM..."
  data-src="/images/hero-full.jpg"
  alt="Hero image"
  style="filter: blur(20px); transition: filter 0.3s;"
  loading="lazy"
/>

<script>
// Lazy load: replace placeholder with full image
document.querySelectorAll('img[data-src]').forEach(img => {
  const fullImg = new Image();
  fullImg.onload = () => {
    img.src = img.dataset.src;
    img.style.filter = 'none';
  };
  fullImg.src = img.dataset.src;
});
</script>

10. Alternatives to Base64 Image Embedding

Base64 is not always the best approach. Consider these alternatives:

CSS Sprites

Combine multiple icons into a single image file and use CSS background-position to display individual icons. Reduces HTTP requests while keeping files cacheable.

/* CSS Sprite example */
.icon {
  background-image: url('/sprites/icons.png');
  background-repeat: no-repeat;
  width: 24px;
  height: 24px;
}
.icon-home    { background-position: 0 0; }
.icon-search  { background-position: -24px 0; }
.icon-settings { background-position: -48px 0; }

Inline SVG

Instead of Base64-encoding SVGs, insert them directly as XML into your HTML. This is more efficient (no Base64 overhead) and allows CSS styling and JavaScript interaction:

<!-- Inline SVG — no Base64 needed, fully styleable -->
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24"
     viewBox="0 0 24 24" fill="none" stroke="currentColor"
     stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" />
  <polyline points="9 22 9 12 15 12 15 22" />
</svg>

<style>
  /* Style inline SVGs with CSS */
  svg { color: #333; transition: color 0.2s; }
  svg:hover { color: #0066cc; }
</style>

CDN with HTTP/2

With HTTP/2 multiplexing, a CDN can serve many small files in parallel over a single connection. The caching benefits often outweigh the minor latency savings of Base64 inlining.

CSS image-set() and srcset

For responsive images, use srcset to serve different sizes rather than embedding a single Base64 version. This saves bandwidth on smaller screens.

<!-- Responsive images with srcset -->
<img
  srcset="/images/hero-400w.webp 400w,
          /images/hero-800w.webp 800w,
          /images/hero-1200w.webp 1200w"
  sizes="(max-width: 600px) 400px, (max-width: 1000px) 800px, 1200px"
  src="/images/hero-800w.webp"
  alt="Hero image"
/>

Summary: Use Base64 for small, critical, single-use images. Use external files (with CDN and HTTP/2) for everything else.

Frequently Asked Questions

What is the maximum size for a Base64 data URI?

There is no formal limit in the specification (RFC 2397). However, practical limits exist: Internet Explorer (legacy) had a 32KB limit; modern browsers like Chrome, Firefox, and Edge can handle data URIs of several megabytes. For performance reasons, keep Base64 images under 10KB — anything larger should be served as an external file.

Does Base64 embedding affect SEO?

Base64-embedded images cannot be independently crawled or indexed by search engines. If your images need to appear in Google Image Search, use regular external URLs with descriptive filenames and alt text. For decorative icons and small UI elements, Base64 has no SEO impact since these images would not appear in image search regardless.

Can I use Base64 images in React and Next.js?

Yes. In React, use Base64 data URIs directly in JSX: <img src="data:image/png;base64,..." />. In Next.js, the next/image component also accepts data URIs for the src prop or the blurDataURL prop for placeholder blur effects. For build-time optimization, convert images during your build process and import them as string constants.

Why does Gmail strip Base64 data URI images?

Gmail strips data URIs as a security measure to prevent potential XSS attacks and tracking techniques that could be embedded in data URIs. Instead of data URIs, use CID (Content-ID) embedding for inline images in emails, or host images externally and reference them with https:// URLs.

How do I convert a Base64 string back to an image file?

In the browser, create a link element: const a = document.createElement("a"); a.href = dataUri; a.download = "image.png"; a.click();. In Node.js: fs.writeFileSync("image.png", Buffer.from(base64String, "base64"));. In Python: open("image.png", "wb").write(base64.b64decode(b64_string)). You can also use our Base64 decoder tool for instant conversion.

𝕏 Twitterin LinkedIn
บทความนี้มีประโยชน์ไหม?

อัปเดตข่าวสาร

รับเคล็ดลับการพัฒนาและเครื่องมือใหม่ทุกสัปดาห์

ไม่มีสแปม ยกเลิกได้ตลอดเวลา

ลองเครื่องมือที่เกี่ยวข้อง

🖼️Image Base64 ConverterB64Base64 Encoder/DecoderB→Base64 Encoder

บทความที่เกี่ยวข้อง

Base64 Encoding ในทางปฏิบัติ: 7 การใช้งานจริงที่นักพัฒนาทุกคนควรรู้

ค้นพบ 7 การใช้งานจริงของ Base64 encoding: ฝังรูปภาพ, Kubernetes secrets, JWT tokens และ data URI

Base64 Encode & Decode จาก Command Line (Linux, Mac, Windows)

เข้ารหัสและถอดรหัส Base64 จากเทอร์มินัลบนทุก OS