Ashutosh Biswas
Ashutosh Biswas

Reputation: 117

JavaScript media query vs CSS media query

I've noticed that the JavaScript media query seems to take effect after the CSS equivalent ones.

I've created two examples demonstrating what I'm talking about:

First example

HTML:

<div class="foo">
  bar
</div>

CSS:

.foo {
  background-color: orange;
}


@media(max-width: 300px) {
  .foo {
    background-color: blue;
    transform: translateY(100px);
    transition: all 300ms ease-out;
  }
}

jsbin link is: here

Here transition happens, when screen width becomes 300px or less from something bigger.

But when creating responsive design such transition can be annoying. I'm trying to get rid of them. The following Javascript and CSS solves the problem, but I'm not sure that is it reliable or not.

2nd example

HTML

<div class="foo">
  bar
</div>
<button>toggle translateY to 200px</button>

CSS

.transition {
  transition: all 300ms ease-out;
}

.foo {
  background-color: orange;
}


@media(max-width: 300px) {
  .foo {
    background-color: blue;
    transform: translateY(100px);
  }
}

.translateY {
  transform: translateY(200px);
}

JavaScript:

const w = window.matchMedia("(max-width: 300px)");
const div = document.querySelector(".foo");
const button = document.querySelector('button');

function fun(e) {
  if (e.matches) {
     div.classList.add('transition');
  } else {
     div.classList.remove('transition');
  }
}

// for initial screen width change detection
fun(w);

w.addEventListener('change', fun);

button.onclick = function() {
  div.classList.toggle('translateY');
}

jsbin link is here

Here it seems the following thing happens in order when screen width becomes 300px or less from something bigger:

  1. CSS transform: translateY(100px) is rendered in a flash.
  2. transition class is added to div by JavaScript.

By clicking the button, it makes sure that the transition class is working.

This example doesn't cause any unwanted transition as screen size becomes 300px or less from something bigger.

So it seems that any CSS media query is rendered before JavaScript equivalent media queries. I think it's a good thing. But I'm not sure, is it the standard well supported behavior? Is it safe to build logic based on this behavior?

Upvotes: 1

Views: 1182

Answers (1)

Gabriele Petrioli
Gabriele Petrioli

Reputation: 196286

This is part of the CSS specificity

Inline styles added to an element (e.g., style="font-weight: bold;") always overwrite any styles in external stylesheets, and thus can be thought of as having the highest specificity.

The javascript code you posted will add inline styles (through the style property of the element) and thus has the highest specificity. (it has nothing to do with the js media query, it just has to do with how you apply the style in the JS to the element)


Update after the comments/update in question

Again it depends on when you load the CSS and the JS. If you first include the CSS file, since it is a render blocking resource, it will be applied first.

I am not sure though, why don't you apply all the rules through CSS media queries ?

const div = document.querySelector(".foo");
const button = document.querySelector('button');

button.onclick = function() {
  div.classList.toggle('translateY');
}
.foo {
  background-color: orange;
}

@media(max-width: 300px) {
  .foo {
    background-color: blue;
    transform: translateY(100px);
    transition: all 300ms ease-out;
  }
}

.translateY {
  transform: translateY(200px);
}
<div class="foo">
  bar
</div>
<button>toggle translateY to 200px</button>

Upvotes: 3

Related Questions