Skip to content

Open-tracking pixel renders as an ~18px empty row — emails get a phantom scrollbar in Outlook (regression in v29.2) #413

Description

@reikjarloekl

Since v29.2, the open-tracking pixel is injected as a full-width table row whose <img> has no dimensions and stays inline. The empty cell renders one full text line box (~18px at default line-height) below the email's last section, so the message body ends up slightly taller than the visible layout. In Outlook this shows as a small extra scroll region — the message scrolls a few millimeters past the footer even though nothing visible is there.

The markup comes from GenerateHTMLOpenTrackingPixel in pkg/notifuse_mjml/template_compilation.go:

return fmt.Sprintf(`<table border="0" cellpadding="0" cellspacing="0" role="presentation" width="100%%"><tr><td><img src="%s" alt="" style="border:0;margin:0;padding:0;"></td></tr></table>`, pixelURL)

Up to v29.1 the pixel was <img src="…" alt="" width="1" height="1">, which renders at 1px and causes no artifact. The v29.2 anti-pixel-blocker rework (1d50e5e, f7035f2) dropped the width/height attributes and added the full-width table wrapper. An inline image without dimensions sits on the text baseline, so the <td> takes the full line height even though the served image is 1×1. The code is unchanged on current main; observed on a self-hosted 35.x instance.

Reproduce: enable email tracking for a workspace, send any template (a test send is enough), open it in Outlook — the message area has a few millimeters of extra scroll below the layout. It is also measurable without Outlook by appending the generated markup before </body> of a compiled 600px MJML email and reading document.documentElement.scrollHeight.

Measurements in Chromium on such a compiled template:

Variant scrollHeight Delta
No pixel 1218px
Current markup, image loaded 1236px +18px
Current markup, image blocked 1236px +18px
Fixed markup (below), image loaded 1219px +1px
Fixed markup (below), image blocked 1218px ±0

Suggested fix that keeps the structural-layout disguise but lets the row collapse — zero out the line box and make the image a block element:

<table border="0" cellpadding="0" cellspacing="0" role="presentation" width="100%"><tr><td style="line-height:0;font-size:0;mso-line-height-rule:exactly"><img src="" alt="" style="display:block;border:0;margin:0;padding:0;"></td></tr></table>

display:block removes the baseline gap, line-height:0/font-size:0 cover clients that ignore one of them, and mso-line-height-rule:exactly makes Word-engine Outlook honor the zero line-height too. The tag still avoids the classic width="1" height="1" blocker fingerprint. Happy to send a PR against dev if you'd like one.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions