A NSW Government website

VML

A VML shape for Windows Outlook (Word), which cannot draw a background image, a gradient or a rounded box in CSS: the base the primitives that need one build on, as Maizzle's <Vml> is. resolveVml in lib/vml.ts validates the props and writes the markup; this puts the content between it.

Examples

VML

A background image, a gradient and a rounded panel, drawn for Windows Outlook in VML behind content every client shows.

17.6 KB built. Open the built email (opens in a new tab)

const image = 'https://digitalnsw.github.io/images/placeholder/email-placeholder.jpg';

<NswLayout title='VML'>
  <NswColumns padding={false}>
    <NswColumn>
      <table role='presentation' width='100%' cellPadding='0' cellSpacing='0'>
        <tbody>
          <tr>
            <td
              valign='top'
              style={{
                backgroundColor: '#949494',
                backgroundImage: 'url(' + image + ')',
                backgroundSize: 'cover',
                backgroundPosition: 'center',
              }}
            >
              <NswVml
                width={layout.width}
                height={299}
                src={image}
                color='#949494'
                inset={[0, 48, 0, 48]}
              >
                <table role='presentation' width='100%' cellPadding='0' cellSpacing='0'>
                  <tbody>
                    <tr>
                      <td style={{ padding: '48px' }}>
                        <table
                          role='presentation'
                          cellPadding='0'
                          cellSpacing='0'
                          bgcolor='#ffffff'
                          style={{ backgroundColor: '#ffffff' }}
                        >
                          <tbody>
                            <tr>
                              <td width='24' style={{ width: '24px' }} />
                              <td style={{ padding: '24px 0' }}>
                                <NswText as='h1' type='headline-md'>
                                  A background image
                                </NswText>
                                <NswText>
                                  Drawn in Windows Outlook by a VML frame fill behind this card.
                                </NswText>
                              </td>
                              <td width='24' style={{ width: '24px' }} />
                            </tr>
                          </tbody>
                        </table>
                      </td>
                    </tr>
                  </tbody>
                </table>
              </NswVml>
            </td>
          </tr>
        </tbody>
      </table>
    </NswColumn>
  </NswColumns>
  <NswColumns padding={false}>
    <NswColumn>
      <table role='presentation' width='100%' cellPadding='0' cellSpacing='0'>
        <tbody>
          <tr>
            <td
              style={{
                backgroundColor: '#002664',
                backgroundImage: 'linear-gradient(90deg, #002664, #146cfd)',
              }}
            >
              <NswVml
                width={layout.width}
                type='gradient'
                color='primary-800'
                color2='primary-600'
                angle={90}
                inset={[0, 48, 0, 48]}
              >
                <table role='presentation' width='100%' cellPadding='0' cellSpacing='0'>
                  <tbody>
                    <tr>
                      <td style={{ padding: '48px' }}>
                        <NswText as='h2' type='headline-md' color='white'>
                          A gradient
                        </NswText>
                        <NswText color='white'>
                          A VML gradient fill in Windows Outlook, a CSS gradient everywhere
                          else.
                        </NswText>
                      </td>
                    </tr>
                  </tbody>
                </table>
              </NswVml>
            </td>
          </tr>
        </tbody>
      </table>
    </NswColumn>
  </NswColumns>
  <NswColumns>
    <NswColumn>
      <NswSpacer height={48} />
      <table role='presentation' width='100%' cellPadding='0' cellSpacing='0'>
        <tbody>
          <tr>
            <td
              style={{
                backgroundColor: '#f5f5f5',
                border: '1px solid #dcdfe0',
                borderRadius: '8px',
              }}
            >
              <NswVml
                shape='roundrect'
                arcSize={0.08}
                fillColor='grey-100'
                strokeColor='grey-300'
                strokeWeight={1}
                inset={[0, 24, 0, 24]}
              >
                <table role='presentation' width='100%' cellPadding='0' cellSpacing='0'>
                  <tbody>
                    <tr>
                      <td style={{ padding: '24px' }}>
                        <NswText as='h2' type='headline-sm'>
                          A rounded panel
                        </NswText>
                        <NswText>
                          A VML roundrect in Windows Outlook, a border radius elsewhere.
                        </NswText>
                      </td>
                    </tr>
                  </tbody>
                </table>
              </NswVml>
            </td>
          </tr>
        </tbody>
      </table>
      <NswSpacer height={48} />
    </NswColumn>
  </NswColumns>
