SharePoint Online JSON Column Formatting: Declarative Rendering Without Code
SharePoint Online JSON column formatting changes only the visual rendering of a column in modern views. It uses declarative JSON with tokens like @currentField and does not alter stored values or enforce security.
27 Oct 2025, 13:36 UTC

What JSON column formatting actually does
SharePoint Online JSON column formatting changes how a column value appears in modern list views, view web parts, and Microsoft Lists surfaces. It does not modify the stored value, enforce security, or run custom logic. The formatter is a declarative JSON object evaluated client-side by the modern UI renderer using a fixed schema and tokens such as @currentField, @me, @now, and @currentWeb. If you need to hide data from users with read access, use column-level permissions, sensitivity labels, or separate lists—formatting alone will not prevent the value from appearing in exports, Microsoft Graph responses, or list forms.
Worked example: color-coding a Choice column
Assume a list has a Choice column with internal name Status and choices Blocked, In Progress, and Completed. Paste the following JSON into List settings → Column settings → Format this column, then save. You need list owner or editor permissions to save column formatting.
{
"$schema": "https://developer.microsoft.com/json-schemas/sp/v2/column-formatting.schema.json",
"elmType": "span",
"style": {
"display": "inline-block",
"padding": "2px 8px",
"border-radius": "12px",
"font-weight": "600",
"font-size": "13px",
"color": "white",
"background-color": "={
if(@currentField == 'Blocked', '#d13438',
if(@currentField == 'In Progress', '#ffb900',
if(@currentField == 'Completed', '#107c10',
'#666666'))}"
}
},
"txtContent": "@currentField"
}
The renderer evaluates the background-color expression for each row. @currentField resolves to the raw choice value. Expected result: Blocked renders red, In Progress renders yellow, and Completed renders green. Arbitrary CSS class names, external stylesheets, and JavaScript are ignored.
Where the formatting appears
- Modern list view (grid and compact)
- List view web part on a modern page
- Microsoft Lists web and mobile apps
- Embedded lists in Teams tabs
It does not apply to classic views, list forms, Excel exports, or API responses. The underlying field value remains unchanged in all those contexts.
Tokens available in the formatter
| Token | Resolves to |
|---|---|
@currentField | Raw value of the column being formatted |
@me | Current user's email or UPN |
@now | Current date and time in ISO 8601 UTC |
@currentWeb | Absolute URL of the current site |
[$FieldInternalName] | Value of another column in the same row |
Expressions use a limited Excel-like syntax: if(), concat(), substring(), toLowerCase(), toUpperCase(), indexOf(), length(), and arithmetic operators. Loops, variables, and custom functions are not supported.
Common mistakes that silently fail
Using display name instead of internal name
When referencing another column via [$FieldInternalName], use the internal programmatic name. The display name "Task Status" might map to Task_x0020_Status or TaskStatus. A mismatched token evaluates to empty with no error message. Retrieve the internal name from the column settings URL Field= query parameter or via /_api/web/lists/getbytitle('ListName')/fields?$select=InternalName,Title.
Assuming formatting propagates to new views
Formatting is stored on the column definition as the CustomFormatter property. A new view renders the formatted column only if the view includes that column and the rendering context invokes the column formatter. Custom JSON view formatting can override column-level formatting.
Exceeding JSON size or schema limits
The formatter JSON is stored as a string property on the field. No hard public limit is documented, but very large nested objects may be truncated or rejected on save. Prefer a lookup column or calculated column that reduces values to a small set of keys, then format against those keys.
Treating formatting as a security control
A user with read permission can open the list in grid view, export to Excel, or call /_api/web/lists/getbytitle('ListName')/items and see the unformatted value. If the column contains PII or credentials, apply column-level permissions (requires SharePoint Advanced Management), sensitivity labels with encryption, or move the data to a separate list with unique permissions.
Verification steps
- Open the list in a modern browser and confirm the colored pills render for each choice.
- Switch to a read-only account or an InPrivate window with a different identity and confirm the same visual rendering appears; formatting is not permission-aware.
- Export the list to Excel; the
Statuscolumn should show plain text values without HTML or style markup. - Call the REST endpoint
/_api/web/lists/getbytitle('ListName')/fields/getbyinternalnameortitle('Status')/CustomFormatterto confirm the JSON is persisted. - Create a new view, add the
Statuscolumn, and verify the formatter appears in that view context.
Limitations to plan for
- No JavaScript, external CSS,
fetch, or DOM manipulation. - Cannot reference columns from other lists or parent/child relationships.
- Date/time comparisons must use
@nowin UTC and ISO strings; time-zone handling is manual. - Hyperlink and picture columns require specific
elmTypevalues such asaorimgand theattributesproperty forhreforsrc. - Multi-value choice or person columns render as arrays; use
join(', ')orlength()in expressions.
When to choose view formatting instead
Column formatting applies to a single field across all views that include it. View formatting controls the entire row layout, enables row-level actions such as buttons and inline edit, and can reference multiple columns simultaneously. Use view formatting when you need a custom card layout, row highlighting based on multiple fields, or action buttons that call Power Automate flows. Column formatting remains the lighter-weight choice for simple value-to-style mappings.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.