Skip to main content

How to Fix Outlook Table Spacing Issues

Fix Outlook table spacing issues caused by mso-table-lspace, cellspacing, and Word engine quirks in HTML email templates.

Eliminate phantom vertical gaps, collapsed borders, and misaligned cells in Outlook desktop clients by enforcing strict table resets and MSO-specific conditional directives. Modern web browsers use standard CSS box models, but Outlook relies on Microsoft Word's legacy rendering engine. This engine ignores standard margin resets on <td> elements and injects proprietary whitespace when modern layout techniques are applied. A foundational grasp of Mastering Email HTML & CSS is required to maintain deterministic layouts in enterprise transactional systems.

Root Cause: Word Engine Rendering Behavior

Outlook's rendering pipeline parses HTML through Word's layout engine, which applies a default 1pt horizontal padding to table cells and aggressively collapses vertical whitespace. It completely ignores margin properties on <td> and <tr> elements. When developers apply display: flex, display: grid, or inline-block fallbacks, the Word engine miscalculates line-height and baseline alignment, resulting in unpredictable 4–8px phantom gaps. This is why the responsive email layouts approach leans on ghost tables rather than CSS layout modes when Outlook is in scope. The engine also overrides standard border-collapse behavior unless explicitly forced via HTML attributes and MSO-specific CSS overrides.

Exact Table Reset Protocol

Enforce a strict baseline reset on every structural table. Do not rely on external stylesheets or inherited CSS for table spacing.

Baseline HTML Attributes:

<table role="presentation" cellpadding="0" cellspacing="0" border="0" width="100%" style="border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt;">
  <tr>
    <td style="line-height: 100%; font-size: 0; vertical-align: top;">
      <!-- Content -->
    </td>
  </tr>
</table>

Critical Rules:

  • Always declare cellpadding="0" cellspacing="0" directly on the <table> tag.
  • Apply border-collapse: collapse; inline.
  • Set line-height: 100%; and font-size: 0; on wrapper <td> elements to eliminate inherited text baseline spacing.
  • Never use margin on table rows or cells.
  • Use padding on <td> elements for spacing; avoid margins on block-level elements inside table cells.

Implementing MSO Conditional Directives

Isolate Outlook-specific overrides using VML-style conditional comments. This prevents modern clients from parsing proprietary mso- properties while forcing the Word engine to respect your spacing rules.

Production-Ready Conditional Block:

<!--[if mso]>
<style type="text/css">
  table, td, th { border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; }
  td { padding: 0; margin: 0; }
  .outlook-spacer { height: 20px; line-height: 20px; font-size: 20px; display: block; }
</style>
<![endif]-->

Implementation Notes:

  • Place the conditional block in the <head> before any inline styles.
  • Use a <td> with explicit height, line-height, and font-size all set to the same pixel value for vertical gaps in Outlook instead of margin or padding.
  • For horizontal spacing, nest a secondary <table> with explicit width attributes.
  • Verify that your CSS inliner does not strip or mangle <!--[if mso]> syntax. Configure your build pipeline to preserve conditional comments.

Vertical spacer pattern:

<!-- Outlook-safe vertical spacer -->
<table role="presentation" cellpadding="0" cellspacing="0" border="0" width="100%">
  <tr>
    <td style="height: 20px; line-height: 20px; font-size: 20px;">&nbsp;</td>
  </tr>
</table>

Transactional Pipeline Integration

Automated dispatch systems frequently break table spacing during template compilation. Implement strict validation and inlining rules to prevent runtime layout shifts.

Pipeline Configuration:

  1. Whitespace Stripping: Enable aggressive whitespace removal in your templating engine (Handlebars, Liquid, MJML), but exclude content inside <pre>, <code>, and conditional comment blocks.
  2. CSS Inlining: Use an inliner that respects <!--[if mso]> blocks. Juice must be configured with preserveMediaQueries: true and should not strip conditional comments — check that your juice version and config do not set removeComments: true. The mechanics of keeping these comments intact are covered in preserving media queries when inlining with Juice.
  3. Dynamic Data Injection: Sanitize all injected strings. Unescaped HTML or line breaks in dynamic variables can force table cells to expand. Wrap dynamic content in <span style="display: block;"> or explicitly set word-break: break-word; on the parent <td>.
  4. Error Handling: Implement pre-flight validation. If the compiled HTML contains <td style="margin:"> or missing cellpadding="0", trigger a build failure and route to a staging queue for manual review. Catch malformed table closures with regex validation before SMTP handoff.