</NswLayout>

Props

Props of NswVml, read from the component
PropTypeDefaultDescription
layoutLayout—The layout the default width is drawn from: the document's (handed on by <NswLayout layout>) unless the shape is given one of its own, and the NSW defaults outside a document. Only the default width (layout.width) is drawn from it; an explicit width still wins.
shapeVmlShaperectThe shape: rect, roundrect (corners from arcSize), oval or line (from from to to, no content). Default rect.
hrefstring—Where the shape links to in Word: the whole shape is then the click target. Other clients see only the content, so link that too.
widthVmlWidththe content width of a full-width column (layout.width less the row padding either side)The shape's width: whole px, or 'page' for the page's full width (Word's mso-width-percent: 1000), which is only for a full-bleed background — Word measures it against the page, not the row, so inside a row it spills past the row. Not for a line. Default the content width of a full-width column (layout.width less the row padding either side).
heightnumber—The shape's height in whole px. Left out, the shape grows to fit its content (mso-fit-shape-to-text). Not for a line.
arcSizenumber—A roundrect's corner radius as a fraction of its shorter side, from 0 to 1 (0.1 on a 40px-tall shape is a 4px radius). Only for a roundrect.
fromreadonly [number, number]—Where a line starts: [x, y] in whole px. Required for a line, and only for one.
toreadonly [number, number]—Where a line ends: [x, y] in whole px. Required for a line, and only for one.
fillColorColorValue—The shape's own fill: a theme colour name or a hex literal, or 'transparent' for none; anything else throws (see resolveColor). Also what shows where a fill image has not loaded. Word's dark mode never recolours a VML fill, though it recolours the text on it. Not for a line.
strokeColorColorValue—The outline's colour: a theme colour name or a hex literal; 'transparent' and anything else throws. Left out, no outline — except a line, which needs it.
strokeWeightnumberVML's own, 1pxThe outline's width in whole px, written as VML points. Only with a strokeColor. Default VML's own, 1px.
typeVmlFillTypeframe when there is a src, VML's solid otherwiseHow the <v:fill> paints: solid, gradient, gradientradial, tile, pattern or frame. Default frame when there is a src, VML's solid otherwise.
srcstring—The fill image's URL.
colorColorValue—The fill's colour, a gradient's first: a theme colour name or a hex literal; 'transparent' and anything else throws.
color2ColorValue—A gradient's second colour: a theme colour name or a hex literal; 'transparent' and anything else throws.
opacitynumber—The fill's opacity, from 0 to 1.
anglenumber—A gradient's direction in CSS linear-gradient degrees, from 0 to 360: 0 runs color at the bottom to color2 at the top, 90 from left to right. Written as VML's own angle, which turns the other way.
focusnumber—Where a gradient's colours meet, as a percentage from -100 to 100 (50 puts the second colour in the middle).
focusSizereadonly [number, number]—A radial gradient's focus size, [x, y] as fractions of the shape.
focusPositionreadonly [number, number]—A radial gradient's focus position, [x, y] as fractions of the shape.
sizereadonly [number, number]—The fill image's size, [width, height] in whole px.
originreadonly [number, number]—The fill image's origin, [x, y] as fractions of the image (-0.5 is its left or top edge). Wins over backgroundPosition.
positionreadonly [number, number]—Where the fill image's origin sits, [x, y] as fractions of the shape. Wins over backgroundPosition.
backgroundPositionVmlBackgroundPosition—The fill image's placement in words, vertical first ('top left', 'center center'): sets origin and position together.
aspectVmlAspect—How the fill image keeps its proportions: atleast (covers the shape) or atmost (fits inside it).
insetreadonly [number, number, number, number]noneSpace between the shape's edge and its content in Word, [top, right, bottom, left] in whole px. In CSS's order, written in VML's (left, top, right, bottom). Word keeps a cell's top and bottom padding inside the text box but drops its left and right, so give the content's side padding here too. Not for a line. Default none.