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>

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.

Compounding gaps in nested tables Each nesting level adds its own default border spacing, so a two pixel default becomes a visible six pixel gap by the third level. Every Nesting Level Adds Its Own Gap outer table — +2px middle table — +2px inner table — +2px content sits 6px in After the reset border-collapse: collapse cellpadding=0 cellspacing=0 border=0 Applied at every level, gaps go to zero. Resetting only the outer table leaves the inner gaps intact — which is why the symptom survives a partial fix.
Because the defaults are per-table, the reset has to be applied to every table in the nest, not just the outermost one.
<!-- 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.

The image descender gap An inline image sits on the text baseline, leaving descender space below it; setting display block or vertical-align middle removes the gap. The Gap Is Descender Space, Not Padding img is inline by default image the strip below is reserved for descenders display: block on the img image, flush to the cell edge no baseline, so no reserved strip
The gap comes from inline layout reserving descender space — taking the image out of the text flow removes it entirely.
<!-- 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.

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.

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.

Validation & Deployment Checklist

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

Pre-Flight Validation:

Cross-Client Rendering Tests:

Deployment & Monitoring:

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

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.

Frequently Asked Questions

Why does the gap appear only in Outlook on Windows?

Because the Word engine applies its own default cell spacing and treats the table as a word-processing grid rather than as a CSS box. Every other engine honours border-collapse and the cellspacing attribute the way the specification describes, so the defaults never surface. The new Outlook on WebView2 behaves like the others, which is why a colleague on it cannot reproduce the report.

Do I need both the attributes and the CSS?

Yes. cellpadding and cellspacing are attributes the Word engine reads; border-collapse and border-spacing are the CSS other engines read. Declaring only one set leaves the other family of clients on its defaults, and the two families disagree — which is how a template ends up correct in exactly the clients the developer tested.

Does this apply to nested tables?

Especially to nested tables, because the defaults are per table and therefore compound. A three-level nest with no reset accumulates three sets of spacing, which is why the gap in a deeply nested layout is larger than the two pixels the outer table suggests. Apply the reset at every level, which is a strong argument for emitting tables from a component.

What about mso-table-lspace and mso-table-rspace?

They remove the horizontal space the Word engine reserves either side of a table, which is a different gap from cell spacing and shows up as a table that will not sit flush against its container. Setting both to 0pt is standard on every table in an email and costs nothing elsewhere, since non-Microsoft clients discard the properties.

Could I use display: block on the cells instead?

No — the Word engine does not implement block layout for table cells, so the declaration is ignored exactly where you need it and changes behaviour everywhere else. Table spacing problems in email are solved with table attributes and MSO properties, not by opting out of table layout.


← Back to Outlook Rendering Fixes