Skip to content

Commit aa960c0

Browse files
authored
Merge pull request #15056 from guardian/fix-aspect-ratio
Support full-width looping videos in articles
2 parents 6a64656 + dd67624 commit aa960c0

File tree

4 files changed

+40
-16
lines changed

4 files changed

+40
-16
lines changed

dotcom-rendering/src/components/Card/Card.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1013,6 +1013,7 @@ export const Card = ({
10131013
}
10141014
subtitleSize={subtitleSize}
10151015
enableHls={enableHls}
1016+
letterboxed={true}
10161017
/>
10171018
</Island>
10181019
)}

dotcom-rendering/src/components/LoopVideoInArticle.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,17 @@ export const LoopVideoInArticle = ({
2929
return null;
3030
}
3131

32+
const calculateAspectRatio = (): number => {
33+
const dimensions = firstVideoAsset?.dimensions;
34+
35+
if (dimensions) {
36+
return dimensions.width / dimensions.height;
37+
}
38+
39+
// Default aspect ratio if dimensions are not available
40+
return 5 / 4;
41+
};
42+
3243
return (
3344
<>
3445
<Island priority="critical" defer={{ until: 'visible' }}>
@@ -39,6 +50,7 @@ export const LoopVideoInArticle = ({
3950
fallbackImageAspectRatio={
4051
(firstVideoAsset?.aspectRatio ?? '5:4') as FEAspectRatio
4152
}
53+
containerAspectRatio={calculateAspectRatio()}
4254
fallbackImageLoading="lazy"
4355
fallbackImageSize="small"
4456
height={firstVideoAsset?.dimensions?.height ?? 400}

dotcom-rendering/src/components/SelfHostedVideo.importable.tsx

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -55,20 +55,23 @@ const videoContainerStyles = (
5555
}
5656
`;
5757

58-
const figureStyles = (aspectRatio: number) => css`
58+
const figureStyles = (aspectRatio: number, letterboxed: boolean) => css`
5959
position: relative;
6060
aspect-ratio: ${aspectRatio};
6161
height: 100%;
62-
max-height: 100vh;
63-
max-height: 100svh;
64-
max-width: 100%;
65-
${from.tablet} {
66-
/**
67-
* The value "80" is derived from the aspect ratio of the 5:4 slot.
68-
* When other slots are used for self-hosted videos, this will need to be adjusted.
69-
*/
70-
max-width: ${aspectRatio * 80}%;
71-
}
62+
${letterboxed &&
63+
css`
64+
max-height: 100vh;
65+
max-height: 100svh;
66+
max-width: 100%;
67+
${from.tablet} {
68+
/**
69+
* The value "80" is derived from the aspect ratio of the 5:4 slot.
70+
* When other slots are used for self-hosted videos, this will need to be adjusted.
71+
*/
72+
max-width: ${aspectRatio * 80}%;
73+
}
74+
`}
7275
`;
7376

7477
/**
@@ -150,6 +153,7 @@ type Props = {
150153
subtitleSource?: string;
151154
subtitleSize: SubtitleSize;
152155
enableHls: boolean;
156+
letterboxed?: boolean;
153157
};
154158

155159
export const SelfHostedVideo = ({
@@ -170,6 +174,7 @@ export const SelfHostedVideo = ({
170174
subtitleSource,
171175
subtitleSize,
172176
enableHls,
177+
letterboxed = false,
173178
}: Props) => {
174179
const adapted = useShouldAdapt();
175180
const { renderingTarget } = useConfig();
@@ -703,7 +708,7 @@ export const SelfHostedVideo = ({
703708
>
704709
<figure
705710
ref={setNode}
706-
css={figureStyles(aspectRatio)}
711+
css={figureStyles(aspectRatio, letterboxed)}
707712
className={`video-container ${videoStyle.toLocaleLowerCase()}`}
708713
data-component="gu-video-loop"
709714
>
@@ -737,6 +742,7 @@ export const SelfHostedVideo = ({
737742
subtitleSize={subtitleSize}
738743
activeCue={activeCue}
739744
enableHls={enableHls}
745+
letterboxed={letterboxed}
740746
/>
741747
</figure>
742748
</div>

dotcom-rendering/src/components/SelfHostedVideoPlayer.tsx

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,16 @@ import { VideoProgressBar } from './VideoProgressBar';
2323

2424
export type SubtitleSize = 'small' | 'medium' | 'large';
2525

26-
const videoStyles = (aspectRatio: number) => css`
26+
const videoStyles = (aspectRatio: number, letterboxed: boolean) => css`
2727
position: relative;
2828
display: block;
2929
height: auto;
3030
width: 100%;
31-
max-height: 100vh;
32-
max-height: 100svh;
31+
${letterboxed &&
32+
css`
33+
max-height: 100vh;
34+
max-height: 100svh;
35+
`}
3336
cursor: pointer;
3437
/* Prevents CLS by letting the browser know the space the video will take up. */
3538
aspect-ratio: ${aspectRatio};
@@ -127,6 +130,7 @@ type Props = {
127130
/* used in custom subtitle overlays */
128131
activeCue?: ActiveCue | null;
129132
enableHls: boolean;
133+
letterboxed: boolean;
130134
};
131135

132136
/**
@@ -169,6 +173,7 @@ export const SelfHostedVideoPlayer = forwardRef(
169173
subtitleSize,
170174
activeCue,
171175
enableHls,
176+
letterboxed,
172177
}: Props,
173178
ref: React.ForwardedRef<HTMLVideoElement>,
174179
) => {
@@ -199,7 +204,7 @@ export const SelfHostedVideoPlayer = forwardRef(
199204
<video
200205
id={videoId}
201206
css={[
202-
videoStyles(aspectRatio),
207+
videoStyles(aspectRatio, letterboxed),
203208
showSubtitles && subtitleStyles(subtitleSize),
204209
]}
205210
crossOrigin="anonymous"

0 commit comments

Comments
 (0)