Detailed debugging workflows for enterprise-scale deployments are documented in Outlook Rendering Fixes.

Validation & Deployment Checklist

Execute the following sequence before promoting templates to production SMTP dispatch.

Pre-Flight Validation:

  • Run compiled HTML through W3C Validator (ignore mso- warnings).
  • Verify all structural tables contain cellpadding="0" cellspacing="0".
  • Confirm no display: flex or grid properties exist in the compiled output.
  • Ensure <!--[if mso]> blocks are intact, unminified, and properly closed.

Cross-Client Rendering Tests:

  • Litmus / Email on Acid: Test against Outlook 2016, 2019, 2021, and Microsoft 365 (Windows).
  • Visual Diff: Compare rendered output against a baseline screenshot. Look specifically for 1–4px vertical gaps between rows.
  • Dark Mode Check: Verify that explicit background colors on <td> and <table> prevent OS-level inversion from altering cell spacing perception.

Deployment & Monitoring:

  • Deploy to a 5% traffic segment.
  • Monitor bounce/reject logs for malformed HTML errors.
  • If spacing anomalies appear in production, immediately revert to the last validated commit and audit recent CSS inliner updates.
  • Maintain a version-controlled template registry. Tag each release with client-specific rendering notes.

Variant: Outlook 365 vs Outlook 2016/2019 Spacing Differences

Although both render through Word, the desktop versions are not identical, and a fix verified only in one can fail in the other. Outlook 2016, 2019, and 2021 (the perpetual-license MSI/click-to-run builds) apply the legacy 1pt cell padding and the most aggressive line-height inheritance. Outlook 365 (the subscription build) shares the same engine but ships incremental rendering updates, so a template that looks tight in 365 can still show 2–4px gaps in 2016. The safe stance is to reset for the strictest build and verify across all of them.

<!-- Reset that holds across Outlook 2016/2019/2021 AND Outlook 365 (Win) -->
<table role="presentation" cellpadding="0" cellspacing="0" border="0" width="100%"
       style="border-collapse:collapse;mso-table-lspace:0pt;mso-table-rspace:0pt;mso-padding-alt:0;">
  <tr>
    <!-- Outlook 2016-2019: mso-line-height-rule:exactly stops 2-4px baseline expansion 365 hides -->
    <td style="margin:0;padding:0;font-size:0;line-height:0;mso-line-height-rule:exactly;">
      <img src="https://cdn.example.com/divider.png" width="600" height="1" alt="" style="display:block;border:0;">
    </td>
  </tr>
</table>

Two MSO properties matter most here. mso-padding-alt:0; neutralizes a padding behavior that surfaces in 2016/2019 but is often invisible in 365, and mso-line-height-rule:exactly forces the older builds to honor the declared line-height instead of expanding it to the font's natural leading. Always confirm the fix in an actual 2016 render, not just 365, because 365's newer build masks the bug your 2016 recipients will see.

Variant: Nested Tables and the Compounding-Gap Problem

Spacing defects compound with nesting depth. Each nested <table> reintroduces the default cellspacing and the inherited line-height of its parent cell, so a three-level structure can accumulate 12px or more of phantom whitespace that no single reset removes. The Word engine does not inherit your outer reset into nested tables — every table is treated independently.

<!-- Nested tables: EACH level needs its own reset or gaps stack in Outlook 2016-2021 -->
<table role="presentation" cellpadding="0" cellspacing="0" border="0" width="100%"
       style="border-collapse:collapse;mso-table-lspace:0pt;mso-table-rspace:0pt;">
  <tr>
    <td style="padding:0;font-size:0;line-height:0;">
      <table role="presentation" cellpadding="0" cellspacing="0" border="0" width="100%"
             style="border-collapse:collapse;mso-table-lspace:0pt;mso-table-rspace:0pt;">
        <tr>
          <!-- Outlook 365: inner table re-adds cellspacing unless reset is repeated here, not inherited -->
          <td style="padding:16px;font-size:15px;line-height:22px;mso-line-height-rule:exactly;color:#334155;">
            Nested content with no compounded gap
          </td>
        </tr>
      </table>
    </td>
  </tr>
