Skip to content

Commit 8dba918

Browse files
committed
Responsive images in style guide.
1 parent c84e49d commit 8dba918

1 file changed

Lines changed: 104 additions & 1 deletion

File tree

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

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

0 commit comments

Comments
 (0)