wp_get_layout_style

The timeline below displays how wordpress function wp_get_layout_style has changed across different WordPress versions. If a version is not listed, refer to the next available version below.

WordPress Version: 6.4

/**
 * Generates the CSS corresponding to the provided layout.
 *
 * @since 5.9.0
 * @since 6.1.0 Added `$block_spacing` param, use style engine to enqueue styles.
 * @since 6.3.0 Added grid layout type.
 * @access private
 *
 * @param string               $selector                      CSS selector.
 * @param array                $layout                        Layout object. The one that is passed has already checked
 *                                                            the existence of default block layout.
 * @param bool                 $has_block_gap_support         Optional. Whether the theme has support for the block gap. Default false.
 * @param string|string[]|null $gap_value                     Optional. The block gap value to apply. Default null.
 * @param bool                 $should_skip_gap_serialization Optional. Whether to skip applying the user-defined value set in the editor. Default false.
 * @param string               $fallback_gap_value            Optional. The block gap value to apply. Default '0.5em'.
 * @param array|null           $block_spacing                 Optional. Custom spacing set on the block. Default null.
 * @return string CSS styles on success. Else, empty string.
 */
function wp_get_layout_style($selector, $layout, $has_block_gap_support = false, $gap_value = null, $should_skip_gap_serialization = false, $fallback_gap_value = '0.5em', $block_spacing = null)
{
    $layout_type = isset($layout['type']) ? $layout['type'] : 'default';
    $layout_styles = array();
    if ('default' === $layout_type) {
        if ($has_block_gap_support) {
            if (is_array($gap_value)) {
                $gap_value = isset($gap_value['top']) ? $gap_value['top'] : null;
            }
            if (null !== $gap_value && !$should_skip_gap_serialization) {
                // Get spacing CSS variable from preset value if provided.
                if (is_string($gap_value) && str_contains($gap_value, 'var:preset|spacing|')) {
                    $index_to_splice = strrpos($gap_value, '|') + 1;
                    $slug = _wp_to_kebab_case(substr($gap_value, $index_to_splice));
                    $gap_value = "var(--wp--preset--spacing--{$slug})";
                }
                array_push($layout_styles, array('selector' => "{$selector} > *", 'declarations' => array('margin-block-start' => '0', 'margin-block-end' => '0')), array('selector' => "{$selector}{$selector} > * + *", 'declarations' => array('margin-block-start' => $gap_value, 'margin-block-end' => '0')));
            }
        }
    } elseif ('constrained' === $layout_type) {
        $content_size = isset($layout['contentSize']) ? $layout['contentSize'] : '';
        $wide_size = isset($layout['wideSize']) ? $layout['wideSize'] : '';
        $justify_content = isset($layout['justifyContent']) ? $layout['justifyContent'] : 'center';
        $all_max_width_value = $content_size ? $content_size : $wide_size;
        $wide_max_width_value = $wide_size ? $wide_size : $content_size;
        // Make sure there is a single CSS rule, and all tags are stripped for security.
        $all_max_width_value = safecss_filter_attr(explode(';', $all_max_width_value)[0]);
        $wide_max_width_value = safecss_filter_attr(explode(';', $wide_max_width_value)[0]);
        $margin_left = ('left' === $justify_content) ? '0 !important' : 'auto !important';
        $margin_right = ('right' === $justify_content) ? '0 !important' : 'auto !important';
        if ($content_size || $wide_size) {
            array_push($layout_styles, array('selector' => "{$selector} > :where(:not(.alignleft):not(.alignright):not(.alignfull))", 'declarations' => array('max-width' => $all_max_width_value, 'margin-left' => $margin_left, 'margin-right' => $margin_right)), array('selector' => "{$selector} > .alignwide", 'declarations' => array('max-width' => $wide_max_width_value)), array('selector' => "{$selector} .alignfull", 'declarations' => array('max-width' => 'none')));
            if (isset($block_spacing)) {
                $block_spacing_values = wp_style_engine_get_styles(array('spacing' => $block_spacing));
                /*
                 * Handle negative margins for alignfull children of blocks with custom padding set.
                 * They're added separately because padding might only be set on one side.
                 */
                if (isset($block_spacing_values['declarations']['padding-right'])) {
                    $padding_right = $block_spacing_values['declarations']['padding-right'];
                    $layout_styles[] = array('selector' => "{$selector} > .alignfull", 'declarations' => array('margin-right' => "calc({$padding_right} * -1)"));
                }
                if (isset($block_spacing_values['declarations']['padding-left'])) {
                    $padding_left = $block_spacing_values['declarations']['padding-left'];
                    $layout_styles[] = array('selector' => "{$selector} > .alignfull", 'declarations' => array('margin-left' => "calc({$padding_left} * -1)"));
                }
            }
        }
        if ('left' === $justify_content) {
            $layout_styles[] = array('selector' => "{$selector} > :where(:not(.alignleft):not(.alignright):not(.alignfull))", 'declarations' => array('margin-left' => '0 !important'));
        }
        if ('right' === $justify_content) {
            $layout_styles[] = array('selector' => "{$selector} > :where(:not(.alignleft):not(.alignright):not(.alignfull))", 'declarations' => array('margin-right' => '0 !important'));
        }
        if ($has_block_gap_support) {
            if (is_array($gap_value)) {
                $gap_value = isset($gap_value['top']) ? $gap_value['top'] : null;
            }
            if (null !== $gap_value && !$should_skip_gap_serialization) {
                // Get spacing CSS variable from preset value if provided.
                if (is_string($gap_value) && str_contains($gap_value, 'var:preset|spacing|')) {
                    $index_to_splice = strrpos($gap_value, '|') + 1;
                    $slug = _wp_to_kebab_case(substr($gap_value, $index_to_splice));
                    $gap_value = "var(--wp--preset--spacing--{$slug})";
                }
                array_push($layout_styles, array('selector' => "{$selector} > *", 'declarations' => array('margin-block-start' => '0', 'margin-block-end' => '0')), array('selector' => "{$selector}{$selector} > * + *", 'declarations' => array('margin-block-start' => $gap_value, 'margin-block-end' => '0')));
            }
        }
    } elseif ('flex' === $layout_type) {
        $layout_orientation = isset($layout['orientation']) ? $layout['orientation'] : 'horizontal';
        $justify_content_options = array('left' => 'flex-start', 'right' => 'flex-end', 'center' => 'center');
        $vertical_alignment_options = array('top' => 'flex-start', 'center' => 'center', 'bottom' => 'flex-end');
        if ('horizontal' === $layout_orientation) {
            $justify_content_options += array('space-between' => 'space-between');
            $vertical_alignment_options += array('stretch' => 'stretch');
        } else {
            $justify_content_options += array('stretch' => 'stretch');
            $vertical_alignment_options += array('space-between' => 'space-between');
        }
        if (!empty($layout['flexWrap']) && 'nowrap' === $layout['flexWrap']) {
            $layout_styles[] = array('selector' => $selector, 'declarations' => array('flex-wrap' => 'nowrap'));
        }
        if ($has_block_gap_support && isset($gap_value)) {
            $combined_gap_value = '';
            $gap_sides = is_array($gap_value) ? array('top', 'left') : array('top');
            foreach ($gap_sides as $gap_side) {
                $process_value = $gap_value;
                if (is_array($gap_value)) {
                    $process_value = isset($gap_value[$gap_side]) ? $gap_value[$gap_side] : $fallback_gap_value;
                }
                // Get spacing CSS variable from preset value if provided.
                if (is_string($process_value) && str_contains($process_value, 'var:preset|spacing|')) {
                    $index_to_splice = strrpos($process_value, '|') + 1;
                    $slug = _wp_to_kebab_case(substr($process_value, $index_to_splice));
                    $process_value = "var(--wp--preset--spacing--{$slug})";
                }
                $combined_gap_value .= "{$process_value} ";
            }
            $gap_value = trim($combined_gap_value);
            if (null !== $gap_value && !$should_skip_gap_serialization) {
                $layout_styles[] = array('selector' => $selector, 'declarations' => array('gap' => $gap_value));
            }
        }
        if ('horizontal' === $layout_orientation) {
            /*
             * Add this style only if is not empty for backwards compatibility,
             * since we intend to convert blocks that had flex layout implemented
             * by custom css.
             */
            if (!empty($layout['justifyContent']) && array_key_exists($layout['justifyContent'], $justify_content_options)) {
                $layout_styles[] = array('selector' => $selector, 'declarations' => array('justify-content' => $justify_content_options[$layout['justifyContent']]));
            }
            if (!empty($layout['verticalAlignment']) && array_key_exists($layout['verticalAlignment'], $vertical_alignment_options)) {
                $layout_styles[] = array('selector' => $selector, 'declarations' => array('align-items' => $vertical_alignment_options[$layout['verticalAlignment']]));
            }
        } else {
            $layout_styles[] = array('selector' => $selector, 'declarations' => array('flex-direction' => 'column'));
            if (!empty($layout['justifyContent']) && array_key_exists($layout['justifyContent'], $justify_content_options)) {
                $layout_styles[] = array('selector' => $selector, 'declarations' => array('align-items' => $justify_content_options[$layout['justifyContent']]));
            } else {
                $layout_styles[] = array('selector' => $selector, 'declarations' => array('align-items' => 'flex-start'));
            }
            if (!empty($layout['verticalAlignment']) && array_key_exists($layout['verticalAlignment'], $vertical_alignment_options)) {
                $layout_styles[] = array('selector' => $selector, 'declarations' => array('justify-content' => $vertical_alignment_options[$layout['verticalAlignment']]));
            }
        }
    } elseif ('grid' === $layout_type) {
        if (!empty($layout['columnCount'])) {
            $layout_styles[] = array('selector' => $selector, 'declarations' => array('grid-template-columns' => 'repeat(' . $layout['columnCount'] . ', minmax(0, 1fr))'));
        } else {
            $minimum_column_width = (!empty($layout['minimumColumnWidth'])) ? $layout['minimumColumnWidth'] : '12rem';
            $layout_styles[] = array('selector' => $selector, 'declarations' => array('grid-template-columns' => 'repeat(auto-fill, minmax(min(' . $minimum_column_width . ', 100%), 1fr))'));
        }
        if ($has_block_gap_support && isset($gap_value)) {
            $combined_gap_value = '';
            $gap_sides = is_array($gap_value) ? array('top', 'left') : array('top');
            foreach ($gap_sides as $gap_side) {
                $process_value = $gap_value;
                if (is_array($gap_value)) {
                    $process_value = isset($gap_value[$gap_side]) ? $gap_value[$gap_side] : $fallback_gap_value;
                }
                // Get spacing CSS variable from preset value if provided.
                if (is_string($process_value) && str_contains($process_value, 'var:preset|spacing|')) {
                    $index_to_splice = strrpos($process_value, '|') + 1;
                    $slug = _wp_to_kebab_case(substr($process_value, $index_to_splice));
                    $process_value = "var(--wp--preset--spacing--{$slug})";
                }
                $combined_gap_value .= "{$process_value} ";
            }
            $gap_value = trim($combined_gap_value);
            if (null !== $gap_value && !$should_skip_gap_serialization) {
                $layout_styles[] = array('selector' => $selector, 'declarations' => array('gap' => $gap_value));
            }
        }
    }
    if (!empty($layout_styles)) {
        /*
         * Add to the style engine store to enqueue and render layout styles.
         * Return compiled layout styles to retain backwards compatibility.
         * Since https://github.com/WordPress/gutenberg/pull/42452,
         * wp_enqueue_block_support_styles is no longer called in this block supports file.
         */
        return wp_style_engine_get_stylesheet_from_css_rules($layout_styles, array('context' => 'block-supports', 'prettify' => false));
    }
    return '';
}

