Search code examples
cssangularmedia-queries

Using proper CSS media queries in Angular


I read that in Angular it is a very bad practice to use the CSS hidden element to hide an element like this:

.container{
  background-color : powderblue;
  height : 50px;
  width : 100%
}

@media (max-width: 400px){
    .container{
        display: none;
    }

}
<div class="container"></div>

And I know the Angular way to show or hide an element is using the *ngIf directive.

Question

How can I get the * ngIf to react on the media query in an 'Angular fashion'?


Solution

  • You can use angular/breakpoints-angular-cdk

    follow these steps

    on the terminal

    npm install @angular/cdk
    

    Then import the layout module and and add it to your NgModule’s list of imports

    import { BrowserModule } from '@angular/platform-browser';
    import { NgModule } from '@angular/core';
    import { LayoutModule } from '@angular/cdk/layout';
    
    import { AppComponent } from './app.component';
    
    @NgModule({
      declarations: [
      AppComponent
    ],
    imports: [
        BrowserModule,
        LayoutModule
    ],
    providers: [],
    bootstrap: [AppComponent]
    })
    

    right after you can use it in your component, just import these classes from @angular/cdk/layout

    import { Component, OnInit } from '@angular/core';
    import { BreakpointObserver, BreakpointState } from '@angular/cdk/layout';
    
    @Component({ ... })
    export class AppComponent implements OnInit {
      public showContainer: boolean;
      constructor(public breakpointObserver: BreakpointObserver) {}
    
      ngOnInit() {
        this.breakpointObserver
          .observe(['(min-width: 400px)'])
          .subscribe((state: BreakpointState) => {
            if (state.matches) {
              this.showContainer = true;
            } else {
              this.showContainer = false;
            }
          });
      }
    }
    

    Check the docs it is a simple API

    !! Attention to the new angular version, there is a better way of doing it !!

    UPDATE IF YOU'RE USING A NEWER VERSION OF ANGULAR, THERE IS A CONSTANT TO HELP WITH THE SCREEN SIZE IDENTIFICATION

    import { Component, OnInit } from '@angular/core';
    import { BreakpointObserver, BreakpointState, Breakpoints } from '@angular/cdk/layout';
    // NEW Breakpoints CONSTANT
    @Component({ ... })
    export class AppComponent implements OnInit {
      public showContainerInTablet: boolean;
      public showContainerInHandset: boolean;
      constructor(public breakpointObserver: BreakpointObserver) {}
    
      ngOnInit() {
        this.breakpointObserver
          .observe([
            Breakpoints.TabletPortrait,
            Breakpoints.HandsetLandscape
          ])
          .subscribe((state ) => {
            const breakpoints = state.breakpoints;
            this.showContainerInHandset = false;
            this.showContainerInTablet = false;
            if (breakpoints[Breakpoints.TabletPortrait]) {
             this.showContainerInTablet = true;
             console.log("screens matches TabletPortrait");
            }
            else if (breakpoints[Breakpoints.HandsetLandscape]) {
             this.showContainerInHandset = true;
             console.log("screens matches HandsetLandscape");
           } 
          });
      }
    }
    

    Check the tutorial on angular website