Skip to content

Commit 08472dc

Browse files
committed
Responsive images in style guide.
1 parent c84e49d commit 08472dc

1 file changed

Lines changed: 103 additions & 1 deletion

File tree

web/modules/custom/server_style_guide/src/Controller/StyleGuideController.php

Lines changed: 103 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -619,8 +619,24 @@ protected function getTextStyles(): array {
619619
protected function getHeroImage(): array {
620620
$url = Url::fromRoute('<front>');
621621

622+
$image_dimensions = [
623+
'mobile' => [
624+
'1x' => [768, 576],
625+
'2x' => [1536, 1152],
626+
],
627+
'md' => [
628+
'1x' => [1024, 580],
629+
'2x' => [1536, 1160],
630+
],
631+
'lg' => [
632+
'1x' => [1440, 800],
633+
'2x' => [2880, 1600],
634+
],
635+
];
636+
$image = $this->buildResponsiveImage($image_dimensions, 'image_item', 'seed');
637+
622638
return $this->buildElementHeroImage(
623-
$this->buildImage($this->getPlaceholderImage(1600, 400)),
639+
$image,
624640
$this->getRandomTitle(),
625641
$this->getRandomTitle(),
626642
Link::fromTextAndUrl('Learn more', $url),
@@ -772,6 +788,92 @@ protected function buildImage(string $url) {
772788
];
773789
}
774790

791+
/**
792+
* Build a responsive image using a <picture> element with breakpoint sources.
793+
*
794+
* Uses server_theme breakpoints to produce <source> elements per breakpoint.
795+
* Each breakpoint key maps to srcset multipliers (1x, 2x) with [width, height].
796+
*
797+
* @param array $image_dimensions
798+
* Dimensions keyed by breakpoint, subkeyed by multiplier. Example:
799+
* @code
800+
* [
801+
* 'mobile' => ['1x' => [400, 300], '2x' => [800, 600]],
802+
* 'sm' => ['1x' => [640, 480], '2x' => [1280, 960]],
803+
* 'md' => ['1x' => [768, 576], '2x' => [1536, 1152]],
804+
* 'lg' => ['1x' => [1024, 768], '2x' => [2048, 1536]],
805+
* ]
806+
* @endcode
807+
* @param string $id
808+
* The placeholder image ID or seed.
809+
* @param string $id_type
810+
* The type of the ID, either 'id' or 'seed'.
811+
* @param string $alt
812+
* Alt text.
813+
*
814+
* @return array
815+
* A render array for a <picture> element.
816+
*/
817+
private function buildResponsiveImage(array $image_dimensions, string $id = '', string $id_type = 'id', string $alt = ''): array {
818+
$breakpoint_media_queries = [
819+
'2xl' => 'all and (min-width: 1536px)',
820+
'xl' => 'all and (min-width: 1280px)',
821+
'lg' => 'all and (min-width: 1024px)',
822+
'md' => 'all and (min-width: 768px)',
823+
'sm' => 'all and (min-width: 640px)',
824+
'mobile' => '',
825+
];
826+
827+
$sources = [];
828+
// Iterate from largest to smallest so the browser picks the first match.
829+
foreach ($breakpoint_media_queries as $breakpoint => $media_query) {
830+
if (!isset($image_dimensions[$breakpoint])) {
831+
continue;
832+
}
833+
834+
$srcset_parts = [];
835+
foreach ($image_dimensions[$breakpoint] as $multiplier => $dimensions) {
836+
[$width, $height] = $dimensions;
837+
$url = $this->getPlaceholderImage($width, $height, $id, $id_type);
838+
$srcset_parts[] = "$url {$multiplier}";
839+
}
840+
841+
$source = [
842+
'#type' => 'html_tag',
843+
'#tag' => 'source',
844+
'#attributes' => [
845+
'srcset' => implode(', ', $srcset_parts),
846+
],
847+
];
848+
if (!empty($media_query)) {
849+
$source['#attributes']['media'] = $media_query;
850+
}
851+
$sources[] = $source;
852+
}
853+
854+
// Fallback <img> using the mobile 1x dimensions.
855+
$fallback_breakpoint = isset($image_dimensions['mobile']) ? 'mobile' : array_key_first($image_dimensions);
856+
$fallback_dimensions = $image_dimensions[$fallback_breakpoint]['1x'];
857+
[$fallback_width, $fallback_height] = $fallback_dimensions;
858+
859+
$sources[] = [
860+
'#type' => 'html_tag',
861+
'#tag' => 'img',
862+
'#attributes' => [
863+
'src' => $this->getPlaceholderImage($fallback_width, $fallback_height, $id, $id_type),
864+
'alt' => $alt,
865+
'width' => $fallback_width,
866+
'height' => $fallback_height,
867+
],
868+
];
869+
870+
return [
871+
'#type' => 'html_tag',
872+
'#tag' => 'picture',
873+
'sources' => $sources,
874+
];
875+
}
876+
775877
/**
776878
* Build text with HTML.
777879
*

0 commit comments

Comments
 (0)