Enquire.js – Media Query Callbacks in JavaScript

Avatar of Nick Williams
Nick Williams am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Der folgende Text ist ein Gastbeitrag von Nick Williams. Nick hat mich wegen einer neuen Bibliothek kontaktiert, die er zur Unterstützung bei der Arbeit mit responsivem Design entwickelt hat. Insbesondere wollte er eine Idee umsetzen, die er hier auf CSS-Tricks gefunden hat, dies aber intelligenter zu gestalten, indem das Skript nur bei Bedarf ausgeführt wird. So entstand diese neue Mini-Bibliothek! Es gibt einige ähnliche Bibliotheken, aber diese ist sehr klein und funktioniert mit nativen Media Queries. Ich überlasse das Wort Nick…

Enquire.js ist eine JavaScript-Bibliothek, die ich für die Arbeit mit Media Queries in JavaScript erstellt habe.

„Halt! Rückzug! Media Queries in JavaScript?! Was für ein Scheusal ist das?“

Obwohl die Prämisse seltsam erscheinen mag, ist es wirklich eine praktische Ergänzung für das Werkzeugrepertoire des responsiven Designs.

Der Knackpunkt

Enquire.js ist eine leichtgewichtige, reine JavaScript-Bibliothek zur Verwaltung von Media Queries. Sie ist weniger als 1 KB groß, wenn sie GZIP-komprimiert und minimiert ist, und hat absolut keine Abhängigkeiten. Ja, Sie haben richtig gelesen – keine Abhängigkeiten, nicht einmal jQuery! Das Einzige, was Sie tun müssen, ist, ein matchMedia Polyfill bereitzustellen, wenn Sie Browser ohne native Implementierung unterstützen möchten.

Anwendungsfälle

  • Responsives Design
  • Mobile-First Design
  • Unterstützung älterer Browser mit Media Queries

Daseinsberechtigung

Wie und warum ist das entstanden? Ich denke, der einfachste Weg, dies zu erklären, ist ein einfaches Szenario…

Stellen Sie sich vor, Sie haben eine etablierte Website, die derzeit feste Breiten hat und für Geräte mit großen Bildschirmen konzipiert ist. Sie haben all den Trubel um dieses „responsive Design“-Geschäft gehört und möchten daran teilhaben. Also beginnen Sie pflichtbewusst mit der Gestaltung und Planung, wie Ihre Website auf Geräten mit kleinen Bildschirmen funktionieren könnte. Sie haben alles weggelassen, Ihren Floating-Sidebar ausgeblendet und die Größe Ihrer Formularelemente erhöht. Großartig!

Aber was ist mit diesem lästigen Menü? Es ist aufwendig, hat mehrere Ebenen und nutzt CSS-Hover-Effekte, um die tiefere Hierarchie anzuzeigen – mit anderen Worten, es funktioniert nicht auf einem Touch-Gerät mit kleinem Bildschirm!

Also graben Sie ein wenig bei Google und stoßen auf eine clevere Lösung, um ein Menü in ein Dropdown umzuwandeln. Hoch fünf für alle, Ihr Menü ist jetzt auf mobilen Touch-Geräten funktionsfähig! Aber Sie haben dieses nagende Gefühl. Sie sind sich nicht ganz sicher, was es ist, aber etwas stimmt immer noch nicht ganz. Ah ja, das ist es; Sie führen diesen Code sogar für Geräte mit großen Bildschirmen aus, obwohl diese ihn absolut nicht benötigen! Sie vergießen eine kleine Träne für die verschwendeten CPU-Zyklen und wünschen sich, es gäbe eine Möglichkeit, dieses JavaScript selektiv auszuführen.

Ein neuer Herausforderer erscheint!

Hier kommt enquire ins Spiel, um zu helfen.

Vorerst bleiben wir beim Szenario „Menü in ein Dropdown umwandeln“, wobei das Menü erscheint, wenn das Fenster kleiner als 960 Pixel ist. Mit enquire ist es so einfach:

enquire.register("max-width: 960px", function() {
  // put Chris' code here to convert your menu to a dropdown
});

