@@ -30,22 +30,43 @@ import type {
3030import { SelfHostedVideoPlayer } from './SelfHostedVideoPlayer' ;
3131import { ophanTrackerWeb } from './YoutubeAtom/eventEmitters' ;
3232
33- const videoAndBackgroundStyles = ( isCinemagraph : boolean ) => css `
33+ const videoContainerStyles = (
34+ isCinemagraph : boolean ,
35+ videoAspectRatio : number ,
36+ aspectRatio ?: number , // The aspect ratio of the container
37+ ) => css `
3438 position : relative;
3539 display : flex;
3640 justify-content : space-around;
3741 background-color : ${ palette ( '--video-background' ) } ;
3842 ${ ! isCinemagraph && `z-index: ${ getZIndex ( 'video-container' ) } ` } ;
43+
44+ /**
45+ * If the video and its containing slot have different dimensions, the slot will use the aspect
46+ * ratio of the video on mobile, so that the video can take up the full width of the screen.
47+ *
48+ * From tablet breakpoints, the aspect ratio of the slot is maintained, for consistency with other content.
49+ * This will result in grey bars on either side of the video if the video is narrower than the slot.
50+ */
51+ aspect- ratio: ${ videoAspectRatio } ;
52+ ${ from . tablet } {
53+ ${ typeof aspectRatio === 'number' && `aspect-ratio: ${ aspectRatio } ;` }
54+ }
3955` ;
4056
41- const videoContainerStyles = ( width : number , height : number ) => css `
57+ const figureStyles = ( aspectRatio : number ) => css `
4258 position : relative;
59+ aspect-ratio : ${ aspectRatio } ;
4360 height : 100% ;
4461 max-height : 100vh ;
4562 max-height : 100svh ;
4663 max-width : 100% ;
4764 ${ from . tablet } {
48- max-width: ${ ( width / height ) * 80 } %;
65+ /**
66+ * The value "80" is derived from the aspect ratio of the 5:4 slot.
67+ * When other slots are used for self-hosted videos, this will need to be adjusted.
68+ */
69+ max-width: ${ aspectRatio * 80 } %;
4970 }
5071` ;
5172
@@ -113,6 +134,12 @@ type Props = {
113134 width : number ;
114135 videoStyle : VideoPlayerFormat ;
115136 posterImage : string ;
137+ /**
138+ * The desired aspect ratio of the container of the video, which can differ from the
139+ * aspect ratio of the video itself. Only applied from the tablet breakpoint, as below this
140+ * breakpoint, the video always takes up the full width of the screen.
141+ */
142+ containerAspectRatio ?: number ;
116143 fallbackImage : CardPictureProps [ 'mainImage' ] ;
117144 fallbackImageSize : CardPictureProps [ 'imageSize' ] ;
118145 fallbackImageLoading : CardPictureProps [ 'loading' ] ;
@@ -132,6 +159,7 @@ export const SelfHostedVideo = ({
132159 width : expectedWidth ,
133160 videoStyle,
134161 posterImage,
162+ containerAspectRatio,
135163 fallbackImage,
136164 fallbackImageSize,
137165 fallbackImageLoading,
@@ -656,17 +684,25 @@ export const SelfHostedVideo = ({
656684 }
657685 } ;
658686
687+ const aspectRatio = width / height ;
688+
659689 const AudioIcon = isMuted ? SvgAudioMute : SvgAudio ;
660690
661691 const optimisedPosterImage = showPosterImage
662692 ? getOptimisedPosterImage ( posterImage )
663693 : undefined ;
664694
665695 return (
666- < div css = { videoAndBackgroundStyles ( isCinemagraph ) } >
696+ < div
697+ css = { videoContainerStyles (
698+ isCinemagraph ,
699+ aspectRatio ,
700+ containerAspectRatio ,
701+ ) }
702+ >
667703 < figure
668704 ref = { setNode }
669- css = { videoContainerStyles ( width , height ) }
705+ css = { figureStyles ( aspectRatio ) }
670706 className = { `video-container ${ videoStyle . toLocaleLowerCase ( ) } ` }
671707 data-component = "gu-video-loop"
672708 >
0 commit comments