Skip to content

Allt om WordPress, webbutveckling — och mer därtill

📱 JavaScript: hur du upptäcker skärmbredd, @media query-motsvarigheten i kod

📱 JavaScript: hur du upptäcker skärmbredd, @media query-motsvarigheten i kod

Ibland är layouten redan klar, CSS-media queries finns på plats, men du behöver upptäcka beteende vid en specifik brytpunkt direkt i JavaScript. Att visa en popup bara på mobila enheter, arrangera om ett rutnät vid storleksändring, trigga en animation när skärmen är "smal": allt detta kräver att skriptet förstår den aktuella fönsterbredden.

Problemet är att utvecklare ofta tar den svåra vägen: de läser av window.innerWidth, lägger på throttle för resize, jämför mot magiska siffror och hamnar i skör kod som lever separat från CSS-brytpunkterna. Ändå har webbläsare länge haft en metod som fungerar med samma media-uttryck som CSS.

Här är tre praktiska tillvägagångssätt: från moderna matchMedia (fungerar som @media i CSS) till en jQuery-variant för äldre projekt. Med live-exempel du kan kopiera och köra direkt.

💡 Snabb översikt:

  • matchMedia: en inbyggd metod som tar ett CSS-mediauttryck och rapporterar om det matchar just nu; idealisk för att synka JS-logik med CSS-brytpunkter
  • resize + matchMedia: en kombination som reagerar på förändringar i webbläsarfönstret; skriptet får veta när en brytpunkt passeras direkt, utan att periodiskt polla innerWidth
  • jQuery-variant: för projekt där jQuery redan finns på sidan; samma resize, men utan inbyggda matchMedia; jämförelsen görs via $(window).width()

MatchMedia: den enda sanningskällan för skärmbredd

Den största nackdelen med window.innerWidth är att den inte vet något om dina CSS-brytpunkter. Du sätter 768px i media queries, skriver sedan if (window.innerWidth < 768) i JS, och till slut förstör avrundning eller rullningslisten synkroniseringen.

window.matchMedia() löser detta problem radikalt: den tar emot samma mediauttryckssträng som CSS-regeln @media. Resultatet är ett MediaQueryList-objekt med en .matches-egenskap (true / false). Inga magiska siffror, ingen mismatch med layouten.

Grundläggande syntax:

1const mq = window.matchMedia("(min-width: 768px)");
2
3if (mq.matches) {
4 console.log("Tablet or wider — 768px+");
5} else {
6 console.log("Mobile resolution — less than 768px");
7}

Samma anrop matchMedia("(min-width: 768px)") utvärderas av webbläsaren med samma regler som @media (min-width: 768px) i CSS. Om sidopanelen döljs vid denna brytpunkt i CSS, "ser" JS samma sak och kan till exempel dölja mobilmenyn.

Förutom .matches ger MediaQueryList-objektet en .media-egenskap (den ursprungliga frågesträngen) och en addEventListener-metod för att prenumerera på ändringar. Det betyder att när du väl deklarerar en brytpunkt i en konfig kan du använda den i både CSS och JS utan att duplicera magiska siffror: extrahera bara 768 till en konstant och stoppa in den på båda ställena.

Reagera på resize utan throttle och workarounds

Att kolla "just nu" är bara halva jobbet. Den verkliga magin börjar när skriptet får veta att en brytpunkt passeras i samma ögonblick som fönstret ändras.

MediaQueryList har en change-händelse som triggas exakt när .matches-värdet växlar. Inte vid varje pixel av resize, utan bara när gränsen passeras:

1const mq = window.matchMedia("(min-width: 500px)");
2
3mq.addEventListener("change", function (e) {
4 if (e.matches) {
5 console.log("Screen expanded to 500px or more");
6 } else {
7 console.log("Screen narrowed to less than 500px");
8 }
9});

För bakåtkompatibilitet med äldre webbläsare kan du uppnå samma resultat genom en allmän resize-hanterare på window:

1window.addEventListener("resize", function () {
2 if (window.matchMedia("(min-width: 500px)").matches) {
3 console.log("Screen width — at least 500px");
4 } else {
5 console.log("Less than 500px");
6 }
7});
Webbläsarkonsol som visar skärmbreddsmeddelanden vid storleksändring

Skillnaden är enkel: changeMediaQueryList är en händelsedriven approach (inga extra anrop under resize inom ett intervall), medan resizewindow är en fallback som alla utvecklare känner till.

Breddintervall: mellan två brytpunkter

En vanlig uppgift är "från 769px till 1024px". matchMedia fungerar som CSS även här: kombinera min-width och max-width i ett enda uttryck:

1window.addEventListener("resize", function () {
2 if (
3 window.matchMedia("(min-width: 769px)").matches &&
4 window.matchMedia("(max-width: 1024px)").matches
5 ) {
6 console.log("Tablet range: 769px – 1024px");
7 } else {
8 console.log("Outside the tablet range");
9 }
10});

Eller som ett enda uttryck (webbläsare förstår sammansatta media queries precis som i CSS):

1const tablet = window.matchMedia("(min-width: 769px) and (max-width: 1024px)");
2
3tablet.addEventListener("change", function (e) {
4 console.log(e.matches ? "Entered tablet range" : "Left tablet range");
5});