WordPress Version: 6.3

/**
 * Generates the CSS corresponding to the provided layout.
 *
 * @since 5.9.0
 * @since 6.1.0 Added `$block_spacing` param, use style engine to enqueue styles.
 * @since 6.3.0 Added grid layout type.
 * @access private
 *
 * @param string               $selector                      CSS selector.
 * @param array                $layout                        Layout object. The one that is passed has already checked
 *                                                            the existence of default block layout.
 * @param bool                 $has_block_gap_support         Optional. Whether the theme has support for the block gap. Default false.
 * @param string|string[]|null $gap_value                     Optional. The block gap value to apply. Default null.
 * @param bool                 $should_skip_gap_serialization Optional. Whether to skip applying the user-defined value set in the editor. Default false.
 * @param string               $fallback_gap_value            Optional. The block gap value to apply. Default '0.5em'.
 * @param array|null           $block_spacing                 Optional. Custom spacing set on the block. Default null.
 * @return string CSS styles on success. Else, empty string.
 */
function wp_get_layout_style($selector, $layout, $has_block_gap_support = false, $gap_value = null, $should_skip_gap_serialization = false, $fallback_gap_value = '0.5em', $block_spacing = null)
{
    $layout_type = isset($layout['type']) ? $layout['type'] : 'default';
    $layout_styles = array();
    if ('default' === $layout_type) {
        if ($has_block_gap_support) {
            if (is_array($gap_value)) {
                $gap_value = isset($gap_value['top']) ? $gap_value['top'] : null;
            }
            if (null !== $gap_value && !$should_skip_gap_serialization) {
                // Get spacing CSS variable from preset value if provided.
                if (is_string($gap_value) && str_contains($gap_value, 'var:preset|spacing|')) {
                    $index_to_splice = strrpos($gap_value, '|') + 1;
                    $slug = _wp_to_kebab_case(substr($gap_value, $index_to_splice));
                    $gap_value = "var(--wp--preset--spacing--{$slug})";
                }
                array_push($layout_styles, array('selector' => "{$selector} > *", 'declarations' => array('margin-block-start' => '0', 'margin-block-end' => '0')), array('selector' => "{$selector}{$selector} > * + *", 'declarations' => array('margin-block-start' => $gap_value, 'margin-block-end' => '0')));
            }
        }
    } elseif ('constrained' === $layout_type) {
        $content_size = isset($layout['contentSize']) ? $layout['contentSize'] : '';
        $wide_size = isset($layout['wideSize']) ? $layout['wideSize'] : '';
        $justify_content = isset($layout['justifyContent']) ? $layout['justifyContent'] : 'center';
        $all_max_width_value = $content_size ? $content_size : $wide_size;
        $wide_max_width_value = $wide_size ? $wide_size : $content_size;
        // Make sure there is a single CSS rule, and all tags are stripped for security.
        $all_max_width_value = safecss_filter_attr(explode(';', $all_max_width_value)[0]);
        $wide_max_width_value = safecss_filter_attr(explode(';', $wide_max_width_value)[0]);
        $margin_left = ('left' === $justify_content) ? '0 !important' : 'auto !important';
        $margin_right = ('right' === $justify_content) ? '0 !important' : 'auto !important';
        if ($content_size || $wide_size) {
            array_push($layout_styles, array('selector' => "{$selector} > :where(:not(.alignleft):not(.alignright):not(.alignfull))", 'declarations' => array('max-width' => $all_max_width_value, 'margin-left' => $margin_left, 'margin-right' => $margin_right)), array('selector' => "{$selector} > .alignwide", 'declarations' => array('max-width' => $wide_max_width_value)), array('selector' => "{$selector} .alignfull", 'declarations' => array('max-width' => 'none')));
            if (isset($block_spacing)) {
                $block_spacing_values = wp_style_engine_get_styles(array('spacing' => $block_spacing));
                /*
                 * Handle negative margins for alignfull children of blocks with custom padding set.
                 * They're added separately because padding might only be set on one side.
                 */
                if (isset($block_spacing_values['declarations']['padding-right'])) {
                    $padding_right = $block_spacing_values['declarations']['padding-right'];
                    $layout_styles[] = array('selector' => "{$selector} > .alignfull", 'declarations' => array('margin-right' => "calc({$padding_right} * -1)"));
                }
                if (isset($block_spacing_values['declarations']['padding-left'])) {
                    $padding_left = $block_spacing_values['declarations']['padding-left'];
                    $layout_styles[] = array('selector' => "{$selector} > .alignfull", 'declarations' => array('margin-left' => "calc({$padding_left} * -1)"));
                }
            }
        }
        if ('left' === $justify_content) {
            $layout_styles[] = array('selector' => "{$selector} > :where(:not(.alignleft):not(.alignright):not(.alignfull))", 'declarations' => array('margin-left' => '0 !important'));
        }
        if ('right' === $justify_content) {
            $layout_styles[] = array('selector' => "{$selector} > :where(:not(.alignleft):not(.alignright):not(.alignfull))", 'declarations' => array('margin-right' => '0 !important'));
        }
        if ($has_block_gap_support) {
            if (is_array($gap_value)) {
                $gap_value = isset($gap_value['top']) ? $gap_value['top'] : null;
            }
            if (null !== $gap_value && !$should_skip_gap_serialization) {
                // Get spacing CSS variable from preset value if provided.
                if (is_string($gap_value) && str_contains($gap_value, 'var:preset|spacing|')) {
                    $index_to_splice = strrpos($gap_value, '|') + 1;
                    $slug = _wp_to_kebab_case(substr($gap_value, $index_to_splice));
                    $gap_value = "var(--wp--preset--spacing--{$slug})";
                }
                array_push($layout_styles, array('selector' => "{$selector} > *", 'declarations' => array('margin-block-start' => '0', 'margin-block-end' => '0')), array('selector' => "{$selector}{$selector} > * + *", 'declarations' => array('margin-block-start' => $gap_value, 'margin-block-end' => '0')));
            }
        }
    } elseif ('flex' === $layout_type) {
        $layout_orientation = isset($layout['orientation']) ? $layout['orientation'] : 'horizontal';
        $justify_content_options = array('left' => 'flex-start', 'right' => 'flex-end', 'center' => 'center');
        $vertical_alignment_options = array('top' => 'flex-start', 'center' => 'center', 'bottom' => 'flex-end');
        if ('horizontal' === $layout_orientation) {
            $justify_content_options += array('space-between' => 'space-between');
            $vertical_alignment_options += array('stretch' => 'stretch');
        } else {
            $justify_content_options += array('stretch' => 'stretch');
            $vertical_alignment_options += array('space-between' => 'space-between');
        }
        if (!empty($layout['flexWrap']) && 'nowrap' === $layout['flexWrap']) {
            $layout_styles[] = array('selector' => $selector, 'declarations' => array('flex-wrap' => 'nowrap'));
        }
        if ($has_block_gap_support && isset($gap_value)) {
            $combined_gap_value = '';
            $gap_sides = is_array($gap_value) ? array('top', 'left') : array('top');
            foreach ($gap_sides as $gap_side) {
                $process_value = is_string($gap_value) ? $gap_value : _wp_array_get($gap_value, array($gap_side), $fallback_gap_value);
                // Get spacing CSS variable from preset value if provided.
                if (is_string($process_value) && str_contains($process_value, 'var:preset|spacing|')) {
                    $index_to_splice = strrpos($process_value, '|') + 1;
                    $slug = _wp_to_kebab_case(substr($process_value, $index_to_splice));
                    $process_value = "var(--wp--preset--spacing--{$slug})";
                }
                $combined_gap_value .= "{$process_value} ";
            }
            $gap_value = trim($combined_gap_value);
            if (null !== $gap_value && !$should_skip_gap_serialization) {
                $layout_styles[] = array('selector' => $selector, 'declarations' => array('gap' => $gap_value));
            }
        }
        if ('horizontal' === $layout_orientation) {
            /*
             * Add this style only if is not empty for backwards compatibility,
             * since we intend to convert blocks that had flex layout implemented
             * by custom css.
             */
            if (!empty($layout['justifyContent']) && array_key_exists($layout['justifyContent'], $justify_content_options)) {
                $layout_styles[] = array('selector' => $selector, 'declarations' => array('justify-content' => $justify_content_options[$layout['justifyContent']]));
            }
            if (!empty($layout['verticalAlignment']) && array_key_exists($layout['verticalAlignment'], $vertical_alignment_options)) {
                $layout_styles[] = array('selector' => $selector, 'declarations' => array('align-items' => $vertical_alignment_options[$layout['verticalAlignment']]));
            }
        } else {
            $layout_styles[] = array('selector' => $selector, 'declarations' => array('flex-direction' => 'column'));
            if (!empty($layout['justifyContent']) && array_key_exists($layout['justifyContent'], $justify_content_options)) {
                $layout_styles[] = array('selector' => $selector, 'declarations' => array('align-items' => $justify_content_options[$layout['justifyContent']]));
            } else {
                $layout_styles[] = array('selector' => $selector, 'declarations' => array('align-items' => 'flex-start'));
            }
            if (!empty($layout['verticalAlignment']) && array_key_exists($layout['verticalAlignment'], $vertical_alignment_options)) {
                $layout_styles[] = array('selector' => $selector, 'declarations' => array('justify-content' => $vertical_alignment_options[$layout['verticalAlignment']]));
            }
        }
    } elseif ('grid' === $layout_type) {
        if (!empty($layout['columnCount'])) {
            $layout_styles[] = array('selector' => $selector, 'declarations' => array('grid-template-columns' => 'repeat(' . $layout['columnCount'] . ', minmax(0, 1fr))'));
        } else {
            $minimum_column_width = (!empty($layout['minimumColumnWidth'])) ? $layout['minimumColumnWidth'] : '12rem';
            $layout_styles[] = array('selector' => $selector, 'declarations' => array('grid-template-columns' => 'repeat(auto-fill, minmax(min(' . $minimum_column_width . ', 100%), 1fr))'));
        }
        if ($has_block_gap_support && isset($gap_value)) {
            $combined_gap_value = '';
            $gap_sides = is_array($gap_value) ? array('top', 'left') : array('top');
            foreach ($gap_sides as $gap_side) {
                $process_value = is_string($gap_value) ? $gap_value : _wp_array_get($gap_value, array($gap_side), $fallback_gap_value);
                // Get spacing CSS variable from preset value if provided.
                if (is_string($process_value) && str_contains($process_value, 'var:preset|spacing|')) {
                    $index_to_splice = strrpos($process_value, '|') + 1;
                    $slug = _wp_to_kebab_case(substr($process_value, $index_to_splice));
                    $process_value = "var(--wp--preset--spacing--{$slug})";
                }
                $combined_gap_value .= "{$process_value} ";
            }
            $gap_value = trim($combined_gap_value);
            if (null !== $gap_value && !$should_skip_gap_serialization) {
                $layout_styles[] = array('selector' => $selector, 'declarations' => array('gap' => $gap_value));
            }
        }
    }
    if (!empty($layout_styles)) {
        /*
         * Add to the style engine store to enqueue and render layout styles.
         * Return compiled layout styles to retain backwards compatibility.
         * Since https://github.com/WordPress/gutenberg/pull/42452,
         * wp_enqueue_block_support_styles is no longer called in this block supports file.
         */
        return wp_style_engine_get_stylesheet_from_css_rules($layout_styles, array('context' => 'block-supports', 'prettify' => false));
    }
    return '';
}

