components
components copied to clipboard
bug(Youtube player): width not responsive
Is this a regression?
- [X] Yes, this behavior used to work in the previous version
The previous version in which this bug was not present was
I only noticed it after a couple of upgrades, so I don't know exactly.
Description
Related: https://github.com/angular/components/issues/28489 However the workarounds that are mentioned there don't work anymore.
Setting width="100%" does not work as the input is transformed into a number type:
https://github.com/angular/components/blob/main/src/youtube-player/youtube-player.ts#L148
What is the solution approach to get the component to display responsively so it shows up correctly on both mobile and desktop?
Reproduction
StackBlitz link: https://stackblitz.com/edit/angular-youtube-player-responsive-issue?file=src%2Fmain.ts Steps to reproduce:
- Open the StackBlitz link
- Optionally make the preview window smaller.
- Check the browser preview to confirm that the video is overflowing the page width.
Expected Behavior
It shoult take the whole width of the screen
Actual Behavior
The video overflows the with of its parent elements.
Environment
- Angular: 17.0.1
- Browser(s): Stackblitz bundled
- Operating System (e.g. Windows, macOS, Ubuntu): online
Anyone looking for a temporary fix until the bug is resolved:
- In your component HTML add
[width]="width"attribute to the<youtube-player>element - In your component TS add:
- In the constructor:
private winRef: WindowRef = inject(WindowRef); public width: number; this.width = this.winRef.nativeWindow?.innerWidth ?? 0;.
- In the constructor:
- If you need to compensate for some padding or margin in your page, just subtract that from the width value.
Now only the width and height numbers work, because now the check happens like this
this._height = height == null || isNaN(height) ? DEFAULT_PLAYER_HEIGHT : height;
you can create a responsive container and use ResizeObserver to get its size. for example
function resizeObservable(elem: Element, options?: ResizeObserverOptions): Observable<ResizeObserverEntry> { return new Observable((subscriber) => { const resizeObserver = new ResizeObserver(([entry]) => { subscriber.next(entry); }); resizeObserver.observe(elem, options); return function unsubscribe(): void { resizeObserver.unobserve(elem); }; }); }
and in component
<div #playerContainer style="width=50%; height: 50%"><youtube-player [height]="playerHeight()" [width]="playerWidth()" [videoId]="videoId"></youtube-player>
@ViewChild('playerContainer', {static: true}) public playerContainerRef?: ElementRef<HTMLElement>; public playerWidth = signal(NaN); public playerHeight = signal(NaN); ngOnInit(): void { if (this.playerContainerRef) { resizeObservable(this.playerContainerRef.nativeElement) .pipe( map(({ contentRect: { height, width } }) => ({ height, width })), distinctUntilChanged((a, b) => a.height === b.height && a.width === b.width), takeUntilDestroyed(this.destroyRef), ) .subscribe(({height,width}) => { this.playerHeight.set(height); this.playerWidth.set(width); }); } }
For now I created a custom component with a wrapper and I'm setting the wrapper height and width on it instead of the angular video player component. And then I set the iframe full width/height.
youtube-player > *,
youtube-player iframe {
width: 100% !important;
height: 100% !important;
}
This is a another workaround it seems. I'm still looking forward to having an official way to do it. ;)
I am also experiencing this issue. Before I was able to set width 100%, now it defaults to 640 because it is no longer a number. Thanks for the worksarounds. I hope the maintainer can allow us to use width 100% again.
We ran into the same issue that youtube videos stopped being responsive. Looks like the issue originated with this commit https://github.com/angular/components/commit/381a65f33d87c885235d2076297f092d6c218bae . Technically, only pixel values are allowed for width/height according to the html5 spec, so this change makes sense. However, browsers seem to tolerate % values. Any thoughts @crisbeto ?
The proposed workarounds seem to mess with aspect ratio or require typescript, so here is another one that only uses css and keeps a fixed aspect ratio:
youtube-player {
position: relative;
padding-top: 56.25%; // 16:9 ratio
}
:host ::ng-deep youtube-player > *, {
position: absolute;
top: 0;
left: 0;
width: 100%!important;
height: 100%!important;
}
:host ::ng-deep youtube-player iframe {
width: 100% !important;
height: 100% !important;
}
One downside: you need to know the aspect ratio beforehand and calculate padding-top on the youtube-player styling accordingly.
Please fix this, responsiveness should be supported by default in 2024.
Issue is still present in 18.1.1.
String inputs "width" and "height" where we could set "200px" or "100%" would be perfect.