<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jerome Leto</title>
    <description>The latest articles on DEV Community by Jerome Leto (@jeromell).</description>
    <link>https://dev.to/jeromell</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4012940%2F3a596ffd-5a25-4f48-9be4-54df0dbfc5fb.png</url>
      <title>DEV Community: Jerome Leto</title>
      <link>https://dev.to/jeromell</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jeromell"/>
    <language>en</language>
    <item>
      <title>When (and when not) to inline images as Base64</title>
      <dc:creator>Jerome Leto</dc:creator>
      <pubDate>Fri, 03 Jul 2026 03:39:02 +0000</pubDate>
      <link>https://dev.to/jeromell/when-and-when-not-to-inline-images-as-base64-2abo</link>
      <guid>https://dev.to/jeromell/when-and-when-not-to-inline-images-as-base64-2abo</guid>
      <description>&lt;p&gt;Base64 image data URIs are one of those web techniques that look like a magic shortcut the first time you use them.&lt;/p&gt;

&lt;p&gt;Instead of referencing an external file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/logo.png"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Logo"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you can put the image bytes directly in the document as text:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"data:image/png;base64,iVBORw0KGgoAAAANSUhEUg..."&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Logo"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That can be useful. It can also make a page slower, harder to cache, and more annoying to maintain.&lt;/p&gt;

&lt;p&gt;Here is the practical rule: inline images as Base64 when self-containment matters more than caching. Keep normal image files when the browser should be able to cache, resize, lazy-load, or optimize them independently.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a Base64 image actually is
&lt;/h2&gt;

&lt;p&gt;An image file is binary data. Base64 rewrites that binary data as plain text using a limited character set. To make the browser treat the text as an image, you wrap it in a data URI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;data:image/png;base64,iVBORw0KGgoAAAANSUhEUg...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first part tells the browser the MIME type. The second part tells it the data is Base64 encoded. The long tail is the image itself.&lt;/p&gt;

&lt;p&gt;Base64 is not compression. It is not encryption. It is just a text representation of the same bytes.&lt;/p&gt;

&lt;h2&gt;
  
  
  When inlining an image is worth it
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Tiny icons and UI assets
&lt;/h3&gt;

&lt;p&gt;For very small images, removing an extra HTTP request can be worth the extra bytes. This is especially true for small icons, logos, placeholders, simple UI sprites, or tiny transparent PNGs.&lt;/p&gt;

&lt;p&gt;Modern HTTP/2 and HTTP/3 make extra requests cheaper than they used to be, so this is not an automatic win. But for a one-off tiny asset inside a small page or widget, a data URI can still be a clean choice.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Single-file deliverables
&lt;/h3&gt;

&lt;p&gt;Sometimes the point is not raw page speed. Sometimes you need one file that carries everything with it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;an HTML report&lt;/li&gt;
&lt;li&gt;an email template&lt;/li&gt;
&lt;li&gt;a CodePen or demo snippet&lt;/li&gt;
&lt;li&gt;a CMS block where you cannot upload assets&lt;/li&gt;
&lt;li&gt;a test fixture that should not depend on external hosting&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In those cases, Base64 is useful because the image travels with the HTML, CSS, JSON, or JavaScript.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Prototypes and throwaway snippets
&lt;/h3&gt;

&lt;p&gt;If you are testing a layout, writing a bug reproduction, or pasting a minimal example into a ticket, a data URI can save time. You do not need to set up static hosting just to show one image.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Local-only conversion workflows
&lt;/h3&gt;

&lt;p&gt;If the image is private, it is nice to avoid uploading it to a random converter. Browser APIs can generate a Base64 data URI locally, so the file never leaves your device.&lt;/p&gt;

&lt;h2&gt;
  
  
  When you should not inline the image
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Large photos and hero images
&lt;/h3&gt;

&lt;p&gt;Base64 usually makes the encoded data about 33% larger than the original binary file. That is because Base64 stores every 3 bytes as 4 text characters.&lt;/p&gt;

&lt;p&gt;For a large JPG, PNG, or WebP, that extra size is not a rounding error. Keep big images as normal files.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Images reused across pages
&lt;/h3&gt;