WordPress Version: 6.2

/**
 * Generates the CSS corresponding to the provided layout.
 *
 * @since 5.9.0
 * @since 6.1.0 Added `$block_spacing` param, use style engine to enqueue styles.
 * @access private
 *
 * @param string               $selector                      CSS selector.
 * @param array                $layout                        Layout object. The one that is passed has already checked
 *                                                            the existence of default block layout.
 * @param bool                 $has_block_gap_support         Optional. Whether the theme has support for the block gap. Default false.
 * @param string|string[]|null $gap_value                     Optional. The block gap value to apply. Default null.
 * @param bool                 $should_skip_gap_serialization Optional. Whether to skip applying the user-defined value set in the editor. Default false.
 * @param string               $fallback_gap_value            Optional. The block gap value to apply. Default '0.5em'.
 * @param array|null           $block_spacing                 Optional. Custom spacing set on the block. Default null.
 * @return string CSS styles on success. Else, empty string.
 */
function wp_get_layout_style($selector, $layout, $has_block_gap_support = false, $gap_value = null, $should_skip_gap_serialization = false, $fallback_gap_value = '0.5em', $block_spacing = null)
{
    $layout_type = isset($layout['type']) ? $layout['type'] : 'default';
    $layout_styles = array();
    if ('default' === $layout_type) {
        if ($has_block_gap_support) {
            if (is_array($gap_value)) {
                $gap_value = isset($gap_value['top']) ? $gap_value['top'] : null;
            }
            if (null !== $gap_value && !$should_skip_gap_serialization) {
                // Get spacing CSS variable from preset value if provided.
                if (is_string($gap_value) && str_contains($gap_value, 'var:preset|spacing|')) {
                    $index_to_splice = strrpos($gap_value, '|') + 1;
                    $slug = _wp_to_kebab_case(substr($gap_value, $index_to_splice));
                    $gap_value = "var(--wp--preset--spacing--{$slug})";
                }
                array_push($layout_styles, array('selector' => "{$selector} > *", 'declarations' => array('margin-block-start' => '0', 'margin-block-end' => '0')), array('selector' => "{$selector}{$selector} > * + *", 'declarations' => array('margin-block-start' => $gap_value, 'margin-block-end' => '0')));
            }
        }
    } elseif ('constrained' === $layout_type) {
        $content_size = isset($layout['contentSize']) ? $layout['contentSize'] : '';
        $wide_size = isset($layout['wideSize']) ? $layout['wideSize'] : '';
        $justify_content = isset($layout['justifyContent']) ? $layout['justifyContent'] : 'center';
        $all_max_width_value = $content_size ? $content_size : $wide_size;
        $wide_max_width_value = $wide_size ? $wide_size : $content_size;
        // Make sure there is a single CSS rule, and all tags are stripped for security.
        $all_max_width_value = safecss_filter_attr(explode(';', $all_max_width_value)[0]);
        $wide_max_width_value = safecss_filter_attr(explode(';', $wide_max_width_value)[0]);
        $margin_left = ('left' === $justify_content) ? '0 !important' : 'auto !important';
        $margin_right = ('right' === $justify_content) ? '0 !important' : 'auto !important';
        if ($content_size || $wide_size) {
            array_push($layout_styles, array('selector' => "{$selector} > :where(:not(.alignleft):not(.alignright):not(.alignfull))", 'declarations' => array('max-width' => $all_max_width_value, 'margin-left' => $margin_left, 'margin-right' => $margin_right)), array('selector' => "{$selector} > .alignwide", 'declarations' => array('max-width' => $wide_max_width_value)), array('selector' => "{$selector} .alignfull", 'declarations' => array('max-width' => 'none')));
            if (isset($block_spacing)) {
                $block_spacing_values = wp_style_engine_get_styles(array('spacing' => $block_spacing));
                /*
                 * Handle negative margins for alignfull children of blocks with custom padding set.
                 * They're added separately because padding might only be set on one side.
                 */
                if (isset($block_spacing_values['declarations']['padding-right'])) {
                    $padding_right = $block_spacing_values['declarations']['padding-right'];
                    $layout_styles[] = array('selector' => "{$selector} > .alignfull", 'declarations' => array('margin-right' => "calc({$padding_right} * -1)"));
                }
                if (isset($block_spacing_values['declarations']['padding-left'])) {
                    $padding_left = $block_spacing_values['declarations']['padding-left'];
                    $layout_styles[] = array('selector' => "{$selector} > .alignfull", 'declarations' => array('margin-left' => "calc({$padding_left} * -1)"));
                }
            }
        }
        if ('left' === $justify_content) {
            $layout_styles[] = array('selector' => "{$selector} > :where(:not(.alignleft):not(.alignright):not(.alignfull))", 'declarations' => array('margin-left' => '0 !important'));
        }
        if ('right' === $justify_content) {
            $layout_styles[] = array('selector' => "{$selector} > :where(:not(.alignleft):not(.alignright):not(.alignfull))", 'declarations' => array('margin-right' => '0 !important'));
        }
        if ($has_block_gap_support) {
            if (is_array($gap_value)) {
                $gap_value = isset($gap_value['top']) ? $gap_value['top'] : null;
            }
            if (null !== $gap_value && !$should_skip_gap_serialization) {
                // Get spacing CSS variable from preset value if provided.
                if (is_string($gap_value) && str_contains($gap_value, 'var:preset|spacing|')) {
                    $index_to_splice = strrpos($gap_value, '|') + 1;
                    $slug = _wp_to_kebab_case(substr($gap_value, $index_to_splice));
                    $gap_value = "var(--wp--preset--spacing--{$slug})";
                }
                array_push($layout_styles, array('selector' => "{$selector} > *", 'declarations' => array('margin-block-start' => '0', 'margin-block-end' => '0')), array('selector' => "{$selector}{$selector} > * + *", 'declarations' => array('margin-block-start' => $gap_value, 'margin-block-end' => '0')));
            }
        }
    } elseif ('flex' === $layout_type) {
        $layout_orientation = isset($layout['orientation']) ? $layout['orientation'] : 'horizontal';
        $justify_content_options = array('left' => 'flex-start', 'right' => 'flex-end', 'center' => 'center');
        $vertical_alignment_options = array('top' => 'flex-start', 'center' => 'center', 'bottom' => 'flex-end');
        if ('horizontal' === $layout_orientation) {
            $justify_content_options += array('space-between' => 'space-between');
            $vertical_alignment_options += array('stretch' => 'stretch');
        } else {
            $justify_content_options += array('stretch' => 'stretch');
            $vertical_alignment_options += array('space-between' => 'space-between');
        }
        if (!empty($layout['flexWrap']) && 'nowrap' === $layout['flexWrap']) {
            $layout_styles[] = array('selector' => $selector, 'declarations' => array('flex-wrap' => 'nowrap'));
        }
        if ($has_block_gap_support && isset($gap_value)) {
            $combined_gap_value = '';
            $gap_sides = is_array($gap_value) ? array('top', 'left') : array('top');
            foreach ($gap_sides as $gap_side) {
                $process_value = is_string($gap_value) ? $gap_value : _wp_array_get($gap_value, array($gap_side), $fallback_gap_value);
                // Get spacing CSS variable from preset value if provided.
                if (is_string($process_value) && str_contains($process_value, 'var:preset|spacing|')) {
                    $index_to_splice = strrpos($process_value, '|') + 1;
                    $slug = _wp_to_kebab_case(substr($process_value, $index_to_splice));
                    $process_value = "var(--wp--preset--spacing--{$slug})";
                }
                $combined_gap_value .= "{$process_value} ";
            }
            $gap_value = trim($combined_gap_value);
            if (null !== $gap_value && !$should_skip_gap_serialization) {
                $layout_styles[] = array('selector' => $selector, 'declarations' => array('gap' => $gap_value));
            }
        }
        if ('horizontal' === $layout_orientation) {
            /*
             * Add this style only if is not empty for backwards compatibility,
             * since we intend to convert blocks that had flex layout implemented
             * by custom css.
             */
            if (!empty($layout['justifyContent']) && array_key_exists($layout['justifyContent'], $justify_content_options)) {
                $layout_styles[] = array('selector' => $selector, 'declarations' => array('justify-content' => $justify_content_options[$layout['justifyContent']]));
            }
            if (!empty($layout['verticalAlignment']) && array_key_exists($layout['verticalAlignment'], $vertical_alignment_options)) {
                $layout_styles[] = array('selector' => $selector, 'declarations' => array('align-items' => $vertical_alignment_options[$layout['verticalAlignment']]));
            }
        } else {
            $layout_styles[] = array('selector' => $selector, 'declarations' => array('flex-direction' => 'column'));
            if (!empty($layout['justifyContent']) && array_key_exists($layout['justifyContent'], $justify_content_options)) {
                $layout_styles[] = array('selector' => $selector, 'declarations' => array('align-items' => $justify_content_options[$layout['justifyContent']]));
            } else {
                $layout_styles[] = array('selector' => $selector, 'declarations' => array('align-items' => 'flex-start'));
            }
            if (!empty($layout['verticalAlignment']) && array_key_exists($layout['verticalAlignment'], $vertical_alignment_options)) {
                $layout_styles[] = array('selector' => $selector, 'declarations' => array('justify-content' => $vertical_alignment_options[$layout['verticalAlignment']]));
            }
        }
    }
    if (!empty($layout_styles)) {
        /*
         * Add to the style engine store to enqueue and render layout styles.
         * Return compiled layout styles to retain backwards compatibility.
         * Since https://github.com/WordPress/gutenberg/pull/42452,
         * wp_enqueue_block_support_styles is no longer called in this block supports file.
         */
        return wp_style_engine_get_stylesheet_from_css_rules($layout_styles, array('context' => 'block-supports', 'prettify' => false));
    }
    return '';
}

