WP_Theme_JSON::update_button_width_declarationsprivate staticWP 7.1.0

Updates button width declarations to use a calc() formula for percentage values.

When a percentage width is set on the Button block via Global Styles, the resulting CSS needs to account for block gap spacing so that buttons tile correctly on a row (e.g. 4 buttons at 25% width all fit on one row).

This mirrors the dynamic calc() formula applied at the block instance level in the button block's stylesheet (style.scss).

Method of the class: WP_Theme_JSON{}

No Hooks.

Returns

Array. The updated feature declarations.

Usage

$result = WP_Theme_JSON::update_button_width_declarations( $feature_declarations, $settings );
$feature_declarations(array) (required)
The feature declarations keyed by selector.
$settings(array) (required)
The theme.json settings.

Changelog

Since 7.1.0 Introduced.

WP_Theme_JSON::update_button_width_declarations() code WP 7.1

private static function update_button_width_declarations( $feature_declarations, $settings ) {
	if ( ! isset( $feature_declarations['.wp-block-button'] ) ) {
		return $feature_declarations;
	}

	foreach ( $feature_declarations['.wp-block-button'] as &$declaration ) {
		if ( 'width' !== $declaration['name'] || ! isset( $declaration['value'] ) ) {
			continue;
		}

		$value      = $declaration['value'];
		$percentage = null;

		// Case 1: Direct percentage value e.g. "25%".
		if ( is_string( $value ) && str_ends_with( $value, '%' ) ) {
			$percentage = (float) $value;
		}

		// Case 2: Preset CSS var e.g. "var(--wp--preset--dimension--50)".
		if ( null === $percentage && is_string( $value ) && str_starts_with( $value, 'var(--wp--preset--dimension--' ) ) {
			// Extract the slug from the var name.
			$slug = substr( $value, strlen( 'var(--wp--preset--dimension--' ), -1 );

			/*
			 * Look up the preset size across all origins.
			 * Check block-level settings first (core/button), then top-level settings.
			 */
			$dimension_sizes = ( $settings['blocks']['core/button']['dimensions']['dimensionSizes'] ?? array() )
				+ ( $settings['dimensions']['dimensionSizes'] ?? array() );
			foreach ( $dimension_sizes as $origin_sizes ) {
				if ( ! is_array( $origin_sizes ) ) {
					continue;
				}
				foreach ( $origin_sizes as $preset ) {
					if ( isset( $preset['slug'] ) && $slug === $preset['slug'] && isset( $preset['size'] ) ) {
						$size = $preset['size'];
						if ( is_string( $size ) && str_ends_with( $size, '%' ) ) {
							$percentage = (float) $size;
						}
						break 2;
					}
				}
			}
		}

		if ( null === $percentage ) {
			continue;
		}

		/*
		 * Apply the same calc() formula as the block instance level (style.scss).
		 * The numeric percentage value is used as a unitless number:
		 * - Multiplied by 1% to get the percentage width.
		 * - Divided by 100 to calculate the gap adjustment proportion.
		 */
		$declaration['value'] = sprintf(
			'calc(%s * 1%% - (var(--wp--style--block-gap, 0.5em) * (1 - %s / 100)))',
			$percentage,
			$percentage
		);
	}
	unset( $declaration );

	return $feature_declarations;
}