Back to blog
May 29, 2025
2 min read

JavaScript API of the Week: Intl.ListFormat.formatToParts()

Learn how to use `Intl.ListFormat.formatToParts()` for customizable and localized list formatting in JavaScript.

Introduction

Internationalization can be a daunting task, particularly when formatting dynamic, user-generated content. Recently, I had to adjust a checkout process so that it lists all selected items, making it easy for the user to confirm them. My client requested to display a confirmation message such as “Confirm your purchase of A, B, and C.” Manually writing a solution for this isn’t too difficult as it’s mostly three or four different cases, assuming you only support a single language. However, custom-built solutions frequently overlook subtle grammatical rules, such as the Oxford comma.

Naturally, I went ahead and decided to make use of Intl.ListFormatter.format() which allows me to provide an array of items to produce grammatically correct and locale-aware output:

> const listFormat = new Intl.ListFormat('en')
> listFormat.format(['One', 'Two', 'Three'])
'One, Two, and Three'

Highlighting items

By this stage, I was quite satisfied that the Intl.ListFormatter API simplified the formatting of elements. Sadly, it falls short when deeper customization is required, such as highlighting the original items and not the literals used to combine them. Fortunately, a related API, namely Intl.ListFormatter.formatToParts(), yields a structured array of parts, enabling fine-grained control over the rendering logic:

> const listFormat = new Intl.ListFormat('en')
> listFormat.formatToParts(['One', 'Two', 'Three'])
[
  { type: 'element', value: 'One' },
  { type: 'literal', value: ', ' },
  { type: 'element', value: 'Two' },
  { type: 'literal', value: ', and ' },
  { type: 'element', value: 'Three' }
]

The resulting array is well-suited for iterating over individual components - both literals and user-supplied elements - render literals (strings that are part of the pattern) verbatim, and our original input elements using custom formatting such as highlighting. This becomes elegant and easy to implement in a custom component:

function FormattedElements({ elements }: { elements: string[] }) {
	const listFormat = new Intl.ListFormat('en')
	return (
		<div>
			{listFormat.formatToParts(elements).map((item) => (
				<span
					className={cn({
						'text-lime-400': item.type === 'element',
					})}
				>
					{item.value}
				</span>
			))}
		</div>
	)
}

Interactive Example

Why don’t you give it a try? Below is the <FormattedElements /> component from the previous section. It dynamically demonstrates how parts of the list can be styled or transformed based on their type, making it an excellent foundation for interactive UIs.