All dies bedeutet nur, dass enquire die bereitgestellte Funktion nur aufruft, wenn die angegebene Media-Query übereinstimmt. Und so sparen Sie die wertvollen CPU-Zyklen für Geräte mit großen Bildschirmen. OK, ich erkenne an, dass das etwas albern ist, da mobile Geräte typischerweise über CPUs mit geringerer Leistung verfügen als Geräte mit größeren Bildschirmen, aber es funktioniert auch in umgekehrter Richtung – dem viel besungenen Mobile-First-Ansatz!

Tiefer eintauchen

An dieser Stelle lohnt es sich, kurz die enquire API durchzugehen, bevor wir uns einigen ausführlicheren Szenarien widmen. Das vorherige Beispiel zeigte den einfachsten Anwendungsfall für enquire – die Übergabe einer Funktion als zweiten Parameter, die ausgeführt wird, wenn eine Media-Query übereinstimmt. Dies ist in den meisten Szenarien ausreichend, aber enquire kann mehr bieten, wenn Sie anspruchsvollere Anforderungen haben. Sie können der register-Methode ein Objekt übergeben, wie hier:

enquire.register("screen and (max-width: 1000px)", {

  // REQUIRED
  // Triggered when the media query transitions
  // from *unmatched* to *matched*
  match : function() {},
  
  // OPTIONAL   
  // Triggered when the media query transitions 
  // from a *matched* to *unmatched*                        
  unmatch : function() {},    
                                
  // OPTIONAL
  // Triggered once immediately upon registration of handler
  setup : function() {},      
                                
  // OPTIONAL
  // Defaults to false
  // If true, defers execution of the setup function
  // until the first media query is matched (still just once)
  deferSetup : true           
});

Diese Signatur gibt Ihnen die volle Kontrolle und ermöglicht es Ihnen, genau zu definieren, was passieren soll und wann es passieren soll. Dies wird erst wirklich nützlich, wenn Sie die listen-Funktion von enquire aufrufen (mehr dazu gleich).

Beispiele

Kommen wir also zu einigen Beispielen, die die erweiterten Funktionen in Aktion zeigen.

Faux Media Queries in älteren Browsern

Enquire.js kann verwendet werden, um in älteren Browsern rudimentäre Media Queries zu simulieren. Bitte verwenden Sie diesen Ansatz jedoch nicht als Ersatz für echte Media Queries in Ihrem CSS, sondern nur als Monkey-Patch für ältere Browser (jQuery wird in diesem Beispiel verwendet).

$(function() {

  // cache body for speed
  var $body = $("body");

  // DRY up handler creation
  function handlerFactory(className) {
    return {
      match : function() {
        $body.addClass(className);
      },
      unmatch : function() {
        $body.removeClass(className);
      }
    };
  }

  // hook up our "media queries"
  enquire
    .register("screen and (max-width : 320px)", handlerFactory("lt-320"))
    .register("screen and (max-width : 640px)", handlerFactory("lt-640"))
    .listen();

});

Hier verwenden wir match- und unmatch-Handler, um dem <body>-Element Klassen hinzuzufügen oder zu entfernen, was es uns ermöglicht, Stile für Bildschirme unterschiedlicher Größe anzusprechen. Beachten Sie, dass wir Aufrufe aller Funktionen von enquire verketten können.

Besonders hervorzuheben ist hier der Aufruf der listen-Funktion, damit enquire auf Browser-Resize- und Orientierungswechselereignisse reagiert (obwohl Orientierungswechselereignisse in älteren Browsern unwahrscheinlich sind). Für optimale Leistung ist listen gedrosselt, um nur einmal pro Zeiteinheit auf ein Ereignis zu reagieren. Standardmäßig sind dies 500 ms, aber Sie können Ihre eigene Drosselung festlegen, indem Sie sie als Parameter an listen übergeben.

// 10000 milliseconds = 10 seconds. Why not?!
enquire.listen(10000); 

Dogfooding

