diff --git a/plugins/embed-optimizer/class-embed-optimizer-tag-visitor.php b/plugins/embed-optimizer/class-embed-optimizer-tag-visitor.php index affed74d24..f0d1facf48 100644 --- a/plugins/embed-optimizer/class-embed-optimizer-tag-visitor.php +++ b/plugins/embed-optimizer/class-embed-optimizer-tag-visitor.php @@ -29,6 +29,17 @@ final class Embed_Optimizer_Tag_Visitor { */ private $added_lazy_script = false; + /** + * Pending styles to insert after the document has been processed. + * + * The keys are the media features to be used in `@media` queries, and the values are arrays of the rules. + * + * @since n.e.x.t + * + * @var array + */ + private $pending_styles = array(); + /** * Determines whether the processor is currently at a figure.wp-block-embed tag. * @@ -183,7 +194,6 @@ private function reduce_layout_shifts( OD_Tag_Visitor_Context $context ): void { $processor->set_attribute( 'id', $element_id ); } - $style_rules = array(); foreach ( $minimums as $minimum ) { $style_rule = sprintf( '#%s { min-height: %dpx; }', @@ -192,17 +202,11 @@ private function reduce_layout_shifts( OD_Tag_Visitor_Context $context ): void { ); $media_feature = od_generate_media_query( $minimum['group']->get_minimum_viewport_width(), $minimum['group']->get_maximum_viewport_width() ); - if ( null !== $media_feature ) { - $style_rule = sprintf( - '@media %s { %s }', - $media_feature, - $style_rule - ); + if ( null === $media_feature ) { + $media_feature = ''; } - $style_rules[] = $style_rule; + $this->pending_styles[ $media_feature ][] = $style_rule; } - - $processor->append_head_html( sprintf( "\n", join( "\n", $style_rules ) ) ); } } @@ -332,4 +336,30 @@ private function lazy_load_embeds( OD_Tag_Visitor_Context $context ): void { $this->added_lazy_script = true; } } + + /** + * Adds styles after the document has been processed. + * + * @since n.e.x.t + * @see self::reduce_layout_shifts() + * + * @param OD_Template_Optimization_Context $context Template optimization context. + */ + public function add_styles( OD_Template_Optimization_Context $context ): void { + $root_rules = array(); + foreach ( $this->pending_styles as $media_feature => $style_rules ) { + if ( '' === $media_feature ) { + $root_rules[] = join( "\n", $style_rules ); + } else { + $root_rules[] = sprintf( + "@media %s {\n\t%s\n}", + $media_feature, + join( "\n\t", $style_rules ) + ); + } + } + if ( count( $root_rules ) > 0 ) { + $context->append_head_html( "\n" ); + } + } } diff --git a/plugins/embed-optimizer/hooks.php b/plugins/embed-optimizer/hooks.php index 80015a9694..b44dd7f460 100644 --- a/plugins/embed-optimizer/hooks.php +++ b/plugins/embed-optimizer/hooks.php @@ -77,7 +77,10 @@ static function (): void { function embed_optimizer_register_tag_visitors( OD_Tag_Visitor_Registry $registry ): void { // Note: This class is loaded on the fly since it is only needed here when Optimization Detective is active. require_once __DIR__ . '/class-embed-optimizer-tag-visitor.php'; - $registry->register( 'embeds', new Embed_Optimizer_Tag_Visitor() ); + $tag_visitor = new Embed_Optimizer_Tag_Visitor(); + $registry->register( 'embeds', $tag_visitor ); + + add_action( 'od_finish_template_optimization', array( $tag_visitor, 'add_styles' ) ); } /** diff --git a/plugins/embed-optimizer/tests/test-cases/all-embeds-inside-viewport/expected.html b/plugins/embed-optimizer/tests/test-cases/all-embeds-inside-viewport/expected.html index 0a59751b12..5b57f6cd82 100644 --- a/plugins/embed-optimizer/tests/test-cases/all-embeds-inside-viewport/expected.html +++ b/plugins/embed-optimizer/tests/test-cases/all-embeds-inside-viewport/expected.html @@ -3,58 +3,50 @@ ... - - - - - - - - diff --git a/plugins/embed-optimizer/tests/test-cases/nested-figure-embed/expected.html b/plugins/embed-optimizer/tests/test-cases/nested-figure-embed/expected.html index 3fb635ce41..9593ba8358 100644 --- a/plugins/embed-optimizer/tests/test-cases/nested-figure-embed/expected.html +++ b/plugins/embed-optimizer/tests/test-cases/nested-figure-embed/expected.html @@ -3,16 +3,22 @@ ... - diff --git a/plugins/embed-optimizer/tests/test-cases/single-spotify-embed-outside-viewport-with-subsequent-script/expected.html b/plugins/embed-optimizer/tests/test-cases/single-spotify-embed-outside-viewport-with-subsequent-script/expected.html index 3e7a8989b6..4a23e13c01 100644 --- a/plugins/embed-optimizer/tests/test-cases/single-spotify-embed-outside-viewport-with-subsequent-script/expected.html +++ b/plugins/embed-optimizer/tests/test-cases/single-spotify-embed-outside-viewport-with-subsequent-script/expected.html @@ -3,10 +3,18 @@ ... diff --git a/plugins/embed-optimizer/tests/test-cases/single-twitter-embed-inside-viewport/expected.html b/plugins/embed-optimizer/tests/test-cases/single-twitter-embed-inside-viewport/expected.html index 1c66adf955..54e6a43150 100644 --- a/plugins/embed-optimizer/tests/test-cases/single-twitter-embed-inside-viewport/expected.html +++ b/plugins/embed-optimizer/tests/test-cases/single-twitter-embed-inside-viewport/expected.html @@ -3,10 +3,18 @@ ... diff --git a/plugins/embed-optimizer/tests/test-cases/single-twitter-embed-outside-viewport-on-mobile/expected.html b/plugins/embed-optimizer/tests/test-cases/single-twitter-embed-outside-viewport-on-mobile/expected.html index 73bff4dda9..0a0c7b62df 100644 --- a/plugins/embed-optimizer/tests/test-cases/single-twitter-embed-outside-viewport-on-mobile/expected.html +++ b/plugins/embed-optimizer/tests/test-cases/single-twitter-embed-outside-viewport-on-mobile/expected.html @@ -3,10 +3,18 @@ ... diff --git a/plugins/embed-optimizer/tests/test-cases/single-twitter-embed-outside-viewport/expected.html b/plugins/embed-optimizer/tests/test-cases/single-twitter-embed-outside-viewport/expected.html index a39166337d..e76813fd4b 100644 --- a/plugins/embed-optimizer/tests/test-cases/single-twitter-embed-outside-viewport/expected.html +++ b/plugins/embed-optimizer/tests/test-cases/single-twitter-embed-outside-viewport/expected.html @@ -3,10 +3,18 @@ ... diff --git a/plugins/embed-optimizer/tests/test-cases/single-wordpress-tv-embed-inside-viewport/expected.html b/plugins/embed-optimizer/tests/test-cases/single-wordpress-tv-embed-inside-viewport/expected.html index 3c80fee092..8d5a679059 100644 --- a/plugins/embed-optimizer/tests/test-cases/single-wordpress-tv-embed-inside-viewport/expected.html +++ b/plugins/embed-optimizer/tests/test-cases/single-wordpress-tv-embed-inside-viewport/expected.html @@ -3,10 +3,18 @@ ... diff --git a/plugins/embed-optimizer/tests/test-cases/single-wordpress-tv-embed-outside-viewport-on-mobile/expected.html b/plugins/embed-optimizer/tests/test-cases/single-wordpress-tv-embed-outside-viewport-on-mobile/expected.html index 2d033e039d..9a4c87c775 100644 --- a/plugins/embed-optimizer/tests/test-cases/single-wordpress-tv-embed-outside-viewport-on-mobile/expected.html +++ b/plugins/embed-optimizer/tests/test-cases/single-wordpress-tv-embed-outside-viewport-on-mobile/expected.html @@ -3,10 +3,18 @@ ... diff --git a/plugins/embed-optimizer/tests/test-cases/single-wordpress-tv-embed-outside-viewport/expected.html b/plugins/embed-optimizer/tests/test-cases/single-wordpress-tv-embed-outside-viewport/expected.html index 68dec6f791..f7d48beee6 100644 --- a/plugins/embed-optimizer/tests/test-cases/single-wordpress-tv-embed-outside-viewport/expected.html +++ b/plugins/embed-optimizer/tests/test-cases/single-wordpress-tv-embed-outside-viewport/expected.html @@ -3,10 +3,18 @@ ... diff --git a/plugins/embed-optimizer/tests/test-cases/single-youtube-embed-inside-viewport-with-only-mobile-url-metrics/expected.html b/plugins/embed-optimizer/tests/test-cases/single-youtube-embed-inside-viewport-with-only-mobile-url-metrics/expected.html index 4682d12039..6ae5c6e764 100644 --- a/plugins/embed-optimizer/tests/test-cases/single-youtube-embed-inside-viewport-with-only-mobile-url-metrics/expected.html +++ b/plugins/embed-optimizer/tests/test-cases/single-youtube-embed-inside-viewport-with-only-mobile-url-metrics/expected.html @@ -3,7 +3,9 @@ ... diff --git a/plugins/embed-optimizer/tests/test-cases/single-youtube-embed-inside-viewport/expected.html b/plugins/embed-optimizer/tests/test-cases/single-youtube-embed-inside-viewport/expected.html index 17bfe841c2..db1704eba8 100644 --- a/plugins/embed-optimizer/tests/test-cases/single-youtube-embed-inside-viewport/expected.html +++ b/plugins/embed-optimizer/tests/test-cases/single-youtube-embed-inside-viewport/expected.html @@ -3,10 +3,18 @@ ... diff --git a/plugins/embed-optimizer/tests/test-cases/single-youtube-embed-outside-viewport-on-mobile/expected.html b/plugins/embed-optimizer/tests/test-cases/single-youtube-embed-outside-viewport-on-mobile/expected.html index e70f057b48..0d4527a3ba 100644 --- a/plugins/embed-optimizer/tests/test-cases/single-youtube-embed-outside-viewport-on-mobile/expected.html +++ b/plugins/embed-optimizer/tests/test-cases/single-youtube-embed-outside-viewport-on-mobile/expected.html @@ -3,10 +3,18 @@ ... diff --git a/plugins/embed-optimizer/tests/test-cases/single-youtube-embed-outside-viewport-with-only-mobile-url-metrics/expected.html b/plugins/embed-optimizer/tests/test-cases/single-youtube-embed-outside-viewport-with-only-mobile-url-metrics/expected.html index 0ae23552d3..2b86a46a35 100644 --- a/plugins/embed-optimizer/tests/test-cases/single-youtube-embed-outside-viewport-with-only-mobile-url-metrics/expected.html +++ b/plugins/embed-optimizer/tests/test-cases/single-youtube-embed-outside-viewport-with-only-mobile-url-metrics/expected.html @@ -3,7 +3,9 @@ ... diff --git a/plugins/embed-optimizer/tests/test-cases/single-youtube-embed-outside-viewport/expected.html b/plugins/embed-optimizer/tests/test-cases/single-youtube-embed-outside-viewport/expected.html index 92a3c236ac..fe82dc6059 100644 --- a/plugins/embed-optimizer/tests/test-cases/single-youtube-embed-outside-viewport/expected.html +++ b/plugins/embed-optimizer/tests/test-cases/single-youtube-embed-outside-viewport/expected.html @@ -3,10 +3,18 @@ ...