</table>

The rule is mechanical: every <table> in the tree carries cellpadding="0" cellspacing="0" border="0" and border-collapse:collapse;mso-table-lspace/rspace:0pt, and every spacer or wrapper <td> sets font-size:0;line-height:0. Flatten the structure wherever possible — fewer nested tables means fewer places for the Word engine to inject spacing. Where deep nesting is unavoidable (complex multi-column digests), the hybrid scaffolding described in responsive email layouts keeps the desktop structure rigid while letting it collapse cleanly on mobile.

Variant: Image Gaps Inside Spacing-Sensitive Cells

A distinct but related symptom is the 3–4px gap beneath images inside table cells in Outlook. Images are inline elements by default and sit on the text baseline, so the descender space below the line appears as a gap. The fix is display:block on the image plus the font-size/line-height reset on its cell.

<!-- Image gap fix: display:block removes baseline descender space in Outlook 2016-2021 + Apple Mail -->
<td style="font-size:0;line-height:0;padding:0;">
  <img src="https://cdn.example.com/banner.png" width="600" alt="Promotional banner"
       style="display:block;border:0;outline:none;text-decoration:none;-ms-interpolation-mode:bicubic;">
</td>

The -ms-interpolation-mode:bicubic property additionally improves Outlook's image scaling quality when the rendered width differs from the source width, preventing the jagged resampling that often accompanies the gap bug. Note that this is purely an Outlook concern — Apple Mail, iOS Mail, and Gmail all already apply display:block semantics or smooth scaling, so the same markup is harmless there while it is essential for the Word engine.

A second image-related trap is the align attribute. Setting align="left" or align="right" on an image floats it in the Word engine and reintroduces surrounding whitespace that display:block was meant to remove. For spacing-sensitive layouts, drop the align attribute on images entirely and control position through the cell's align attribute and padding instead, so the reset stays in one predictable place.

Targeted Debugging Steps

When a gap persists after applying the resets, work through these named checks in order.

  1. Symptom: gap only in Outlook 2016, clean in 365 — Cause: mso-line-height-rule missing. Fix: add mso-line-height-rule:exactly to every text cell and re-render in 2016.
  2. Symptom: gap grows with each section — Cause: nested tables without per-level resets. Fix: apply cellspacing="0" and font-size:0 on every nested table and wrapper cell.
  3. Symptom: thin line under every image — Cause: image on text baseline. Fix: display:block on the <img> and font-size:0;line-height:0 on the cell.
  4. Symptom: spacing appeared after a build change — Cause: inliner stripped or minified <!--[if mso]> blocks. Fix: confirm removeComments is off; see preserving media queries when inlining with Juice.
  5. Symptom: horizontal gap between side-by-side cells — Cause: residual cellspacing or whitespace between cells. Fix: cellspacing="0" on the table and mso-table-lspace/rspace:0pt.

Tightened Validation Checklist

Run this focused pass specifically for spacing before any wider QA.

  • Every table in the tree carries cellpadding="0" cellspacing="0" border="0".
  • Every text cell sets mso-line-height-rule: exactly with an explicit pixel line-height.
  • Every spacer/wrapper cell sets font-size:0; line-height:0.
  • Every structural image sets display:block and border:0.
  • Rendered in Outlook 2016 (not only 365) with no visible row, image, or column gaps.
  • <!--[if mso]> blocks survive the inliner unminified and balanced.
  • No display:flex, grid, or margin on any <td>/<tr> in the compiled output.
Where Word-engine spacing creeps in Annotated table showing the three points where Outlook adds whitespace: cellspacing gaps, mso-table lspace and rspace padding, and inherited line-height on cells. Where Outlook Adds Spacing Cell A Cell B Spanning Cell C gap cellspacing default 1pt gaps mso-table-lspace side padding line-height baseline padding Reset all three with cellspacing=0, mso-table-lspace/rspace 0pt, and font-size 0 on wrappers.
The three spots where Outlook's Word engine injects whitespace: default cellspacing, mso-table lspace/rspace padding, and inherited cell line-height.

← Back to Outlook Rendering Fixes