Lassen Sie uns ein Beispiel für die reale Anwendung von enquire durchgehen, das von der Projektseite von enquire.js stammt (Dogfooding FTW!). Hier wollte ich, dass die Seite so schnell wie möglich geladen wird, indem standardmäßig nur das absolute Minimum an JavaScript geladen wird und alles darüber hinaus asynchron nachgeladen wird, nur wenn es benötigt wird. So erhalten Geräte mit kleinen Bildschirmen (und damit auch solche, die wahrscheinlich eine langsame Verbindung haben) die schnellstmögliche Seitenladezeit, und nur Geräte mit großen Bildschirmen müssen sich mit den zusätzlichen Ressourcen auseinandersetzen.

Insbesondere wird dieses Muster verwendet, um allen Code zu laden, der zum Erstellen und Rendern der Seitenleiste „Jump To“ der Projektseite erforderlich ist. Dieses Beispiel ist leicht vereinfacht, um nicht von den wichtigen Konzepten abzulenken.

$(function() {

  $toc = $(".toc");

  enquire.register("screen and (min-width: 1310px)", [{

    deferSetup : true,

    setup : function () {

      // use Modernizr's yepnope to load 
      // additional scripts and manage callbacks
      Modernizr.load([ 
        {
          load: "js/jquery.toc.js",
          callback : function() {
            // code to generate "Jump To" list
            // and append to body
          }
        },  

        // load in the bootstrap plugins.
        // they hook themselves up via their data-API
        "js/vendor/bootstrap-scrollspy.js",
        "js/vendor/bootstrap-affix.js"
      ]);
    },

    match : function() {
      $toc.fadeIn();
    },

    unmatch : function() {
      $toc.hide();
    }

  }]).listen();   

});

Hier wurden zwei neue Optionen eingeführt – setup und deferSetup. setup ist eine Funktion, die nur einmal aufgerufen wird, was großartig ist, um alle aufwendigen DOM-Manipulationen im Voraus zu erledigen. Standardmäßig wird setup *sofort nach der Registrierung Ihres Query-Handlers aufgerufen*, unabhängig davon, ob die Query bereits übereinstimmt. Wenn Sie jedoch das Flag deferSetup angeben, können wir das Setup auf den ersten Abgleich verschieben, wenn eine Query übereinstimmt.

In diesem Fall ist es offensichtlich sinnvoll, da Skripte nur für Geräte mit großen Bildschirmen geladen werden. Die Funktionen match und unmatch sind dann dafür zuständig, die Liste „Jump To“ einfach ein- und auszublenden.

Weitere Beispiele

Einige weitere Szenarien, die enquire mühelos bewältigen würde:

  • Responsive Bilder
    • Verwenden Sie data-*-Attribute und wechseln Sie das src eines Bildes je nachdem, welche Media-Query übereinstimmt.
  • Inhalte neu anordnen
    • Manchmal ist es nicht so einfach, Elemente auf kleinen Bildschirmen zu stapeln; Sie möchten vielleicht, dass Inhalte in einer völlig anderen Reihenfolge erscheinen.
    • Auch hier würde ich einen deklarativen Ansatz mit data-*-Attributen empfehlen, damit Sie Quell- und Zielelemente auswählen können.

Es gibt noch mehr...

Enquire.js hat noch mehr zu bieten! Sie können mehrere Handler pro Query und auch mehrere Queries registrieren, was Ihnen ultimative Flexibilität gibt! Weitere Informationen hierzu finden Sie auf der Projektseite von enquire.js.

Herunterladen, Forken und Beitragen!

Downloads und Quellcode finden Sie auf dem Projekt auf GitHub. Wenn Sie beitragen möchten, tun Sie dies bitte, ich würde mich über Meinungen, Gedanken und Ideen von anderen freuen. Forken Sie nach Herzenslust und machen Sie einen Pull-Request mit allen Änderungen. Wenn Sie auf Probleme stoßen, erstellen Sie gerne ein Issue auf GitHub und ich werde das Problem duly beheben :)

Lizenz

Das Projekt ist unter der MIT-Lizenz lizenziert, sodass Sie es nach Belieben verwenden können.