Commit 67ad824cc5 for wordpress.org

commit 67ad824cc5cf70c99bcada6e98871ac1f5efed83
Author: isabel_brison <isabel_brison@git.wordpress.org>
Date:   Fri Jan 30 02:40:40 2026 +0000

    Editor: screen size based block visibility support.

    Adds ability to hide blocks at different screen sizes to the block visibility support.

    Props ramonopoly, isabel_brison, westonruter.
    Closes #64414.

    Built from https://develop.svn.wordpress.org/trunk@61565


    git-svn-id: http://core.svn.wordpress.org/trunk@60876 1a063a9b-81f0-0310-95a4-ce76da25c4cd

diff --git a/wp-includes/block-supports/block-visibility.php b/wp-includes/block-supports/block-visibility.php
index 523536cf56..756e050041 100644
--- a/wp-includes/block-supports/block-visibility.php
+++ b/wp-includes/block-supports/block-visibility.php
@@ -7,9 +7,10 @@
  */

 /**
- * Render nothing if the block is hidden.
+ * Render nothing if the block is hidden, or add viewport visibility styles.
  *
  * @since 6.9.0
+ * @since 7.0.0 Added support for viewport visibility.
  * @access private
  *
  * @param string $block_content Rendered block content.
@@ -23,10 +24,126 @@ function wp_render_block_visibility_support( $block_content, $block ) {
 		return $block_content;
 	}

-	if ( isset( $block['attrs']['metadata']['blockVisibility'] ) && false === $block['attrs']['metadata']['blockVisibility'] ) {
+	$block_visibility = $block['attrs']['metadata']['blockVisibility'] ?? null;
+
+	if ( false === $block_visibility ) {
 		return '';
 	}

+	if ( is_array( $block_visibility ) && ! empty( $block_visibility ) ) {
+		$viewport_config = $block_visibility['viewport'] ?? null;
+
+		if ( ! is_array( $viewport_config ) || empty( $viewport_config ) ) {
+			return $block_content;
+		}
+		/*
+		 * Viewport size definitions are in several places in WordPress packages.
+		 * The following are taken from: https://github.com/WordPress/gutenberg/blob/trunk/packages/base-styles/_breakpoints.scss
+		 * The array is in a future, potential JSON format, and will be centralized
+		 * as the feature is developed.
+		 *
+		 * Viewport sizes as array items are defined sequentially. The first item's size is the max value.
+		 * Each subsequent item starts after the previous size (using > operator), and its size is the max.
+		 * The last item starts after the previous size (using > operator), and it has no max.
+		 */
+		$viewport_sizes = array(
+			array(
+				'name' => 'Mobile',
+				'slug' => 'mobile',
+				'size' => '480px',
+			),
+			array(
+				'name' => 'Tablet',
+				'slug' => 'tablet',
+				'size' => '782px',
+			),
+			array(
+				'name' => 'Desktop',
+				'slug' => 'desktop',
+				/*
+				 * Note: the last item in the $viewport_sizes array does not technically require a 'size' key,
+				 * as the last item's media query is calculated using `width > previous size`.
+				 * The last item is present for validating the attribute values, and in order to indicate
+				 * that this is the final viewport size, and to calculate the previous media query accordingly.
+				 */
+			),
+		);
+
+		/*
+		 * Build media queries from viewport size definitions using the CSS range syntax.
+		 * Could be absorbed into the style engine,
+		 * as well as classname building, and declaration of the display property, if required.
+		 */
+		$viewport_media_queries = array();
+		$previous_size          = null;
+		foreach ( $viewport_sizes as $index => $viewport_size ) {
+			// First item: width <= size.
+			if ( 0 === $index ) {
+				$viewport_media_queries[ $viewport_size['slug'] ] = "@media (width <= {$viewport_size['size']})";
+			} elseif ( count( $viewport_sizes ) - 1 === $index && $previous_size ) {
+				// Last item: width > previous size.
+				$viewport_media_queries[ $viewport_size['slug'] ] = "@media (width > $previous_size)";
+			} else {
+				// Middle items: previous size < width <= size.
+				$viewport_media_queries[ $viewport_size['slug'] ] = "@media ({$previous_size} < width <= {$viewport_size['size']})";
+			}
+
+			$previous_size = $viewport_size['size'] ?? null;
+		}
+
+		$hidden_on = array();
+
+		// Collect which viewport the block is hidden on (only known viewport sizes).
+		foreach ( $viewport_config as $viewport_config_size => $is_visible ) {
+			if ( false === $is_visible && isset( $viewport_media_queries[ $viewport_config_size ] ) ) {
+				$hidden_on[] = $viewport_config_size;
+			}
+		}
+
+		// If no viewport sizes have visibility set to false, return unchanged.
+		if ( empty( $hidden_on ) ) {
+			return $block_content;
+		}
+
+		// Maintain consistent order of viewport sizes for class name generation.
+		sort( $hidden_on );
+
+		$css_rules   = array();
+		$class_names = array();
+
+		foreach ( $hidden_on as $hidden_viewport_size ) {
+			/*
+			 * If these values ever become user-defined,
+			 * they should be sanitized and kebab-cased.
+			 */
+			$visibility_class = 'wp-block-hidden-' . $hidden_viewport_size;
+			$class_names[]    = $visibility_class;
+			$css_rules[]      = array(
+				'selector'     => '.' . $visibility_class,
+				'declarations' => array(
+					'display' => 'none !important',
+				),
+				'rules_group'  => $viewport_media_queries[ $hidden_viewport_size ],
+			);
+		}
+
+		wp_style_engine_get_stylesheet_from_css_rules(
+			$css_rules,
+			array(
+				'context'  => 'block-supports',
+				'prettify' => false,
+			)
+		);
+
+		if ( ! empty( $block_content ) ) {
+			$processor = new WP_HTML_Tag_Processor( $block_content );
+			if ( $processor->next_tag() ) {
+				$processor->add_class( implode( ' ', $class_names ) );
+				$block_content = $processor->get_updated_html();
+			}
+		}
+	}
+
 	return $block_content;
 }

diff --git a/wp-includes/kses.php b/wp-includes/kses.php
index c71453177d..ed2f96503a 100644
--- a/wp-includes/kses.php
+++ b/wp-includes/kses.php
@@ -2631,6 +2631,8 @@ function safecss_filter_attr( $css, $deprecated = '' ) {
 			'column-span',
 			'column-width',

+			'display',
+
 			'color',
 			'filter',
 			'font',
diff --git a/wp-includes/version.php b/wp-includes/version.php
index 3df640ba48..6fceeb1f84 100644
--- a/wp-includes/version.php
+++ b/wp-includes/version.php
@@ -16,7 +16,7 @@
  *
  * @global string $wp_version
  */
-$wp_version = '7.0-alpha-61564';
+$wp_version = '7.0-alpha-61565';

 /**
  * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.