WordPress Version: 6.1

/**
 * Generates the CSS corresponding to the provided layout.
 *
 * @since 5.9.0
 * @since 6.1.0 Added `$block_spacing` param, use style engine to enqueue styles.
 * @access private
 *
 * @param string               $selector                      CSS selector.
 * @param array                $layout                        Layout object. The one that is passed has already checked
 *                                                            the existence of default block layout.
 * @param bool                 $has_block_gap_support         Optional. Whether the theme has support for the block gap. Default false.
 * @param string|string[]|null $gap_value                     Optional. The block gap value to apply. Default null.
 * @param bool                 $should_skip_gap_serialization Optional. Whether to skip applying the user-defined value set in the editor. Default false.
 * @param string               $fallback_gap_value            Optional. The block gap value to apply. Default '0.5em'.
 * @param array|null           $block_spacing                 Optional. Custom spacing set on the block. Default null.
 * @return string CSS styles on success. Else, empty string.
 */
function wp_get_layout_style($selector, $layout, $has_block_gap_support = false, $gap_value = null, $should_skip_gap_serialization = false, $fallback_gap_value = '0.5em', $block_spacing = null)
{
    $layout_type = isset($layout['type']) ? $layout['type'] : 'default';
    $layout_styles = array();
    if ('default' === $layout_type) {
        if ($has_block_gap_support) {
            if (is_array($gap_value)) {
                $gap_value = isset($gap_value['top']) ? $gap_value['top'] : null;
            }
            if (null !== $gap_value && !$should_skip_gap_serialization) {
                // Get spacing CSS variable from preset value if provided.
                if (is_string($gap_value) && str_contains($gap_value, 'var:preset|spacing|')) {
                    $index_to_splice = strrpos($gap_value, '|') + 1;
                    $slug = _wp_to_kebab_case(substr($gap_value, $index_to_splice));
                    $gap_value = "var(--wp--preset--spacing--{$slug})";
                }
                array_push($layout_styles, array('selector' => "{$selector} > *", 'declarations' => array('margin-block-start' => '0', 'margin-block-end' => '0')), array('selector' => "{$selector}{$selector} > * + *", 'declarations' => array('margin-block-start' => $gap_value, 'margin-block-end' => '0')));
            }
        }
    } elseif ('constrained' === $layout_type) {
        $content_size = isset($layout['contentSize']) ? $layout['contentSize'] : '';
        $wide_size = isset($layout['wideSize']) ? $layout['wideSize'] : '';
        $justify_content = isset($layout['justifyContent']) ? $layout['justifyContent'] : 'center';
        $all_max_width_value = $content_size ? $content_size : $wide_size;
        $wide_max_width_value = $wide_size ? $wide_size : $content_size;
        // Make sure there is a single CSS rule, and all tags are stripped for security.
        $all_max_width_value = safecss_filter_attr(explode(';', $all_max_width_value)[0]);
        $wide_max_width_value = safecss_filter_attr(explode(';', $wide_max_width_value)[0]);
        $margin_left = ('left' === $justify_content) ? '0 !important' : 'auto !important';
        $margin_right = ('right' === $justify_content) ? '0 !important' : 'auto !important';
        if ($content_size || $wide_size) {
            array_push($layout_styles, array('selector' => "{$selector} > :where(:not(.alignleft):not(.alignright):not(.alignfull))", 'declarations' => array('max-width' => $all_max_width_value, 'margin-left' => $margin_left, 'margin-right' => $margin_right)), array('selector' => "{$selector} > .alignwide", 'declarations' => array('max-width' => $wide_max_width_value)), array('selector' => "{$selector} .alignfull", 'declarations' => array('max-width' => 'none')));
            if (isset($block_spacing)) {
                $block_spacing_values = wp_style_engine_get_styles(array('spacing' => $block_spacing));
                /*
                 * Handle negative margins for alignfull children of blocks with custom padding set.
                 * They're added separately because padding might only be set on one side.
                 */
                if (isset($block_spacing_values['declarations']['padding-right'])) {
                    $padding_right = $block_spacing_values['declarations']['padding-right'];
                    $layout_styles[] = array('selector' => "{$selector} > .alignfull", 'declarations' => array('margin-right' => "calc({$padding_right} * -1)"));
                }
                if (isset($block_spacing_values['declarations']['padding-left'])) {
                    $padding_left = $block_spacing_values['declarations']['padding-left'];
                    $layout_styles[] = array('selector' => "{$selector} > .alignfull", 'declarations' => array('margin-left' => "calc({$padding_left} * -1)"));
                }
            }
        }
        if ('left' === $justify_content) {
            $layout_styles[] = array('selector' => "{$selector} > :where(:not(.alignleft):not(.alignright):not(.alignfull))", 'declarations' => array('margin-left' => '0 !important'));
        }
        if ('right' === $justify_content) {
            $layout_styles[] = array('selector' => "{$selector} > :where(:not(.alignleft):not(.alignright):not(.alignfull))", 'declarations' => array('margin-right' => '0 !important'));
        }
        if ($has_block_gap_support) {
            if (is_array($gap_value)) {
                $gap_value = isset($gap_value['top']) ? $gap_value['top'] : null;
            }
            if (null !== $gap_value && !$should_skip_gap_serialization) {
                // Get spacing CSS variable from preset value if provided.
                if (is_string($gap_value) && str_contains($gap_value, 'var:preset|spacing|')) {
                    $index_to_splice = strrpos($gap_value, '|') + 1;
                    $slug = _wp_to_kebab_case(substr($gap_value, $index_to_splice));
                    $gap_value = "var(--wp--preset--spacing--{$slug})";
                }
                array_push($layout_styles, array('selector' => "{$selector} > *", 'declarations' => array('margin-block-start' => '0', 'margin-block-end' => '0')), array('selector' => "{$selector}{$selector} > * + *", 'declarations' => array('margin-block-start' => $gap_value, 'margin-block-end' => '0')));
            }
        }
    } elseif ('flex' === $layout_type) {
        $layout_orientation = isset($layout['orientation']) ? $layout['orientation'] : 'horizontal';
        $justify_content_options = array('left' => 'flex-start', 'right' => 'flex-end', 'center' => 'center');
        $vertical_alignment_options = array('top' => 'flex-start', 'center' => 'center', 'bottom' => 'flex-end');
        if ('horizontal' === $layout_orientation) {
            $justify_content_options += array('space-between' => 'space-between');
        }
        if (!empty($layout['flexWrap']) && 'nowrap' === $layout['flexWrap']) {
            $layout_styles[] = array('selector' => $selector, 'declarations' => array('flex-wrap' => 'nowrap'));
        }
        if ($has_block_gap_support && isset($gap_value)) {
            $combined_gap_value = '';
            $gap_sides = is_array($gap_value) ? array('top', 'left') : array('top');
            foreach ($gap_sides as $gap_side) {
                $process_value = is_string($gap_value) ? $gap_value : _wp_array_get($gap_value, array($gap_side), $fallback_gap_value);
                // Get spacing CSS variable from preset value if provided.
                if (is_string($process_value) && str_contains($process_value, 'var:preset|spacing|')) {
                    $index_to_splice = strrpos($process_value, '|') + 1;
                    $slug = _wp_to_kebab_case(substr($process_value, $index_to_splice));
                    $process_value = "var(--wp--preset--spacing--{$slug})";
                }
                $combined_gap_value .= "{$process_value} ";
            }
            $gap_value = trim($combined_gap_value);
            if (null !== $gap_value && !$should_skip_gap_serialization) {
                $layout_styles[] = array('selector' => $selector, 'declarations' => array('gap' => $gap_value));
            }
        }
        if ('horizontal' === $layout_orientation) {
            /*
             * Add this style only if is not empty for backwards compatibility,
             * since we intend to convert blocks that had flex layout implemented
             * by custom css.
             */
            if (!empty($layout['justifyContent']) && array_key_exists($layout['justifyContent'], $justify_content_options)) {
                $layout_styles[] = array('selector' => $selector, 'declarations' => array('justify-content' => $justify_content_options[$layout['justifyContent']]));
            }
            if (!empty($layout['verticalAlignment']) && array_key_exists($layout['verticalAlignment'], $vertical_alignment_options)) {
                $layout_styles[] = array('selector' => $selector, 'declarations' => array('align-items' => $vertical_alignment_options[$layout['verticalAlignment']]));
            }
        } else {
            $layout_styles[] = array('selector' => $selector, 'declarations' => array('flex-direction' => 'column'));
            if (!empty($layout['justifyContent']) && array_key_exists($layout['justifyContent'], $justify_content_options)) {
                $layout_styles[] = array('selector' => $selector, 'declarations' => array('align-items' => $justify_content_options[$layout['justifyContent']]));
            } else {
                $layout_styles[] = array('selector' => $selector, 'declarations' => array('align-items' => 'flex-start'));
            }
        }
    }
    if (!empty($layout_styles)) {
        /*
         * Add to the style engine store to enqueue and render layout styles.
         * Return compiled layout styles to retain backwards compatibility.
         * Since https://github.com/WordPress/gutenberg/pull/42452,
         * wp_enqueue_block_support_styles is no longer called in this block supports file.
         */
        return wp_style_engine_get_stylesheet_from_css_rules($layout_styles, array('context' => 'block-supports', 'prettify' => false));
    }
    return '';
}

