Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript overriding CSS display property after change of media query

Tags:

javascript

css

I have a table that I need to be visible on a Desktop and hidden on a mobile with the option of clicking a button to show it and another to hide it on the latter. It appears to work fine, but when I select Button2 to hide the table in minimised view on a desktop (to imitate a mobile view) and drag the browser to increase its size to desktop the table remains hidden unless I refresh the page.

Basically, the javascript function close_table() sets display:none which overrides the CSS display:block @min-width 481px.

Is there a way to ensure the table is visible when increasing the browser size (after button2 has been selected) without having to refresh?

Any tips/help would be appreciated.

Here's sample code below

HTML :

<button id="Button1" onclick="view_table()">View table</button>
<div id="table">
    <button id="Button2” onclick="close_table()">Hide table</button>
</div>

CSS :

@media (max-width:480px){
    #table {
        display: none;
    }
    #Button1 {
        display: block;
    }
}

@media (min-width:481px){
    #table {
        display: block;
    }
    #Button1 {
        display: none;
    }
}

JS :

function view_table() {
    document.getElementById("table").style.display="block"
}
function close_table() {
    document.getElementById("table").style.display="none"
}
like image 302
Carey Avatar asked Oct 30 '22 02:10

Carey


1 Answers

The issue is that when you say document.getElementById('table').styles.* you are directly setting styling on an element through the DOM which has a higher priority than the media queries do through CSS. This means that when the media queries are triggered again nothing will happen because the DOM elements now have a higher priority styling, so the MQ rules are ignored.

You also can't do the usual .hide .show classes because there isn't a way to add or remove classes just through media queries.

That pretty much leaves EventListeners that will listen for a window that's being resized and execute the functionality that you want.

I found this article and was able to use it to write this code snippet that completes the functionality that you were looking for.

JavaScript has access to window.matchMedia which is where all the media related items for a document are stored.In short, this allows us to directly work with media-query-like strings inside of our JavaScript instead of solely in our CSS.

Here are some additional resources about media queries that might be helpful to skim through as you are learning this.

For the code snippet, click full page to let you see what resizing the widow looks like.

Using Media Queries

Media Query types

MatchMedia()

/* Commented code on bottom is running. This is un-commented for easier readability.

'use strict'


if (matchMedia) { 
  const mq = window.matchMedia("(min-width: 481px)"); 
  mq.addListener(WidthChange); 
  WidthChange(mq); 
}

function WidthChange(mq) {
  if (mq.matches) {
    view_table() 
  } else {
    close_table()
  }
}

function view_table() {
  document.getElementById('table').style.visibility = 'visible'
  document.getElementById('button2').style.visibility = 'visible'
  document.getElementById('button1').style.visibility = 'hidden' 
}

function close_table() {
  document.getElementById('table').style.visibility = 'hidden'
  document.getElementById('button2').style.visibility = 'hidden'
  document.getElementById('button1').style.visibility = 'visible' 
}


*/

'use strict'


if (matchMedia) { // technically this is window.matchMedia, which is actually a function stored as a property on the window object. If the browser supports matchMedia then this is true. Else - no media queries regardless.

  const mq = window.matchMedia("(min-width: 481px)"); // The matchMedia() function is passed a media query string.

  mq.addListener(WidthChange);
  WidthChange(mq); // Immediately calls the new listener and pass in the mq object.
}

function WidthChange(mq) {
  // Equivalant to window.matchMedia("(min-width: 481px)").matches... .matches is a Boolean.
  if (mq.matches) {
    view_table() // If mq.matches is true ( meaning >= 481px)
  } else {
    close_table()
  }

}

function view_table() {
  document.getElementById('table').style.visibility = 'visible'
  document.getElementById('button2').style.visibility = 'visible'
  document.getElementById('button1').style.visibility = 'hidden' // You can also say display:none here on button1 to have the table move up into the spot where the button was for a cleaner look.
}

function close_table() {
  document.getElementById('table').style.visibility = 'hidden'
  document.getElementById('button2').style.visibility = 'hidden'
  document.getElementById('button1').style.visibility = 'visible' // If you do say display:none above, then this needs to beexactly what the original display property was.

}


// Note that this will update when the window go above or below the min-width.
// If you click the "view table" button  then make the window smaller
// it won't hide anything unless you went above the min-width then back down.
// This is because it's only triggered on a true or false change. If you want 
// it to be more reactive you can add more conditionals or check out MediaQueryList.change().
main {
  width: 100%;
}

table {
  width: 70%;
  border: 1px solid black;
  margin: auto;
}

.buttons {
  margin-top: 5px;
  margin-bottom: 5px;
  text-align: center;
}
<!DOCTYPE html>
<html>

<head>
  <link href="index.css" rel="stylesheet" type="text/css" />
</head>

<body>
  <main id="main">
    <div class="buttons">
      <button id="button1" onclick="view_table()">View table</button>
    </div>
    <div id="table">
      <table>
        <tr>
          <td>sample</td>
          <td>100</td>
          <td>10000</td>
        </tr>
        <tr>
          <td>sample</td>
          <td>100</td>
          <td>10000</td>
        </tr>
        <tr>
          <td>sample</td>
          <td>100</td>
          <td>10000</td>
        </tr>
      </table>
    </div>
    <div class="buttons">
      <button id="button2" onclick="close_table()">Hide table</button>
    </div>
  </main>
</body>
<script src="index.js "></script>

</html>
like image 156
Michael Treat Avatar answered Nov 15 '22 06:11

Michael Treat