Vilken variant ska man välja? changeMediaQueryList när du behöver fånga det exakta ögonblicket då gränsen passeras (till exempel för att strukturera om DOM-trädet). resize + matchMedia när logiken är enklare och du bara behöver "kolla nu" utan att prenumerera på framtida övergångar.

JQuery-variant: när matchMedia inte är tillgänglig

Om projektet använder jQuery och polyfills inte är ett alternativ uppnås samma resultat genom att jämföra $(window).width() med ett tröskelvärde:

1jQuery(document).ready(function ($) {
2 if ($(window).width() > 1000) {
3 console.log("Screen width greater than 1000px");
4 } else {
5 console.log("Screen width 1000px or less");
6 }
7});

Denna kod körs en gång vid sidladdning. För att spåra resize, linda in kontrollen i en hanterare:

1jQuery(document).ready(function ($) {
2 function checkWidth() {
3 if ($(window).width() > 1000) {
4 console.log("Width > 1000px");
5 } else {
6 console.log("Width ≤ 1000px");
7 }
8 }
9
10 checkWidth(); // initial run
11 $(window).on("resize", checkWidth);
12});

Men kom ihåg: $(window).width() och matchMedia kan skilja sig med några pixlar på grund av rullningslisten. matchMedia arbetar med viewporten, precis som CSS-regler. Därför rekommenderar jag den inbyggda metoden för all ny kod.

MatchMedia vs innerWidth: en kort jämförelse

Kriterium

matchMedia

innerWidth

Synkronisering med CSS

Fullständig (samma uttryck)

Manuell sifferjustering

Händelse vid brytpunkts-passering

changeMediaQueryList

Endast resizewindow

Hantering av rullningslist

Samma som CSS (viewport)

Webbläsarberoende

Mörkt tema / prefers-reduced-motion-detektion

Ja (vilket mediauttryck som helst)

Nej

⁉️🤔 Vanliga frågor

Vilken är bättre: matchMedia eller window.innerWidth?

matchMedia är alltid bättre när logiken är knuten till CSS-brytpunkter. Den använder samma regler som @media, vilket eliminerar avvikelser på en pixel eller två på grund av rullningslist eller zoom. innerWidth är bara lämpligt när du behöver det exakta numeriska värdet (till exempel för att beräkna hur många element som får plats), inte faktumet "skärm bredare än N pixlar".

Fungerar matchMedia i äldre webbläsare?

Ja, stödet är brett: alla moderna webbläsare inklusive mobila, samt Internet Explorer 10+. IE9 och äldre är lämnade bakom; för dem måste du använda window.innerWidth eller jQuery-varianten från denna artikel. I praktiken närmar sig andelen IE9 år 2026 noll.

Kan matchMedia kontrollera mer än bara bredd?

Ja, metoden accepterar vilket giltigt CSS-mediauttryck som helst. Till exempel: (orientation: portrait) för enhetsorientering; (prefers-color-scheme: dark) för mörkt tema i operativsystemet; (prefers-reduced-motion: reduce) för en begäran om att inaktivera animationer. Det fungerar precis som i CSS: window.matchMedia("(prefers-color-scheme: dark)").matches returnerar true om användaren har mörkt tema aktiverat.

Behöver jag ta bort change-hanteraren när jag lämnar sidan?

I modern kod, nej. Webbläsaren rensar minnet automatiskt vid sidavladdning. I SPA:er (React, Vue), där en komponent monteras och avmonteras utan sidomladdning, måste du spara en referens till hanteraren och ta bort den via removeEventListener i componentWillUnmount / onUnmounted; annars får du minnesläckor och upprepade triggers på "döda" komponenter.

Varför visar $(window).width() och matchMedia ibland olika bredder?

För att de mäter olika saker. matchMedia arbetar med viewport-bredden (CSS-visningsytan), samma som media queries använder. $(window).width() / window.innerWidth inkluderar bredden på den vertikala rullningslisten, om den finns. Skillnaden är vanligtvis 15-17 px, exakt rullningslistens bredd. Därav regeln: om du knyter logik till CSS-brytpunkter, använd matchMedia; om du behöver den "sanna" fönsterbredden i pixlar, använd innerWidth.

Så vad ska man använda: den slutliga slutsatsen

För ny kod är svaret tydligt: window.matchMedia(). Den lever i samma kontrakt som din CSS, kräver ingen manuell sifferjustering för varje brytpunkt och tillhandahåller en händelsemodell av typen "den växlade, du vet" istället för konstant breddpollning.

Ett typiskt scenario där skillnaden märks direkt: du bygger ett produktkort som visar ett galleri med fyra bilder på desktop, men en svepbar enkel bild på mobil. I CSS har du @media (max-width: 768px) som ändrar layouten. I JS, istället för if (window.innerWidth <= 768) skriver du matchMedia("(max-width: 768px)"), och webbläsaren garanterar att JS-villkoret triggas exakt när layouten ändras. Inget "nästan fungerade", inga buggar vid 767px på grund av rullningslisten.

Lämna jQuery-approachen med $(window).width() för underhåll av gamla projekt: den fungerar, men tvingar dig att duplicera brytpunkter i koden och avviker tyst från CSS med rullningslistens bredd.

Och om du vill se allt som beskrivits ovan i praktiken, här är en 10-minuters tutorial där matchMedia förklaras från anrop till händelsemodell:

Testa att ersätta närmaste if (innerWidth < 768) med matchMedia("(min-width: 768px)"), så kommer du omedelbart att känna hur mycket renare koden blir.