0

I have a big parent element that contains multiple childs elements and the parent has overflow-y: auto. When the screen size is small (400 px to 700 px) I want that one of the child component will fit to the screen size, and only the child component will be seen (without overflow).

At the beginning I thought doing it with media queries. The problem is that in media queries:

@media (min-width: 400px) and (max-width: 700px) {
   //
}

It takes the window innerWidth. I saw that what I need is something like window.outerWidth (the screen size and not the content size inside the browser window).

So, I tried using:

    @HostListener('window:resize', ['$event'])
private onResize(): void {
    const outerWidth: number = window.outerWidth;
    const smallScreenClassName: string = 'small-screen';
    const isContainSmallScreen: boolean = this.el.nativeElement.classList.contains(smallScreenClassName);

    this.el.nativeElement.style.width = "";

    if (outerWidth >= 400 && outerWidth <= 700) {
        this.el.nativeElement.classList.add(smallScreenClassName);
        this.el.nativeElement.style.width = `${outerWidth}px`;
    }
    else if (isContainSmallScreen) {
        this.el.nativeElement.classList.remove(smallScreenClassName);
    }
}

But this is not good enough because I found that the outerWidth is not precise, sometimes the child component doesn't fit to the screen.

Is there any better way to do what I am trying to do?

RoG
  • 411
  • 4
  • 20

1 Answers1

0

I had a similar use-case for redrawing some d3 charts when the window was resized. In the end I set up a separate service to detect the initial screen size and monitor changes:

import { Injectable } from '@angular/core';
import { Observable, fromEvent } from 'rxjs';
import { map, debounceTime, startWith } from 'rxjs/operators';

@Injectable({
  providedIn: 'root'
})
export class WindowResizeService {
  windowSize$: Observable<WindowDimensions>;
  windowInit$: Observable<Event>;

  constructor() {
    this.windowSize$ = fromEvent(window, 'resize').pipe(debounceTime(100),
      map(event => {
        return { width: (event.target as Window).innerWidth, height: (event.target as Window).innerHeight };
      }),
      startWith({ width: (window as Window).innerWidth, height: (window as Window).innerHeight }),
    );
  }

}

export interface WindowDimensions { width: number; height: number; }

Then you can subscribe to this from your component and make any necessary adjustments to your layout accordingly, based on the value of resize.

import { Subscription } from 'rxjs';
import { WindowResizeService } from './window-resize.service';

constructor(private windowResizeService: WindowResizeService) { }

windowResizeSub: Subscription;

ngAfterViewInit() {
  this.windowResizeSub = this.windowResizeService.windowSize$.subscribe(resize => {
    // Make your layout adjustments here
    console.log(resize);
  });
}

ngOnDestroy() {
  if (this.windowResizeSub) {
    this.windowResizeSub.unsubscribe();
  }
}
Matt Saunders
  • 3,538
  • 2
  • 22
  • 30
  • Hi, thanks for your response. This is not what I am looking for.. I want the width of the browser's window without the scroll. i.e: if you change the window with the chrome extension 'Window resizer' to 400 * 700, how can I find the width 400px from the code? – RoG Jul 20 '20 at 10:44
  • If you just want to set something to the width of the viewport on a given device, using viewport CSS units (rather than px) will be the cleanest choice. E.g. width:100vw; will set the width of a div to the full width of the viewport https://css-tricks.com/fun-viewport-units/ – Matt Saunders Jul 20 '20 at 10:53
  • This doesn't work when the child's parent has bigger width (the parent has scroll). I don't want that the child component wdth be the parent's with, just the pageWidth – RoG Jul 20 '20 at 10:58
  • This is the closest width I have found: window.outerWidth. But I am not sure why it's not precise (it's bigger than the width I am expecting to find) – RoG Jul 20 '20 at 11:19
  • It sounds like this is the layout you're looking for, unless I misunderstand? https://stackblitz.com/edit/js-rvn7bh?file=index.html – Matt Saunders Jul 20 '20 at 13:28
  • Thanks. I found out that In ancestor parent I have min-width. This is the problem that I can't override it from the child component. – RoG Jul 21 '20 at 06:44
  • 1
    Ah. If it's an Angular app you could add a media query to `styles.css` to override the min-width in the parent for mobile devices. Or you can use Renderer 2 to change the style from your child component; see this answer for how to select the parent https://stackoverflow.com/a/55224857/2627160 and this one for changing the style https://stackoverflow.com/a/51911002/2627160 – Matt Saunders Jul 21 '20 at 08:31