Headless Block Styles
Headless Block Styles brings full Gutenberg block styling to any headless frontend (e.g. Next.js) using the WordPress REST API — no WPGraphQL required.
It does two things:
- Serves the global stylesheet (
wp_get_global_stylesheet()): all--wp--preset--*CSS variables, preset classes (has-*-color,has-*-font-size, …), and theme/user styles — the CSS WordPress would normally enqueue on its own frontend. - Computes per-block inline styles on the server with the WordPress Style Engine and adds a
block_datafield to post REST responses, so your frontend receives ready-to-spread React style objects instead of deriving them from raw block attributes in JavaScript.
REST API
GET /wp-json/headless-block-styles/v1/stylesheet
types— comma-separated subset ofvariables,presets,styles,base-layout-styles. Omit for all.format—json(default) orcss(raw CSS, usable directly in a<link>tag).
GET /wp-json/headless-block-styles/v1/theme
Returns merged theme.json settings (wp_get_global_settings()) — color palette, font sizes, layout sizes.
block_data field on posts and pages
Every REST-enabled post type response gains a block_data field: the parsed block tree where each block carries inlineStyles (camelCase, ready for a React style prop), classNames (editor-parity has-* classes), attributes, innerHTML, and recursive innerBlocks.
inlineStyles covers the `style` attribute (spacing, borders, typography, colors — via the WP Style Engine), preset attributes (`backgroundColor`, `textColor`, `gradient`, `borderColor`, `fontSize`, `fontFamily`), and layout (`width`, `height`, `layout.contentSize/wideSize/justifyContent`).
rendered_blocks field on posts and pages
For rendering WordPress’s HTML faithfully: returns html, css, and svg — the rendered block markup together with the block-support CSS WordPress generates at render time (layout container rules, element link/button colors, duotone filters) and the duotone SVG definitions. On a normal WordPress frontend this CSS is printed in a <style> tag and never reaches REST consumers; here it is captured from the same render as the returned HTML so the generated class names always match.
Not needed on a request? Exclude fields: /wp/v2/posts?_fields=id,title,content.
Filters
headless_block_styles_block_inline_styles— modify a block’s computed style object. Args:$styles,$attrs.headless_block_styles_block_class_names— modify a block’s computed class names. Args:$classnames,$attrs.headless_block_styles_post_types— which post types get theblock_datafield.
Full documentation and Next.js usage examples: github.com/FuSan21/headless-block-styles