Skip to content
Advertisement

How to make JS media query work properly?

Media query in JS works, but as soon as it’s nested within a function such as onscroll or onclick, they’ll not work properly.

I’ll just put the code in here just in case you want to resize window easier: https://www.w3schools.com/code/tryit.asp?filename=GP7P1ENXH9JY

Try to test the media query if it works, I know it works, but as soon as you resize it to 768px(desktop) and started scrolling down, it starts to revert back to the tablet media query(600px) and the color changes too, even though the window size is still 768px width. How do I fix this?

window.onscroll = function() {stickynavbar();}

var element1 = document.getElementById("element1");
var element2 = document.getElementById("element2");
var myBtn = document.getElementsByTagName("button")[0];

var desktop = window.matchMedia("(min-width: 768px)");
var tablet = window.matchMedia("(min-width: 600px)");

function stickynavbar() {

  function element1Query(desktop){
      if (desktop.matches){
          element1.style.background = "darkred";
      }
      else{
          element1.style.background = "black";
      }
  }
  element1Query(desktop);
  desktop.addListener(element1Query);

  function element1TQuery(tablet){
      if (tablet.matches){
          element1.style.background = "darkblue";
      }
      else{
          element1.style.background = "black";
      }
  }
  element1TQuery(tablet);
  tablet.addListener(element1TQuery);

  function element2Query(desktop){
      if (desktop.matches){
          element2.style.background = "darkgreen";
      }
      else{
          element2.style.background = "gray";
      }
  }
  element2Query(desktop);
  desktop.addListener(element2Query);

  function element2TQuery(tablet){
      if (tablet.matches){
          element2.style.background = "yellow";
      }
      else{
          element2.style.background = "gray";
      }
  }

  element2TQuery(tablet);
  tablet.addListener(element2TQuery);
}
.element1{
        position: absolute;
        top: 0;
        left: 0;
        width: 50%;
        height: 1000px;
        background: black;
    }
    .element2{
        position: absolute;
        top: 0;
        right: 0;
        width: 50%;
        height: 1000px;
        background: gray;
    }
<!DOCTYPE html>
<html>
<body>

<div class="element1" id="element1"></div>
<div class="element2" id="element2"></div>
</body>
</html>

Advertisement

Answer

Here is another way to achieve it, the function only handles when the state matches, thus prevent the race condition

let element1 = document.getElementById("element1")
let desktop = window.matchMedia("(min-width: 768px)")
let tablet = window.matchMedia("(min-width: 600px) and (max-width:767px)")
let small = window.matchMedia("(max-width:599px)")

desktop.addEventListener('change', function(){
  if(desktop.matches)
    element1.style.background = "darkred";
})

tablet.addEventListener('change', function(){
  if(tablet.matches)
    element1.style.background = "darkblue";
})

small.addEventListener('change', function(){
  if(small.matches)
    element1.style.background = "black";
})
.element1 {
  position: absolute;
  top: 0;
  left: 0;
  width: 50%;
  height: 1000px;
  background: black;
}

.element2 {
  position: absolute;
  top: 0;
  right: 0;
  width: 50%;
  height: 1000px;
  background: gray;
}
<!DOCTYPE html>
<html>
<body>
  <div class="element1" id="element1"></div>
  <div class="element2" id="element2"></div>
</body>

</html>
1 People found this is helpful
Advertisement