PluginProbe ʕ •ᴥ•ʔ
FrontBlocks for Gutenberg/GeneratePress / trunk
FrontBlocks for Gutenberg/GeneratePress vtrunk
trunk 0.2.0 0.2.1 0.2.2 0.2.3 0.2.4 0.2.5 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.1.0 1.2.0 1.2.1 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 ci-artifacts
frontblocks / includes / Frontend / ColumnsSameHeight.php
frontblocks / includes / Frontend Last commit date
Animations.php 1 month ago BackButton.php 7 months ago BeforeAfter.php 1 month ago BlockPatterns.php 4 months ago Carousel.php 1 week ago ColumnsSameHeight.php 1 week ago ContainerEdgeAlignment.php 4 weeks ago Counter.php 1 month ago DownloadButton.php 1 week ago Events.php 4 weeks ago FaqSchema.php 1 week ago FluidTypography.php 4 weeks ago Gallery.php 8 months ago GravityFormsInline.php 1 month ago Headline.php 4 weeks ago InsertPost.php 1 month ago ProductCategories.php 4 weeks ago ReadingProgress.php 7 months ago ReadingTime.php 8 months ago ShapeAnimations.php 4 weeks ago StackedImages.php 4 months ago StickyColumn.php 4 weeks ago SvgUpload.php 4 weeks ago Testimonials.php 8 months ago TextAnimation.php 1 month ago UserText.php 4 weeks ago
ColumnsSameHeight.php
176 lines
1 <?php
2 /**
3 * Columns Same Height module for FrontBlocks (native columns block enhancement).
4 *
5 * @package FrontBlocks
6 * @author Alex castellón <castellon@close.technology>
7 * @copyright 2026 Closemarketing
8 * @version 1.0.0
9 */
10
11 namespace FrontBlocks\Frontend;
12
13 defined( 'ABSPATH' ) || exit;
14
15 /**
16 * ColumnsSameHeight class.
17 *
18 * Adds a "Same height columns" toggle to the native core/columns block.
19 * When enabled, all sibling columns stretch to the height of the tallest one.
20 *
21 * @since 1.3.7
22 */
23 class ColumnsSameHeight {
24 /**
25 * Constructor.
26 */
27 public function __construct() {
28 add_action( 'init', array( $this, 'register_assets' ) );
29 add_action( 'enqueue_block_editor_assets', array( $this, 'enqueue_editor_assets' ) );
30 add_action( 'enqueue_block_assets', array( $this, 'enqueue_editor_styles' ) );
31 add_filter( 'register_block_type_args', array( $this, 'register_native_block_attributes' ), 10, 2 );
32 add_filter( 'render_block_core/columns', array( $this, 'apply_same_height_class' ), 10, 2 );
33 }
34
35 /**
36 * Register block assets.
37 *
38 * @return void
39 */
40 public function register_assets() {
41 wp_register_script(
42 'frontblocks-columns-same-height-editor',
43 FRBL_PLUGIN_URL . 'assets/columns-same-height/frontblocks-columns-same-height-option.js',
44 array(
45 'wp-blocks',
46 'wp-element',
47 'wp-block-editor',
48 'wp-components',
49 'wp-compose',
50 'wp-hooks',
51 'wp-i18n',
52 ),
53 FRBL_VERSION,
54 true
55 );
56
57 wp_register_style(
58 'frontblocks-columns-same-height',
59 FRBL_PLUGIN_URL . 'assets/columns-same-height/frontblocks-columns-same-height.css',
60 array(),
61 FRBL_VERSION
62 );
63 }
64
65 /**
66 * Enqueue editor assets.
67 *
68 * @return void
69 */
70 public function enqueue_editor_assets() {
71 wp_enqueue_script( 'frontblocks-columns-same-height-editor' );
72
73 wp_set_script_translations(
74 'frontblocks-columns-same-height-editor',
75 'frontblocks'
76 );
77 }
78
79 /**
80 * Inject editor styles inside the iframe via wp-block-library inline styles.
81 *
82 * `wp-block-library` is guaranteed to load inside the WP 6.3+ editor iframe,
83 * so attaching inline CSS to it ensures the styles reach block content.
84 * The selectors cover both structural variants: data attr on the columns
85 * element itself (wrapperProps merged) or on an outer wrapper div.
86 *
87 * @return void
88 */
89 public function enqueue_editor_styles() {
90 if ( ! is_admin() ) {
91 return;
92 }
93
94 $css = '
95 [data-frbl-same-height] .wp-block-columns,
96 [data-frbl-same-height].wp-block-columns {
97 align-items: stretch;
98 }
99 [data-frbl-same-height] .wp-block-columns > .wp-block-column,
100 [data-frbl-same-height].wp-block-columns > .wp-block-column {
101 display: flex;
102 flex-direction: column;
103 }
104 [data-frbl-same-height] .wp-block-columns > .wp-block-column > *,
105 [data-frbl-same-height].wp-block-columns > .wp-block-column > * {
106 flex-grow: 1;
107 }
108 ';
109
110 wp_add_inline_style( 'wp-block-library', $css );
111 }
112
113 /**
114 * Register frblSameHeight attribute server-side for core/columns.
115 *
116 * @param array $args Block type args.
117 * @param string $block_type Block type name.
118 * @return array
119 */
120 public function register_native_block_attributes( $args, $block_type ) {
121 if ( 'core/columns' !== $block_type ) {
122 return $args;
123 }
124
125 if ( ! isset( $args['attributes'] ) ) {
126 $args['attributes'] = array();
127 }
128
129 $args['attributes']['frblSameHeight'] = array(
130 'type' => 'boolean',
131 'default' => false,
132 );
133
134 return $args;
135 }
136
137 /**
138 * Add the same-height CSS class to the columns wrapper and enqueue styles.
139 *
140 * @param string $block_content Block HTML.
141 * @param array $block Block data.
142 * @return string
143 */
144 public function apply_same_height_class( $block_content, $block ) {
145 $attrs = $block['attrs'] ?? array();
146
147 if ( empty( $attrs['frblSameHeight'] ) ) {
148 return $block_content;
149 }
150
151 if ( ! wp_style_is( 'frontblocks-columns-same-height', 'enqueued' ) ) {
152 wp_enqueue_style( 'frontblocks-columns-same-height' );
153 }
154
155 if ( class_exists( 'WP_HTML_Tag_Processor' ) ) {
156 $processor = new \WP_HTML_Tag_Processor( $block_content );
157
158 if ( $processor->next_tag( array( 'class_name' => 'wp-block-columns' ) ) ) {
159 $existing = $processor->get_attribute( 'class' ) ?? '';
160 $processor->set_attribute( 'class', trim( $existing . ' frbl-columns-same-height' ) );
161 return $processor->get_updated_html();
162 }
163
164 return $block_content;
165 }
166
167 // Fallback for WP < 6.2.
168 return preg_replace(
169 '/(<div[^>]+class="[^"]*wp-block-columns[^"]*")/',
170 '$1 frbl-columns-same-height',
171 $block_content,
172 1
173 );
174 }
175 }
176