Removing an element on resize doesn't work (but adding does)

Which code are you referring to?

The first code you added is just a once only code because you missed out the event listener. It would only add the new element if you were already at the smaller width and only on load.

The adjusted snippet I gave you above added the event listener so the element is added when the media query breakpoint is activated.

However you have not yet added the code to remove the element so all you get is an element added each time you return to the smaller screen

I gave you a working demo in the codepen showing the how to add and also remove the element. I assumed you had left it out on purpose just for testing :slight_smile:

If you want the new box only on the large screen then just reverse the if/else code. Iā€™ve adjusted the codepen to show this:

1 Like

If you are adding to the Sitepoint page then I guess you need it like thi:

const mqls = window.matchMedia("(max-width: 850px)");
const hostElement = document.querySelector(".header-module--nav--7IzCJ");
const parasiteElement = `
    <div class="phoneNumberBox" dir="ltr" style="text-align: center; background: red;">
        <h2>Call me:</h2>
        <a tel:X>+1 012-3456780</a>
    </div>
`;

function mediaqueryresponse(mql) {
  if (mqls.matches) {
    // {max-width: 850px} query matched
        var contactInfo = document.querySelector('.phoneNumberBox');
     if (contactInfo !== null) contactInfo.remove()
  } else {
     hostElement.insertAdjacentHTML("beforeend", parasiteElement);
  }
}
mediaqueryresponse(mqls);
// attach listener function to listen in on state changes
mqls.addEventListener("change", mediaqueryresponse);

Small Screen:
Screen Shot 2022-02-07 at 20.41.49

Large Screen:

1 Like

@PaulOB

I meant to to the code in post #21 (with changing max-width to min-width).

There is one flaw here. You pass in mqls to mediaqueryresponse on the initial call which is good.

mediaqueryresponse(mqls);

However you then donā€™t use it (Note mql and mqls)

function mediaqueryresponse(mql) {
  if (mqls.matches) {

Instead referring to the mqls outside of the function. Changing your function parameter from mql to mqls should fix that. It then keeps matches nicely contained inside of the function,

You could (if you like) also make use of an early return to get rid of the need for that else statement. Note I have gone for an easier to read and remember ā€˜mediaQueryListā€™ parameter here

function mediaqueryresponse(mediaQueryList) {
    if (mediaQueryList.matches) {
        const contactInfo = document.querySelector('.phoneNumberBox')

        if (contactInfo !== null) contactInfo.remove()
        return // exit here
    }
    // we didn't exit? Not a match then!
    hostElement.insertAdjacentHTML("afterend", parasiteElement)
}

Note: I havenā€™t tested this. Just a look at your code.

1 Like

@bendqh1 you will need to open the console at the bottom. Note how many times the resize event fires compared to matchmedia. matchmedia is more efficient and frees up the event loop to handle other things.

I checked for such event notifications on both Google Chrome console and Microsoft Edge console (in the end) but didnā€™t find any; I only find warnings and/or errors there.

Anyway, I understand that idea about software performance.
But isnā€™t something like mqls.addEventListener("change", mediaqueryresponse); on each webpage in a large website also a problem?

Itā€™s a good question, I donā€™t know is the answer.

I prefer the mediaQueryList, but you can alleviate the issue with the resize eventListener by using debounce.

You can see the same codepen I did, but this time with debounce. For convenience I have used lodash.

window.addEventListener('resize', _.debounce(resizeHandler, 300))

codepen here

1 Like

The problem I see (with my limited js knowledge) is that you donā€™t get the change at exactly the right point and it makes it feel laggy compared to the matchMedia version.

e.g.

You can see the red appears exactly when it should with the matchMedia routine but the debounced resize (blue background) you have to wait until the debounce has finished. It makes it look laggy just for a color change but imagine if this was a layout change and then the layout could possibly be broken until the debounce has finished because the screen may have been resized quite a bit smaller during that time.

I doubt there is any noticeable impact compared to using the resize event which is known resource hog.

@PaulOB

I would go with matchMedia, hands down. In fact I will be amending a responsive menu I wrote previously with matchMedia.

I was just giving an example. A better use for debounce would be say for instance a search box, where you donā€™t want the database being thrashed on every key press, but rather on the completion of typing a word.

I concurr :slight_smile:

1 Like

Yes, sorry I didnā€™t mean to infer that you meant it as a better alternative :slight_smile:

Yes that makes sense :slight_smile:

1 Like

For possible future readers, this thread somewhat continued here and here:

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.