Responsive design problem - showing hiding with media query

I’m posting this in the CSS forum, but I’m actually not sure if that’s right. It might be CSS, or CSS and HTML, or javascript, no idea.

I’m working on a responsive design, and the media queries work great. I can change styles and layout as needed.
But now I’m trying to make the top menu bar become a button for mobile screens, and use javascript to toggle the div with the menu options between hidden and visible.
Works fine also.

The problem is when resizing the window.

  1. As long as I don’t click the button, when I go from “big” to “small” the menu bar disappears and the button appears, and when I go from “small” to “big” the button disappears and the menubar appears. Fine.
  2. As long as I stay “small” and click the button, the menu bar appears/disappears. Perfect.
  3. But when I’m “small” and start clicking the button, and then resize the window back to “big”, if the menu bar is hidden, it doesn’t reappear! Oops.

It seems like changing the display style with javascript messes up the changing of display style with media queries.

I’ve searched, but didn’t find any working solutions. This stuff (JS) seems to work only in FF.

Is there a CSS solution? Or do I have to move the question to the JS forum?

Here is the code:


<div class="navbar">
		
  <a class="brand" href="#">
    <img src="img/logo.png" />
  </a>

  <a class="btn btn-navbar" href="javascript:togglediv('navigation');">
    <span class="icon-bar"></span>
    <span class="icon-bar"></span>
    <span class="icon-bar"></span>
  </a>
		
  <div id="navigation" class="nav-collapse collapse">
    <ul class="nav-list">
      <li><a href="#home">Home</a></li>
      <li><a href="#about">About</a></li>
      <li><a href="#updates">Updates</a></li>
      <li><a href="#screenshots">Screenshots</a></li>
      <li><a href="#contact">Contact</a></li>
    </ul>
  </div>
		
  <div class="clear"></div>
</div>

main css

.navbar .btn-navbar {
  display:none;
}

media query

@media screen and (max-width: 700px) {

.navbar .btn-navbar {
  display:inherit!important;
}

.navbar .nav-collapse {
  display:none;
}

}

  function togglediv(divname) {
    var mydiv = document.getElementById(divname);
    if(mydiv.style.display == "block") {
      mydiv.style.display = "none";
    } else {
      mydiv.style.display = "block";
    }
  }

Hi,

The js writes an inline style into the element (style=“display:block” or style=“display:none”) which means that your css will be over-ridden.

You could instead add a class to the element with js to determine the state.

e.g.


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Untitled Document</title>
<style>
.navbar .btn-navbar { display:none; }
.nav-off{display:block!important}

@media screen and (max-width: 700px) {
.navbar .btn-navbar {display:block;}
.navbar .nav-collapse { display:none; }
.nav-off{display:none!important}
}
</style>
</head>


<body>
<div class="navbar"> <a class="brand" href="#"> <img src="img/logo.png" /> </a> <a class="btn btn-navbar" href="javascript:togglediv('navigation');">hello <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </a>
		<div id="navigation" class="nav-collapse" >
				<ul class="nav-list">
						<li><a href="#home">Home</a></li>
						<li><a href="#about">About</a></li>
						<li><a href="#updates">Updates</a></li>
						<li><a href="#screenshots">Screenshots</a></li>
						<li><a href="#contact">Contact</a></li>
				</ul>
		</div>
</div>
<script type="text/javascript">
  function togglediv(divname) {
    var mydiv = document.getElementById(divname);   
    if(mydiv.style.display == "block") {
      mydiv.style.display = "none";
						mydiv.className+=" nav-off";
    } else {
      mydiv.className=mydiv.className.replace(new RegExp(" nav-off\\\\b"), "");
						mydiv.style.display = "block";
    }
  }	
	
</script>
</body>
</html>


Does that do what you wanted?

Thanks a lot Paul. I had to tweak it a bit, but your explanation pointed me in the right direction, and I got it to work.

Just keep your sanity by realising that, unless by large and small you are getting hit by phones or tablets changing orientation, most small devices won’t start getting larger to trigger the problem (except for web developers, who like squishing and growing responsive pages for testing etc).

I know.
But if for some reason someone squishes his browser window for a moment, and then when he re-expands it the menu doesn’t show up anymore, that would be bad publicity :smiley:
It just has to work. And now it does.

Off Topic:

It would be interesting to see your solution, if it can be reduced to a simple example.

Of course :slight_smile:

    
<div class="navbar">
		
  <a class="brand" href="#">
    <img src="img/logo.png" />
  </a>

  <a class="btn btn-navbar" href="javascript:togglediv('navigation');">
    <span class="icon-bar"></span>
    <span class="icon-bar"></span>
    <span class="icon-bar"></span>
  </a>
		
  <div id="navigation" class="nav-collapse">
    <ul class="nav-list">
      <li><a href="#home">Home</a></li>
      <li><a href="#about">About</a></li>
      <li><a href="#updates">Updates</a></li>
      <li><a href="#screenshots">Screenshots</a></li>
      <li><a href="#contact">Contact</a></li>
    </ul>
  </div>
		
  <div class="clear"></div>
</div>

main CSS


.navbar .btn-navbar {
	display:none;
}

media query


@media screen and (max-width: 700px) {

.navbar .btn-navbar {
  display:inherit!important;
}

.navbar .nav-collapse {
  display:none;
}

.nav-on {
  display:block!important;
}

}

javascript


  function togglediv(divname) {
    var mydiv = document.getElementById(divname);   
    var pattern = new RegExp("(^| )" + 'nav-on' + "( |$)");
    if(pattern.test(mydiv.className)) {
      mydiv.className=mydiv.className.replace(new RegExp(" nav-on\\\\b"), "");
    } else {
      mydiv.className+=" nav-on";
    }
  }

Since without hitting this toggle button, the whole ul remains unavailable to screen readers and other AT, I would put some text in that anchor stating what it does (“toggle menu” or similar) to make this whole setup work a little better.
Some tweets from Marco Zehe (Mozilla a11y developer):
Anchors
nowadays
suck

And Twitter Bootstrap not only encourages bad code (the examples on the http://twitter.github.com/bootstrap/ site) but seems to even be going out of its way to make sure stuff is broken and inaccessible by default (when I used Bootstrap, I rewrote large parts of it to make it actually work with keyboard and give clickable areas access points and actual text… le sigh).

I actually don’t mind the display: none/block setup for large menus (instead of the usual pulling offscreen or clipping), since when it’s display: none you can very easily skip over it, especially nice when sighted and using the keyboard, but then the CSS can’t be display: none by default (if the JS breaks or isn’t there, stuff’s not available by default), and the toggle has to work everywhere for everyone.

So for example for a dropdown I made it display normally by default, and had JS add in the class with the display: none styles and also add in the anchor (no point in having an anchor who does nothing, unless there’s already Javascript working).

Thanks, Guido … and interesting followup, poes. :slight_smile:

Loved this: https://twitter.com/JoelSutherland/status/269141335397789696

Pugh … I always drag from the bottom right corner. :nono:

lol - It’s easy to make it responsive when there’s no content in the page :slight_smile:

low-content pages ftw