WordPress Version: 5.9

/**
 * Generates the CSS corresponding to the provided layout.
 *
 * @since 5.9.0
 * @access private
 *
 * @param string $selector              CSS selector.
 * @param array  $layout                Layout object. The one that is passed has already checked
 *                                      the existence of default block layout.
 * @param bool   $has_block_gap_support Whether the theme has support for the block gap.
 * @param string $gap_value             The block gap value to apply.
 * @return string CSS style.
 */
function wp_get_layout_style($selector, $layout, $has_block_gap_support = false, $gap_value = null)
{
    $layout_type = isset($layout['type']) ? $layout['type'] : 'default';
    $style = '';
    if ('default' === $layout_type) {
        $content_size = isset($layout['contentSize']) ? $layout['contentSize'] : '';
        $wide_size = isset($layout['wideSize']) ? $layout['wideSize'] : '';
        $all_max_width_value = $content_size ? $content_size : $wide_size;
        $wide_max_width_value = $wide_size ? $wide_size : $content_size;
        // Make sure there is a single CSS rule, and all tags are stripped for security.
        // TODO: Use `safecss_filter_attr` instead - once https://core.trac.wordpress.org/ticket/46197 is patched.
        $all_max_width_value = wp_strip_all_tags(explode(';', $all_max_width_value)[0]);
        $wide_max_width_value = wp_strip_all_tags(explode(';', $wide_max_width_value)[0]);
        $style = '';
        if ($content_size || $wide_size) {
            $style = "{$selector} > * {";
            $style .= 'max-width: ' . esc_html($all_max_width_value) . ';';
            $style .= 'margin-left: auto !important;';
            $style .= 'margin-right: auto !important;';
            $style .= '}';
            $style .= "{$selector} > .alignwide { max-width: " . esc_html($wide_max_width_value) . ';}';
            $style .= "{$selector} .alignfull { max-width: none; }";
        }
        $style .= "{$selector} .alignleft { float: left; margin-right: 2em; }";
        $style .= "{$selector} .alignright { float: right; margin-left: 2em; }";
        if ($has_block_gap_support) {
            $gap_style = $gap_value ? $gap_value : 'var( --wp--style--block-gap )';
            $style .= "{$selector} > * { margin-top: 0; margin-bottom: 0; }";
            $style .= "{$selector} > * + * { margin-top: {$gap_style};  margin-bottom: 0; }";
        }
    } elseif ('flex' === $layout_type) {
        $layout_orientation = isset($layout['orientation']) ? $layout['orientation'] : 'horizontal';
        $justify_content_options = array('left' => 'flex-start', 'right' => 'flex-end', 'center' => 'center');
        if ('horizontal' === $layout_orientation) {
            $justify_content_options += array('space-between' => 'space-between');
        }
        $flex_wrap_options = array('wrap', 'nowrap');
        $flex_wrap = (!empty($layout['flexWrap']) && in_array($layout['flexWrap'], $flex_wrap_options, true)) ? $layout['flexWrap'] : 'wrap';
        $style = "{$selector} {";
        $style .= 'display: flex;';
        if ($has_block_gap_support) {
            $gap_style = $gap_value ? $gap_value : 'var( --wp--style--block-gap, 0.5em )';
            $style .= "gap: {$gap_style};";
        } else {
            $style .= 'gap: 0.5em;';
        }
        $style .= "flex-wrap: {$flex_wrap};";
        $style .= 'align-items: center;';
        if ('horizontal' === $layout_orientation) {
            $style .= 'align-items: center;';
            /**
             * Add this style only if is not empty for backwards compatibility,
             * since we intend to convert blocks that had flex layout implemented
             * by custom css.
             */
            if (!empty($layout['justifyContent']) && array_key_exists($layout['justifyContent'], $justify_content_options)) {
                $style .= "justify-content: {$justify_content_options[$layout['justifyContent']]};";
            }
        } else {
            $style .= 'flex-direction: column;';
            if (!empty($layout['justifyContent']) && array_key_exists($layout['justifyContent'], $justify_content_options)) {
                $style .= "align-items: {$justify_content_options[$layout['justifyContent']]};";
            }
        }
        $style .= '}';
        $style .= "{$selector} > * { margin: 0; }";
    }
    return $style;
}