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.