Reduce File Size with Base64 Image Headers and Footers
Adding a Base64 image to a header or footer on a large multi-page PDF can inflate the output file dramatically. The fix is to embed the image once instead of on every page, while still letting per-page text like {page} render normally.
The bloat happens because of how the renderer handles a combined fragment. When a single fragment holds both the image and dynamic content such as {page}, the engine treats all of the HTML as dynamic and re-embeds the Base64 image on every page. Splitting the work into two passes keeps the image static and the page-number layer small.
Solution
1. Split the header or footer into two fragments
Separate the content into a static fragment and a dynamic one. Put the image and any text that never changes in the static fragment. Put per-page content such as {page} in the dynamic fragment. Give both fragments the same table layout and cell widths so the dynamic text lands correctly over the static layer.
2. Add the static fragment first
Call AddHtmlHeadersAndFooters with only the static fragment. The Base64 image is rendered and embedded a single time.
3. Add the dynamic fragment in a second pass
Call AddHtmlHeadersAndFooters again with only the dynamic fragment. Since this pass carries no image, the per-page content stays small.
using IronPdf;
var pdf = PdfDocument.FromFile("input.pdf");
// Static layer: holds the Base64 image. The page-number cell is left empty.
string staticFooter = @"
<table style='width:100%; table-layout:fixed;'>
<tr>
<td style='width:20%;'>
<img src='data:image/png;base64,iVBORw0KGg...' style='width:150px;' />
</td>
<td style='width:80%; text-align:right;'></td>
</tr>
</table>";
// Dynamic layer: holds only {page}. Same layout, but no image.
string dynamicFooter = $@"
<table style='width:100%; table-layout:fixed;'>
<tr>
<td style='width:20%;'></td>
<td style='width:80%; text-align:right; font-size:10px;'>Page {{page}} of {pdf.PageCount}</td>
</tr>
</table>";
// Pass 1: add the static image footer (image embedded once).
pdf.AddHtmlHeadersAndFooters(new ChromePdfRenderOptions
{
HtmlFooter = new HtmlHeaderFooter { HtmlFragment = staticFooter, MaxHeight = 40 }
});
// Pass 2: add the dynamic page-number footer (no image, stays small).
pdf.AddHtmlHeadersAndFooters(new ChromePdfRenderOptions
{
HtmlFooter = new HtmlHeaderFooter { HtmlFragment = dynamicFooter, MaxHeight = 40 }
});
pdf.SaveAs("output.pdf");
using IronPdf;
var pdf = PdfDocument.FromFile("input.pdf");
// Static layer: holds the Base64 image. The page-number cell is left empty.
string staticFooter = @"
<table style='width:100%; table-layout:fixed;'>
<tr>
<td style='width:20%;'>
<img src='data:image/png;base64,iVBORw0KGg...' style='width:150px;' />
</td>
<td style='width:80%; text-align:right;'></td>
</tr>
</table>";
// Dynamic layer: holds only {page}. Same layout, but no image.
string dynamicFooter = $@"
<table style='width:100%; table-layout:fixed;'>
<tr>
<td style='width:20%;'></td>
<td style='width:80%; text-align:right; font-size:10px;'>Page {{page}} of {pdf.PageCount}</td>
</tr>
</table>";
// Pass 1: add the static image footer (image embedded once).
pdf.AddHtmlHeadersAndFooters(new ChromePdfRenderOptions
{
HtmlFooter = new HtmlHeaderFooter { HtmlFragment = staticFooter, MaxHeight = 40 }
});
// Pass 2: add the dynamic page-number footer (no image, stays small).
pdf.AddHtmlHeadersAndFooters(new ChromePdfRenderOptions
{
HtmlFooter = new HtmlHeaderFooter { HtmlFragment = dynamicFooter, MaxHeight = 40 }
});
pdf.SaveAs("output.pdf");
Imports IronPdf
Dim pdf = PdfDocument.FromFile("input.pdf")
' Static layer: holds the Base64 image. The page-number cell is left empty.
Dim staticFooter As String = "
<table style='width:100%; table-layout:fixed;'>
<tr>
<td style='width:20%;'>
<img src='data:image/png;base64,iVBORw0KGg...' style='width:150px;' />
</td>
<td style='width:80%; text-align:right;'></td>
</tr>
</table>"
' Dynamic layer: holds only {page}. Same layout, but no image.
Dim dynamicFooter As String = $"
<table style='width:100%; table-layout:fixed;'>
<tr>
<td style='width:20%;'></td>
<td style='width:80%; text-align:right; font-size:10px;'>Page {{page}} of {pdf.PageCount}</td>
</tr>
</table>"
' Pass 1: add the static image footer (image embedded once).
pdf.AddHtmlHeadersAndFooters(New ChromePdfRenderOptions With {
.HtmlFooter = New HtmlHeaderFooter With {.HtmlFragment = staticFooter, .MaxHeight = 40}
})
' Pass 2: add the dynamic page-number footer (no image, stays small).
pdf.AddHtmlHeadersAndFooters(New ChromePdfRenderOptions With {
.HtmlFooter = New HtmlHeaderFooter With {.HtmlFragment = dynamicFooter, .MaxHeight = 40}
})
pdf.SaveAs("output.pdf")
The two table-layout:fixed fragments share identical cell widths, so the page number in the second pass sits exactly where the empty cell was in the first. The same technique applies to headers: keep the image in the static pass, and place any dynamic header text in the second pass.
Option: Reference an external image or SVG
If you do not need the image inlined as Base64, pointing the <img> at an external file or using an SVG can shrink the output size further than a Base64 string.