&lt;p&gt;An external image can be cached once and reused across page views. An inlined image is bundled into every document or stylesheet that contains it.&lt;/p&gt;

&lt;p&gt;If the same logo appears on 20 pages, inlining it 20 times is usually worse than letting the browser cache one file.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Responsive images
&lt;/h3&gt;

&lt;p&gt;Normal image files can use &lt;code&gt;srcset&lt;/code&gt;, &lt;code&gt;sizes&lt;/code&gt;, lazy loading, CDN transforms, format negotiation, and caching headers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt;
  &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/hero-800.webp"&lt;/span&gt;
  &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"/hero-400.webp 400w, /hero-800.webp 800w, /hero-1600.webp 1600w"&lt;/span&gt;
  &lt;span class="na"&gt;sizes=&lt;/span&gt;&lt;span class="s"&gt;"100vw"&lt;/span&gt;
  &lt;span class="na"&gt;loading=&lt;/span&gt;&lt;span class="s"&gt;"lazy"&lt;/span&gt;
  &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Product screenshot"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is much harder to preserve when the image is baked into a string.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Anything you expect humans to edit
&lt;/h3&gt;

&lt;p&gt;Base64 strings are unpleasant to review in Git diffs, easy to truncate by accident, and noisy inside templates. If designers, marketers, or other engineers need to update the image regularly, use a normal asset file.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to generate a Base64 data URI in the browser
&lt;/h2&gt;

&lt;p&gt;The simplest browser-native path is &lt;code&gt;FileReader.readAsDataURL()&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"file"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"file"&lt;/span&gt; &lt;span class="na"&gt;accept=&lt;/span&gt;&lt;span class="s"&gt;"image/*"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;textarea&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"output"&lt;/span&gt; &lt;span class="na"&gt;readonly&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/textarea&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fileInput&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#file&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#output&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;fileInput&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;change&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fileInput&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;files&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FileReader&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;output&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="nx"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readAsDataURL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;data:image/png;base64,iVBORw0KGgoAAAANSUhEUg...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can use that string directly in HTML:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"data:image/png;base64,iVBORw0KGgoAAAANSUhEUg..."&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Logo"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or in CSS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.logo&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sx"&gt;url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUg...")&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  A simple checklist
&lt;/h2&gt;

&lt;p&gt;Inline the image if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;it is small&lt;/li&gt;
&lt;li&gt;it is not reused across many pages&lt;/li&gt;
&lt;li&gt;self-contained delivery matters&lt;/li&gt;
&lt;li&gt;you do not need responsive image behavior&lt;/li&gt;
&lt;li&gt;the string will not make your source files painful to maintain&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Keep it as a normal file if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;it is a photo or large graphic&lt;/li&gt;
&lt;li&gt;it should be cached separately&lt;/li&gt;
&lt;li&gt;it appears on many pages&lt;/li&gt;
&lt;li&gt;it needs &lt;code&gt;srcset&lt;/code&gt;, lazy loading, CDN resizing, or image optimization&lt;/li&gt;
&lt;li&gt;non-developers need to replace it often&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Tiny tool note
&lt;/h2&gt;

&lt;p&gt;I built a small free tool for this workflow: &lt;a href="https://image2base64.com/png-to-base64" rel="noopener noreferrer"&gt;PNG to Base64 converter&lt;/a&gt;. It runs entirely in the browser with &lt;code&gt;FileReader&lt;/code&gt;, so the PNG is not uploaded, and it gives you the raw Base64 string plus ready-to-paste HTML and CSS snippets.&lt;/p&gt;

&lt;p&gt;There is also a general &lt;a href="https://image2base64.com/" rel="noopener noreferrer"&gt;image to Base64 converter&lt;/a&gt; for JPG, SVG, WebP, GIF, and other image formats.&lt;/p&gt;

&lt;p&gt;Use Base64 as a packaging tool, not a default image strategy. When the image is tiny or the deliverable must be self-contained, it can be perfect. When performance, caching, and responsive delivery matter, boring old image files are still the better answer.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>html</category>
      <category>css</category>
    </item>
  </channel>
</rss>
