Per-Corner Radius in Outlook Using VML Paths
Hey community!
Excited to share a technical win that I think many email developers will find valuable - especially those pushing the limits of what's possible in Outlook.
The Challenge
We recently tackled a design requirement that most email developers would consider "not possible in Outlook" - applying different border-radius values to each individual corner of an element, dynamically, within a complex multi-row email module.
Most of us are familiar with the standard workaround for rounded corners in Outlook: the arcsize property on VML <v:roundrect>. It works well, but it applies a uniform radius to all four corners. The moment you need, say, a 20px top-left, 0px top-right, 8px bottom-right, and 16px bottom-left - you're stuck. At least with the conventional approach.
The Solution: VML <v:shape> with Custom Path Data
The key insight is moving away from <v:roundrect> entirely and using a <v:shape> element with a custom path attribute. This gives you full control over every point and curve in the shape.
The path uses VML's drawing commands to manually define each corner arc:
m — moveto (starting point)
l — lineto
ae — arcto (this is where the magic happens per corner)
x — close path
Each ae command lets you independently define the arc for that specific corner — its center point, radius width, radius height, start angle, and sweep angle. By calculating these values based on your desired pixel radius and the element's dimensions, you can achieve fully asymmetric rounded corners.
Key things to know if you want to implement this:
VML coordinates are in EMUs (English Metric Units) by default when used without a coordinate size override. Define coordsize on your shape to work in a pixel-friendly space.
The ae arc command takes: cx, cy, rx, ry, startAngle, sweepAngle — all in the coordinate system you've defined.
You must calculate arc entry/exit points precisely so your l (lineto) segments connect cleanly to each arc — mismatches cause rendering artifacts.
Dynamic values (e.g., driven by template variables) are achievable — you just need to pre-calculate the path string server-side or at template compile time.
Always wrap in a conditional comment <!--[if mso]>...<![endif]--> and provide a CSS fallback for non-Outlook clients.
Test across Outlook 2016, 2019, and 365 (Windows) — rendering can vary slightly between versions.
The Result
With this approach, complex designs that combine multiple rows, varied radii per corner, and dynamic content are absolutely achievable in Outlook — something many teams have written off as impossible.
It took research, iteration, and thorough validation, but the outcome is a reusable pattern our team can now build on for future requirements.
If you're working on a similar challenge and want to discuss the implementation details, drop a comment — happy to share more!