Skip to content

Commit 5885cb9

Browse files
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. git-svn-id: https://develop.svn.wordpress.org/trunk@61565 602fd350-edb4-49c9-b593-d223f7449a82
1 parent e3ad7a0 commit 5885cb9

4 files changed

Lines changed: 476 additions & 4 deletions

File tree

src/wp-includes/block-supports/block-visibility.php

Lines changed: 119 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@
77
*/
88

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

26-
if ( isset( $block['attrs']['metadata']['blockVisibility'] ) && false === $block['attrs']['metadata']['blockVisibility'] ) {
27+
$block_visibility = $block['attrs']['metadata']['blockVisibility'] ?? null;
28+
29+
if ( false === $block_visibility ) {
2730
return '';
2831
}
2932

33+
if ( is_array( $block_visibility ) && ! empty( $block_visibility ) ) {
34+
$viewport_config = $block_visibility['viewport'] ?? null;
35+
36+
if ( ! is_array( $viewport_config ) || empty( $viewport_config ) ) {
37+
return $block_content;
38+
}
39+
/*
40+
* Viewport size definitions are in several places in WordPress packages.
41+
* The following are taken from: https://github.com/WordPress/gutenberg/blob/trunk/packages/base-styles/_breakpoints.scss
42+
* The array is in a future, potential JSON format, and will be centralized
43+
* as the feature is developed.
44+
*
45+
* Viewport sizes as array items are defined sequentially. The first item's size is the max value.
46+
* Each subsequent item starts after the previous size (using > operator), and its size is the max.
47+
* The last item starts after the previous size (using > operator), and it has no max.
48+
*/
49+
$viewport_sizes = array(
50+
array(
51+
'name' => 'Mobile',
52+
'slug' => 'mobile',
53+
'size' => '480px',
54+
),
55+
array(
56+
'name' => 'Tablet',
57+
'slug' => 'tablet',
58+
'size' => '782px',
59+
),
60+
array(
61+
'name' => 'Desktop',
62+
'slug' => 'desktop',
63+
/*
64+
* Note: the last item in the $viewport_sizes array does not technically require a 'size' key,
65+
* as the last item's media query is calculated using `width > previous size`.
66+
* The last item is present for validating the attribute values, and in order to indicate
67+
* that this is the final viewport size, and to calculate the previous media query accordingly.
68+
*/
69+
),
70+
);
71+
72+
/*
73+
* Build media queries from viewport size definitions using the CSS range syntax.
74+
* Could be absorbed into the style engine,
75+
* as well as classname building, and declaration of the display property, if required.
76+
*/
77+
$viewport_media_queries = array();
78+
$previous_size = null;
79+
foreach ( $viewport_sizes as $index => $viewport_size ) {
80+
// First item: width <= size.
81+
if ( 0 === $index ) {
82+
$viewport_media_queries[ $viewport_size['slug'] ] = "@media (width <= {$viewport_size['size']})";
83+
} elseif ( count( $viewport_sizes ) - 1 === $index && $previous_size ) {
84+
// Last item: width > previous size.
85+
$viewport_media_queries[ $viewport_size['slug'] ] = "@media (width > $previous_size)";
86+
} else {
87+
// Middle items: previous size < width <= size.
88+
$viewport_media_queries[ $viewport_size['slug'] ] = "@media ({$previous_size} < width <= {$viewport_size['size']})";
89+
}
90+
91+
$previous_size = $viewport_size['size'] ?? null;
92+
}
93+
94+
$hidden_on = array();
95+
96+
// Collect which viewport the block is hidden on (only known viewport sizes).
97+
foreach ( $viewport_config as $viewport_config_size => $is_visible ) {
98+
if ( false === $is_visible && isset( $viewport_media_queries[ $viewport_config_size ] ) ) {
99+
$hidden_on[] = $viewport_config_size;
100+
}
101+
}
102+
103+
// If no viewport sizes have visibility set to false, return unchanged.
104+
if ( empty( $hidden_on ) ) {
105+
return $block_content;
106+
}
107+
108+
// Maintain consistent order of viewport sizes for class name generation.
109+
sort( $hidden_on );
110+
111+
$css_rules = array();
112+
$class_names = array();
113+
114+
foreach ( $hidden_on as $hidden_viewport_size ) {
115+
/*
116+
* If these values ever become user-defined,
117+
* they should be sanitized and kebab-cased.
118+
*/
119+
$visibility_class = 'wp-block-hidden-' . $hidden_viewport_size;
120+
$class_names[] = $visibility_class;
121+
$css_rules[] = array(
122+
'selector' => '.' . $visibility_class,
123+
'declarations' => array(
124+
'display' => 'none !important',
125+
),
126+
'rules_group' => $viewport_media_queries[ $hidden_viewport_size ],
127+
);
128+
}
129+
130+
wp_style_engine_get_stylesheet_from_css_rules(
131+
$css_rules,
132+
array(
133+
'context' => 'block-supports',
134+
'prettify' => false,
135+
)
136+
);
137+
138+
if ( ! empty( $block_content ) ) {
139+
$processor = new WP_HTML_Tag_Processor( $block_content );
140+
if ( $processor->next_tag() ) {
141+
$processor->add_class( implode( ' ', $class_names ) );
142+
$block_content = $processor->get_updated_html();
143+
}
144+
}
145+
}
146+
30147
return $block_content;
31148
}
32149

src/wp-includes/kses.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2631,6 +2631,8 @@ function safecss_filter_attr( $css, $deprecated = '' ) {
26312631
'column-span',
26322632
'column-width',
26332633

2634+
'display',
2635+
26342636
'color',
26352637
'filter',
26362638
'font',

0 commit comments

Comments
 (0)