Skip to Content
Styling Guide

Styling Guide

A practical guide to styling pom presentations — colors, fonts, backgrounds, borders, shadows, and more.

Color Format

Colors are specified as 6-digit hex without the # prefix (e.g., FF0000, 333333). This is the recommended format for consistency.

<Text color="333333">Dark gray text</Text> <Text color="FF0000">Red text</Text> <VStack backgroundColor="F8F9FA"><Text>Light gray background</Text></VStack>

Design Tokens with <Theme>

Declare a color palette once at the top level with a <Theme> element and reference each token from any color attribute as $tokenName. This keeps the palette in one place instead of repeating hex values on every node.

Theme tokens example

<Theme surface="0F172A" accent="38BDF8" textMain="F8FAFC" textMuted="94A3B8" /> <Slide> <VStack w="100%" h="max" padding="48" gap="16" backgroundColor="$surface"> <Text fontSize="28" color="$textMain" bold="true">Title</Text> <Timeline dateColor="$textMuted" titleColor="$textMain" w="1000" h="120"> <TimelineItem date="Q1" title="Phase 1" color="$accent" /> </Timeline> </VStack> </Slide>
  • At most one <Theme> per document; it applies to all slides regardless of position.
  • $tokenName references are resolved in color attributes (any attribute ending in Color / Colors, color keys inside object/JSON attributes, highlight) and inside backgroundGradient / textGradient strings.
  • Composite nodes (Timeline, Matrix, Tree, Flow) expose dedicated text-color attributes (e.g. dateColor / titleColor / axisLabelColor / textColor / connectorStyle.labelColor) so the whole deck — including labels on charts and diagrams — can be retinted from a single <Theme>.
  • Token names start with a letter and may contain letters, digits, _, and -. Values are 6-digit hex (# prefix optional). Referencing an unknown token throws a ParseXmlError with a “did you mean” suggestion.

See Nodes — Top-Level <Theme> for the full reference.

A set of colors that work well for business presentations:

PurposeColorHex
TitleNear-black1A1A2E
Body textDark gray333333
SubtitleMedium gray666666
Muted textLight gray999999
PrimaryBlue1D4ED8
SuccessGreen16A34A
WarningAmberD97706
DangerRedDC2626
InfoSky blue0EA5E9
Light BGOff-whiteF8F9FA
BorderLight grayE5E7EB

Font

The default font is Noto Sans JP, bundled with pom for accurate text measurement in both Node.js and browser environments.

Specifying a Font

<Text fontFamily="Arial">English text in Arial</Text> <Text fontFamily="Noto Sans JP">Japanese text (default)</Text>

Note: Custom fonts must be installed on the system where the PPTX is opened. Noto Sans JP is the only font with built-in measurement support.

Font Size Guide

RoleSize (px)Usage
Title28–40Slide titles
Heading18–24Section headings
Body13–16Paragraphs and list items
Caption10–12Footnotes, labels, captions
<VStack gap="12" alignItems="start"> <Text fontSize="36" bold="true" color="1A1A2E">Slide Title</Text> <Text fontSize="20" bold="true" color="333333">Section Heading</Text> <Text fontSize="14" color="333333">Body text with regular size.</Text> <Text fontSize="11" color="999999">Caption or footnote</Text> </VStack>

Line Height

Control line spacing with lineHeight (multiplier of fontSize, default: 1.3).

<Text lineHeight="1.5">Wider line spacing for readability</Text> <Text lineHeight="1.0">Tight line spacing</Text>

For Text (and the text inside Shape), lineHeight is reflected in both the yoga layout measurement (block height = lines × fontSize × lineHeight) and the rendered line spacing, which is emitted as a fixed value (PowerPoint spcPts) of fontSize × lineHeight. This keeps the measured height and the rendered line height aligned, so a tall lineHeight no longer creates asymmetric whitespace above/below the glyph ink.

Ul / Ol use a different convention. Their line spacing is rendered as a multiplier (PowerPoint spcPct) of the bundled-font metric, so the effective row height is measureFontLineHeightRatio × lineHeight × fontSize. Use the same lineHeight value when you want Text and Ul blocks to look visually consistent; the absolute pixel values may differ slightly.

Text Decoration

Bold, Italic, Strikethrough

<Text bold="true">Bold text</Text> <Text italic="true">Italic text</Text> <Text strike="true">Strikethrough text</Text> <Text bold="true" italic="true">Bold italic</Text>

Inline Formatting

Use <B>, <I>, <U>, <S>, <Mark>, and <Span> child elements to apply bold, italic, underline, strikethrough, highlight, color, or per-run fontSize to part of the text:

Inline formatting example

<Text fontSize="16">Normal <B>bold part</B> normal</Text> <Text fontSize="16">Normal <I>italic part</I> normal</Text> <Text fontSize="16"><B>bold</B> and <I>italic</I> mixed</Text> <Text fontSize="16"><B><I>Bold italic (nested)</I></B></Text> <Text fontSize="16">Normal <U>underline part</U> normal</Text> <Text fontSize="16">Normal <S>strikethrough part</S> normal</Text> <Text fontSize="16"><Mark color="FFFF00">highlighted part</Mark> normal</Text> <Text fontSize="16"><B><U>Bold underline (nested)</U></B></Text> <Text fontSize="16">Normal <Span color="FF0000">red part</Span> normal</Text> <Text fontSize="16"><B><Span color="1D4ED8">bold blue</Span></B></Text> <Text fontSize="52" bold="true" color="1D4ED8">¥84.2<Span fontSize="20">M</Span></Text>

<Span fontSize> is handy for KPI-style “big number + small unit” composition (¥84.2M, 118%) within a single <Text> — the digit and unit share one baseline automatically without needing the older HStack + alignItems="end" workaround. Layout measurement uses the largest run-level fontSize so the Text container is sized for the biggest glyph.

This also works inside <Li> and <Td>:

<Ul fontSize="14"> <Li>Normal <B>bold</B> item</Li> <Li>Normal <U>underline</U> item</Li> </Ul>

Underline

Underline styles example

Simple underline:

<Text underline="true">Underlined text</Text>

Customized underline with style and color:

<Text underline.style="wavy" underline.color="FF0000">Wavy red underline</Text> <Text underline.style="dbl">Double underline</Text> <Text underline.style="dotted">Dotted underline</Text>

See the Text section in Nodes for all available underline styles.

Highlight

Apply a background highlight to text:

Highlight example

<Text highlight="FFFF00">Yellow highlighted text</Text> <Text highlight="90EE90">Green highlighted text</Text>

Text Effects (glow / outline)

glow adds a glow halo around the characters; outline draws a border along the character edges. Both are exported as native PowerPoint text effects (editable, not rasterized) and are useful for keeping titles legible on top of background images.

Text effects example

<Text fontSize="40" bold="true" color="FFFFFF" glow.size="8" glow.opacity="0.5" glow.color="1D4ED8">Glowing title</Text> <Text fontSize="40" bold="true" color="FFFFFF" outline.size="2" outline.color="0F172A">Outlined title</Text>
PropertyTypeDescription
glow.sizenumberGlow radius in px (default: 8)
glow.opacity0–1Glow opacity (default: 0.75)
glow.colorhexGlow color (default: FFFFFF)
outline.sizenumberOutline width in px (default: 1)
outline.colorhexOutline color (default: FFFFFF)
  • Both apply per text node. When inline formatting (<B>, <Span>, …) is used, the node-level effect applies to all runs.
  • LibreOffice does not render character glow (outline renders fine); open the PPTX in PowerPoint to see the glow.

Text Alignment

<Text textAlign="left">Left aligned (default)</Text> <Text textAlign="center">Center aligned</Text> <Text textAlign="right">Right aligned</Text>

Background

Background Color

All nodes support backgroundColor:

<Text backgroundColor="F8F9FA" padding="16">Content on a light gray background</Text>

Background Gradient

Apply a CSS-like linear-gradient() or radial-gradient() as the background with backgroundGradient. Exported as a native PowerPoint gradient fill (editable in PowerPoint, not rasterized). Takes precedence over backgroundColor and works on the slide root for full-slide gradient backgrounds.

Background gradient example

<VStack backgroundGradient="linear-gradient(135deg, #1E40AF 0%, #0EA5E9 100%)" w="600" h="300" padding="32"> <Text fontSize="24" color="FFFFFF" bold="true">Gradient background</Text> </VStack> <VStack backgroundGradient="linear-gradient(to right, #16A34A 0%, #DBEAFE 100%)" w="600" h="200" padding="32" /> <VStack backgroundGradient="linear-gradient(45deg, #7C3AED 0%, #EC4899 50%, #F97316 100%)" w="600" h="200" padding="32" /> <VStack backgroundGradient="radial-gradient(circle at center, #1D4ED8 0%, #38BDF8 100%)" w="600" h="300" padding="32"> <Text fontSize="24" color="FFFFFF" bold="true">Radial blob</Text> </VStack> <VStack backgroundGradient="radial-gradient(circle at top right, #7C3AED 0%, #0F172A 70%)" w="600" h="300" padding="32" />
  • linear-gradient: angle accepts <n>deg (0 = bottom-to-top, clockwise) or to <direction> keywords (to right, to bottom left, …) and defaults to 180deg (top-to-bottom).
  • radial-gradient: optional <shape> (circle / ellipse, default ellipse) + optional <size> (closest-side / closest-corner / farthest-side / farthest-corner, default farthest-corner) + optional at <position> (at center / at top right / at 25% 75% etc., default center). PowerPoint’s radial fill follows the container aspect ratio and does not visually distinguish circle vs. ellipse or the size keyword — they are accepted as syntax but render the same farthest-corner ellipse on output. Only the center position changes the rendered result.
  • Both forms require two or more hex color stops; stop positions (%) are optional and distributed evenly when omitted.

Text Gradient

Paint the characters themselves with a linear-gradient() via textGradient on <Text>. Same syntax as backgroundGradient (angle + 2 or more hex color stops). Exported as a native PowerPoint gradient text fill (editable in PowerPoint, not rasterized). Takes precedence over color, and overrides per-run colors inside inline tags (<Span color="..."> etc.) so the whole text reads with one gradient. Useful for cover titles, KPI numerals, and pull quotes. Note: in browser environments use pptx.write()pptx.writeFile() falls back to plain pptxgenjs output without the gradient post-processing.

<Text fontSize="64" bold="true" textGradient="linear-gradient(90deg, #38BDF8 0%, #A78BFA 100%)">Gradient title</Text> <Text fontSize="56" bold="true" textGradient="linear-gradient(135deg, #F472B6, #FB923C)">¥84.2M</Text>

Background Image

Set a background image with backgroundImage.src and control sizing with backgroundImage.sizing:

<Text backgroundImage.src="./photo.jpg" backgroundImage.sizing="cover" w="400" h="300" color="FFFFFF">Text over image</Text>
PropertyValuesDescription
backgroundImage.srcURL / file path / base64Image source
backgroundImage.sizingcover / containcover fills area (default), contain fits within

Border

Add borders to any node with dot notation:

<Text border.color="E5E7EB" border.width="1" padding="16">Container with a light border</Text>

Border Properties

PropertyTypeDescription
border.colorhexBorder color
border.widthnumberBorder width (px)
border.dashTypestringLine style (see below)

Border Dash Types

See Common Properties in Nodes for available dash types.

<Text border.color="333333" border.width="2" border.dashType="dash" padding="16">Dashed border</Text>

Border Radius

Round corners with borderRadius:

<Text backgroundColor="1D4ED8" borderRadius="8" padding="16" color="FFFFFF">Rounded box</Text>

Per-Side Border

Style each edge independently with borderTop / borderRight / borderBottom / borderLeft. Each uses the same fields as border (color / width / dashType).

Per-side border example

<Text borderLeft.color="1D4ED8" borderLeft.width="6" padding.left="16">Accent bar</Text> <Text borderBottom.color="333333" borderBottom.width="3">Underlined heading</Text>
  • Per-side values merge field-by-field with the uniform border (per-side takes precedence) — border.color="E5E7EB" border.width="1" borderLeft.width="6" is a thin frame with a thick left accent.
  • Per-side borders cannot be combined with borderRadius. When both are specified, the per-side values are ignored and the uniform border style is used, and a PER_SIDE_BORDER_WITH_RADIUS diagnostic is emitted at build time.

Shadow

Add drop shadows to any node (except Line):

Shadow example

<VStack shadow.type="outer" shadow.blur="4" shadow.offset="2" shadow.color="000000" shadow.opacity="0.3" padding="16"> <Text>Card with shadow</Text> </VStack>

Shadow Properties

PropertyTypeDescription
shadow.typestringouter (default) / inner
shadow.blurnumberBlur radius
shadow.offsetnumberOffset distance
shadow.anglenumberAngle in degrees
shadow.colorhexShadow color
shadow.opacity0–1Shadow opacity

Opacity

Control background transparency with opacity (0 = fully transparent, 1 = fully opaque):

Opacity example

<Text backgroundColor="1D4ED8" opacity="0.5" padding="16">Semi-transparent blue background</Text>

Rotation

Text, Shape, Image, and Icon accept rotate as a number of degrees clockwise. Rotation is applied only when rendering to PowerPoint; yoga layout uses the unrotated bounding box, so the rotated node does not change sibling placement or the parent’s size.

Rotation example

<Text rotate="12">Rotated label</Text> <Shape shapeType="rect" w="120" h="60" rotate="-15" /> <Image src="sample.png" w="160" h="100" rotate="8" /> <Icon name="cpu" rotate="45" />

Rotated nodes are intentionally excluded from the NODE_OUT_OF_BOUNDS diagnostic because their final bounds cannot be derived from the static layout — verify them visually.

Overlay Pattern with Layer

Combine opacity with Layer for overlay effects:

Layer overlay example

<Layer w="800" h="400"> <Image src="./photo.jpg" w="800" h="400" /> <Shape shapeType="rect" w="800" h="400" fill.color="000000" fill.transparency="0.6" /> <VStack w="800" h="400" justifyContent="center" alignItems="center"> <Text fontSize="36" bold="true" color="FFFFFF">Overlay Title</Text> </VStack> </Layer>

Shape Fill and Line

Shape nodes use fill for background and line for outline (separate from the common border property):

<Shape shapeType="rect" w="200" h="100" fill.color="1D4ED8" fill.transparency="0" line.color="0F3B8E" line.width="2"> Styled shape </Shape>

Fill Properties

PropertyTypeDescription
fill.colorhexFill color
fill.transparency0–1Fill transparency (0 = opaque)

Line Properties

PropertyTypeDescription
line.colorhexOutline color
line.widthnumberOutline width (px)
line.dashTypestringSame dash types as border

Combining Styles

A practical example combining multiple styling techniques:

Combining styles example

<VStack w="max" h="max" padding="48" gap="24" backgroundColor="F8F9FA"> <!-- Title area --> <Text fontSize="36" bold="true" color="1A1A2E">Quarterly Report</Text> <Text fontSize="16" color="666666">Q4 2025 Results</Text> <!-- Card with shadow and border --> <HStack gap="16" w="max"> <VStack backgroundColor="FFFFFF" borderRadius="8" padding="24" gap="8" border.color="E5E7EB" border.width="1" shadow.blur="4" shadow.offset="2" shadow.color="000000" shadow.opacity="0.1"> <Text fontSize="12" color="999999">Revenue</Text> <Text fontSize="28" bold="true" color="16A34A">$1.2M</Text> </VStack> <VStack backgroundColor="FFFFFF" borderRadius="8" padding="24" gap="8" border.color="E5E7EB" border.width="1" shadow.blur="4" shadow.offset="2" shadow.color="000000" shadow.opacity="0.1"> <Text fontSize="12" color="999999">Growth</Text> <Text fontSize="28" bold="true" color="1D4ED8">+24%</Text> </VStack> </HStack> <!-- Highlighted note --> <Text fontSize="13" color="666666" highlight="FEF3C7"> Note: Figures are preliminary and subject to final audit. </Text> </VStack>
Last updated on