Gérer vos media queries en JS avec matchMedia

Publié le 03 Jun 2020

Les média queries en CSS sont fréquemment utilisés par les développeurs afin de dynamiser le rendu d'un document HTML pour qu'il soit adapté à tous les supports.

Cette méthode se caractérise généralement par un code de type :


        @media screen and (min-width:768px){
// do stuff
}
    

La problématique est que nous devons parfois utiliser ce procédé en Javascript pour créer des actions en live sur des breakpoints particuliers.

Gérer les media queries avec matchMedia.

matchMedia est une fonction native de Javascript, permettant de contrôler si on rentre dans une condition de media query ou non.

Par exemple :


        if (window.matchMedia("(min-width: 768px)").matches) {
    // do stuff when your screen width is greater than 768px
} else {
    // do stuff when your screen width is lower than 768px
}
    

Dans le cas présent, on regarde simplement si la taille de notre support est supérieure à 768px de large. Un exemple simple mais qui peut créer des fichiers Javascript très longs et assez difficiles à lire à vrai dire.

Une autre problématique peut également être la performance, car l'action Javascript que vous allez appliquer se jouera à chaque redimensionnement de fenêtre, même si vous ne l'augmentez que de quelques pixels de large sur votre écran.

Optimiser ses media queries avec mediaMatch à l'aide des listeners.

Le traitement peut donc être un peu différent en déclarant en amont nos variables de matches et en checkant ensuite lorsqu'on rentre dans ces matches.

Voici un exemple un peu plus complet :


        // Matches settings
var portraitLandscape = window.matchMedia("(orientation: landscape)");
var mobile = window.matchMedia("(max-width: 768px)");
var tabletPortrait = window.matchMedia("(max-width: 991px)");
var tabletLandscape = window.matchMedia("(max-width: 1199px)");

// Manage orientation
portraitLandscape.addListener(function(m) {
    if(m.matches) {
        // Changed to landscape
    } else {
        // Changed to portrait
    }
});
// Manage mobile
mobile.addListener(function(m) {
    if(m.matches) {
        // Change to Mobile format
    }
});
// Manage tabletPortrait
tabletPortrait.addListener(function(m) {
    if(m.matches) {
        // Change to tabletPortrait format
    }
});
// Manage tabletLandscape
tabletLandscape.addListener(function(m) {
    if(m.matches) {
        // Change to tabletLandscape format
    }else{
        // Change to greater than 1199px
    }
});
    

Dans ce cas, la gestion se fait au redimensionnement ou lorsque vous changez l'orientation de votre écran.

La problématique est que lors du chargement de la page, ces actions ne sont pas prises en compte.

On peut donc modifier un peu ce code.

Gérer ses media queries avec mediaMatch au chargement et au redimensionnement de la page.

Voici le code complet de notre exemple, permettant de gérer les breakpoints au chargement de la page, au redimensionnement de la fenêtre et au changement d’orientation de l’écran :


        // Matches settings
var portraitLandscape = window.matchMedia("(orientation: landscape)");
var mobile = window.matchMedia("(max-width: 768px)");
var tabletPortrait = window.matchMedia("(max-width: 991px)");
var tabletLandscape = window.matchMedia("(max-width: 1199px)");

if(portraitLandscape.matches) {
   // Loaded to landscape
} else {
    // Loaded to portrait
}

if(mobile.matches) {
    // Loaded to Mobile format
}
if(tabletPortrait.matches) {
    // Loaded to tabletPortrait format
}
if(tabletLandscape.matches) {
    // Loaded to tabletLandscape format
}else{
    // Loaded to greater than 1199px
}

// Manage orientation
portraitLandscape.addListener(function(m) {
    if(m.matches) {
        // Changed to landscape
    } else {
        // Changed to portrait
    }
});
// Manage mobile
mobile.addListener(function(m) {
    if(m.matches) {
        // Change to Mobile format
    }
});
// Manage tabletPortrait
tabletPortrait.addListener(function(m) {
    if(m.matches) {
        // Change to tabletPortrait format
    }
});
// Manage tabletLandscape
tabletLandscape.addListener(function(m) {
    if(m.matches) {
        // Change to tabletLandscape format
    }else{
        // Change to greater than 1199px
    }
});
    

Et la compatibilité dans tout ça ?

Les matchMedia sont pris en compte sur la plupart des navigateurs récents comme vous pouvez le voir sur CanIUse :

https://caniuse.com/#feat=matchmedia

Un exemple live ?

Bien entendu, voici un exemple simple :

https://jsfiddle.net/comtocode/pfvdn24b/17/

Et voila !