Javascript

La méthode matchMedia ou les Media Queries pour JavaScript

Article par (Alsacréations, Strasbourg)
Créé le , mis à jour le (29723 lectures)
Tags : javascript, media queries, media, matchmedia

Vous connaissez certainement les Media Queries CSS. Celles-ci permettent d'adapter les instructions de style appliquées à un document HTML, en fonction de nombreux critères (résolution de l'écran, dimensions, périphérique de sortie). C'est la technique la plus souple et la plus utilisée actuellement pour ajuster dynamiquement l'affichage et obtenir un rendu graphique différent sur écrans classiques, mobiles, tablettes, et autres moyens d'accéder au web.

Avec matchMedia(), les mêmes capacités de détection sont rendues disponibles en JavaScript. La syntaxe de la requête média reste la même, ce qui est bien agréable. Ainsi, il sera possible de déclencher des actions complémentaires à ce que l'on peut déjà construire en CSS, que ce soit au chargement du document ou bien à n'importe quel moment à la demande en exécutant matchMedia().

C'est une méthode qui dépend de l'objet window (la fenêtre du navigateur) et qui prend en argument une chaîne de texte contenant l'expression à tester, pour retourner true ou false via sa propriété matches.

<script>
if (window.matchMedia("(min-width: 600px)").matches) {
  /* La largeur minimum de l'affichage est 600 px inclus */
} else {
  /* L'affichage est inférieur à 600px de large */
}
</script>

Voir la démonstration n°1

Si l'on examine de plus près l'objet retourné dans une console JavaScript...

matchMedia console

Celui-ci est de type MediaQueryList, et équipé de deux propriétés de base :

  • matches (booléen true/false qui permet de faire le test)
  • media (la requête elle-même)

Bien sûr, cette méthode vient en complément de CSS et n'est pas vouée à remplacer les Media Queries là où elles sont déjà efficaces. Le but est de se brancher sur la gestion de la détection pour aller plus loin qu'une conséquence sur l'affichage des éléments.

// Fonction exécutée au redimensionnement
function redimensionnement() {
  var result = document.getElementById('result');
  if("matchMedia" in window) { // Détection
    if(window.matchMedia("(min-width:600px)").matches) {
      // Il y a de la place
    } else {
      // Il y en a moins...
    }
  }
}
// On lie l'événement resize à la fonction
window.addEventListener('resize', redimensionnement, false);

L'événement resize est tout indiqué pour déclencher une vérification avec matchMedia(). Consultez l'exemple suivant pour le voir en action.

Voir la démonstration n°2

Le dernier exemple va plus loin en chargeant des fichiers JavaScript selon le résultat renvoyé par matchMedia().

if(window.matchMedia("(min-width:800px)").matches) {
  // Chargement de jQuery dans un nouvel élément <script> ajouté à la section <head>
  var script1 = document.createElement('script');
  script1.type='text/javascript';
  script1.src = '//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js';
  script1.onload = function() {
    // Lorsque jQuery est chargé...
    // On fait la même chose : chargement dynamique // mais cette fois-ci avec jQuery (c'est plus simple)
    $.getScript('slideshow.js');
  }
  // Insertion dans le DOM de la balise script initiale
  document.getElementsByTagName('head')[0].appendChild(script1);
}

Il s'agit de faire appel à jQuery et un autre fichier de script conçu sur mesure pour lancer un slideshow si la largeur de l'affichage le permet.

Voir la démonstration n°3

Cette technique ici sert uniquement à la démonstration et exploite un script minimaliste pour sa compréhension. L'intérêt majeur serait de pouvoir détecter ce que l'on ne peut pas faire avec du JavaScript conventionnel, par exemple l'orientation (mentionnée précédemment) ou la densité de pixels pour charger des images appropriées : une démonstration est disponible sur Thinkmobilefirst : Conditional retina pictures loading.

Tableau des compatibilités

Navigateurs Versions
Internet Explorer Internet Explorer 10
Firefox Firefox 6
Firefox Android 15
Chrome Chrome 9
Chrome Mobile 18 (Android 4+)
Opera Opera 12.1
Opera Mobile 12.1
Safari

Safari 5.1 Safari Mobile 5.0

Android Browser Android Browser 3.0
Blackberry Logo Blackberry Browser 10

Pour les anciens moteurs qui ne supporteraient pas nativement matchMedia, il existe des bibliothèques JavaScript, détectant (du mieux qu'elles peuvent) les changements d'état, notamment matchMedia.js développée par Paul Irish.

Commentaires

tm™ a dit le

Merci pour l'article !
Tu as déjà testé enquire.js (http://wickynilliams.github.com/enquire.js/) ?

tm

rodolpheb a dit le

Super article,
Merci j'étais en plein dedans!! :)

Olivier C a dit le

Avec cette solution on peut commencer à prévoir des trucs pas mal. Par exemple, en lien avec un script jQuery comme ça pour la nav sur mobile :

http://css-tricks.com/examples/ConvertMenuToD...

Ce qui évite d'avoir des menus dupliqués, lié à un display:none sur l'un des deux menus en fonction de la résolution... comme on peut voir sur beaucoup de sites (pas très gracieux je trouve).

geoffreym a dit le

hello,
J'ai appliqué les media queries sur mon site.
Ce que j'ai fais, c'est vraiment une version différente du site lorsque l'écran est a moins de 800px. Du coup je me retrouve dans le HTML à avoir parfois 2 fois mon contenu. Au niveau de l'utilisateur ça ne change rien, mais est ce que c'est pas un problème pour le référencement ? Est ce que google peut sanctionner le fait d'avoir du contenu similaire non visible ? Merci
( http://www.geoffrey-menissier.fr )

jmlapam a dit le

@geoffreym tu devrais essayer de voir pour les max 1024 aussi.

Super article. Ça va bien m'aider dans mes projets. Merci.