Skip to content

bug(Youtube player): width not responsive #28829

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
1 task done
Eraldo opened this issue Apr 5, 2024 · 9 comments
Open
1 task done

bug(Youtube player): width not responsive #28829

Eraldo opened this issue Apr 5, 2024 · 9 comments
Labels
area: youtube-player P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent

Comments

@Eraldo
Copy link

Eraldo commented Apr 5, 2024

Is this a regression?

  • 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: #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:

  1. Open the StackBlitz link
  2. Optionally make the preview window smaller.
  3. 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
@Eraldo Eraldo added the needs triage This issue needs to be triaged by the team label Apr 5, 2024
@kevinriemens
Copy link

kevinriemens commented Apr 8, 2024

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;.
  • If you need to compensate for some padding or margin in your page, just subtract that from the width value.

@amysorto amysorto added P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent area: youtube-player and removed needs triage This issue needs to be triaged by the team labels Apr 9, 2024
@StepaZol
Copy link

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); }); } }

@Eraldo
Copy link
Author

Eraldo commented Apr 25, 2024

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. ;)

@mattiLeBlanc
Copy link

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.

@MarcoGlauser
Copy link

We ran into the same issue that youtube videos stopped being responsive. Looks like the issue originated with this commit 381a65f .
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 ?

@hassmal
Copy link

hassmal commented Jun 19, 2024

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.

@martinboue
Copy link

Issue is still present in 18.1.1.

String inputs "width" and "height" where we could set "200px" or "100%" would be perfect.

@Baruch055
Copy link

I did this:
html:

<youtube-player *ngIf="videoId" [videoId]="videoId" disablePlaceholder [playerVars]="playerConfig" [width]="iframeWidth"
    [height]="iframeHeight" />

TS:

 iframeWidth = window.innerWidth / 100 * 80;
  iframeHeight = this.iframeWidth * 9 / 16;

And it works great.
Hope this helps someone.

@developedbydb
Copy link

I ran into the same issue where the YouTube video player in Angular wasn't resizing properly with screen size changes. Here's a solution that worked for me to dynamically adjust the width and height.

your-component.component.html:

<youtube-player
  [videoId]="'YOUR_VIDEO_ID'"
  loadApi="false"
  [width]="iframeWidth"
  [height]="iframeHeight">
</youtube-player>

your-component.component.css:

:host ::ng-deep youtube-player iframe,
:host ::ng-deep youtube-player-placeholder {
  width: 100% !important;
  height: auto !important;
  aspect-ratio: 16/9; /* adjust aspect ratio */
}

your-component.component.ts:

import { Component, OnInit, OnDestroy, inject, PLATFORM_ID } from '@angular/core';
import { isPlatformBrowser } from '@angular/common';

@Component({
  selector: 'your-component',
  templateUrl: './your-component.component.html',
styleUrls: ['./your-component.component.css'],
})
export class YourComponent implements OnInit, OnDestroy {
  private platformId = inject(PLATFORM_ID);
  private isBrowser = isPlatformBrowser(this.platformId);
  private resizeObserver: ResizeObserver | null = null;

  iframeWidth = 800;
  iframeHeight = 450;

  ngOnInit() {
    if (this.isBrowser) {
      this.setupResizeObserver();
      this.loadYouTubePlayer();
    }
  }

  private setupResizeObserver() {
    const container = document.querySelector('.youtube-container');
    if (container) {
      this.resizeObserver = new ResizeObserver(entries => {
        const width = entries[0].contentRect.width;
        this.updatePlayerSize(width);
      });
      this.resizeObserver.observe(container);
    }
  }

  private updatePlayerSize(width: number) {
    this.iframeWidth = width;
    this.iframeHeight = width * (9 / 16);
  }

  private loadYouTubePlayer() {
    if (!(window as any).YT) {
      const tag = document.createElement('script');
      tag.src = "https://www.youtube.com/iframe_api";
      document.body.appendChild(tag);
    }
  }

  ngOnDestroy() {
    this.resizeObserver?.disconnect();
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: youtube-player P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent
Projects
None yet
Development

No branches or pull requests

10 participants