Media Query conflicts with $(window).resize() - javascript

I've got a left nav div that hides via media query at < 768 and a filter button that displays at < 768. When you click the filter button it uses JQuery to toggle the display of the left nav via show()/hide(). When the window is resized >= 768 I use JQuery to set the display of the left nav back to show.
As I said, my media query handles hiding the left nav when the window width goes below 768, but the problem is it only fires if I have not clicked the filter button. Once I size it under 768 and then click the filter button to turn it on and then click it again to turn it off and then size up over 768 and then back down the left nav is still there. It's like the media query no longer works for the display:none attribute. There are other css properties I change in the media query like width and color and those still work, but it's no longer hiding the div.
I've simplified the code to illustrates the problem.
HTML
Button
<div id="navLeft">NavLeft</div>
CSS
#navLeft {
background-color:orange;
}
#filterButton {
background-color:silver;
display: none;
}
#media only screen and (max-width: 300px) {
#navLeft {
display: none;
}
#filterButton {
display: inline;
}
}
JS
$(window).resize(function()
{
var $theWindowSize = $(this).width();
if($theWindowSize > 300)
{
$('#navLeft').show();
}
});
// Filters
$('#filterButton').bind('click',function(event)
{
event.preventDefault();
if ($('#filterButton').hasClass('filtersActive'))
{
$('#navLeft').hide();
$('#filterButton').removeClass('filtersActive');
}
else
{
$('#navLeft').show();
$('#filterButton').addClass('filtersActive');
}
});
Here's the fiddle. To replicate the behavior follow the steps below.
https://jsfiddle.net/athcy8fL/
1) Resize the width of the Result viewport several times under and above 300px before clicking anything and you'll see everything works as planned. Under 300px the button comes on and the NavLeft div hides. Over 300px and the Button hides and the NavLeft shows
2) Size the Result viewport below 300px and click the Button link. The NavLeft div should appear. Good.
3) Size the Result viewport above 300px and the Button hides. Good.
4) Size the Result viewport below 300px, the NavLeft should hide but it does not. Not Good.
Why doesn't the media query work after using Javascript to alter its display property?

The problem is that when you call .show() in an element that is not already visible, jquery will add an inline style to show the element and override your css, causing the media-query not to work.
I modified your code a little bit to take the inline-style priority into account
http://jsfiddle.net/yjs3fou7/
basically I changed the resize function:
$(window).resize(function()
{
var $theWindowSize = $(this).width();
if($theWindowSize > 300)
{
$('#navLeft').show();
$('#filterButton').removeClass('filtersActive')
} else {
if (!$('#filterButton').hasClass('filtersActive'))
$('#navLeft').hide();
}
});
inline styles have more priority than id or class styles according to css specificity rules so once you start manipulating things from javascript you must remember it may cause your css to stop being applied

The problem is the use of inline styles which has more specificity than the css rules.
$(window).resize(function() {
var $theWindowSize = $(this).width();
if ($theWindowSize > 300) {
$('#navLeft').removeClass('show');
$('#filterButton').removeClass('filtersActive');
}
});
// Filters
$('#filterButton').bind('click', function(event) {
event.preventDefault();
$('#filterButton').toggleClass('filtersActive');
$('#navLeft').toggleClass('show', $('#filterButton').hasClass('filtersActive'));
});
#navLeft {
background-color: orange;
}
#filterButton {
background-color: silver;
display: none;
}
#media only screen and (max-width: 300px) {
#navLeft {
display: none;
}
#filterButton {
display: inline;
}
#navLeft.show {
display: block;
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
Button
<div id="navLeft">NavLeft</div>
Demo: Fiddle

Related

Change display property and id attribute

I have 2 sections:
<section class="notes animate" id="need" style="background:#fff; height:900px; padding-top:70px;">
<!--stuff --->
</section>
<section class="focus" id="need" style="display:none;">
<!--stuff --->
</section>
I want to display the second section when window is lowered to width less than 1043px. And hide the first section by display:none
Update:
How can I remove id attribute of first section, when width is less than 1043?
You should use CSS media queries. You can read more about it here: http://www.w3schools.com/css/css_rwd_mediaqueries.asp
For example:
#media only screen and (max-width: 1043px) {
section.focus {
display: block;
}
}
Firstly you cannot use same ID for more than one div. So change the id of one div.
And to hide the second div and show the first div:
Use CSS:
#media only screen and (max-width: 1043px) {
.focus {
display: block;
}
.notes {
display: none;
}
}
In response to your requirement for removing the ID attribute, try the following JavaScript. It can only do it once however, and if you are interested in performance you should consider investigating debounce/throttle for the resize handler. (http://benalman.com/code/projects/jquery-throttle-debounce/examples/debounce/)
$(window).on('resize', function() {
if($(window).width() < 1043) {
$('.notes').removeAttr('id');
$(window).off('resize');
}
});
However, the media queries answers are the correct approach to show/hide based on screen width.

Click handler interferes with CSS hover state

On large screens, I want dropdowns to appear on hover, but on mobile I want to arrange them like accordions.
My jQuery is conflicting with my CSS. On mobile, clicking the li creates all kinds of problems: the event fires over and over, and if I resize to larger viewport, the dropdown remains open and the :focus and :hover rules are disabled.
Sass
// If bigger screen, show the submenu on hover or focus
ul.sub {
display: none;
}
body.desktop {
li.dropdown:hover,
li.dropdown:focus {
> ul.sub {
dispay: block;
}
}
}
JavaScript
if ($('body.desktop').length < 1) {
$('li.dropdown > a').on('click', function(e){
$(this).parent().find('.dropdown-menu').slideToggle('fast');
e.preventDefault();
});
} else {
return false;
}
The problem was the style="display:none;" rule applied by the .slideToggle() method. I needed to devise a way to override this on larger viewports.
JavaScript
$(window).resize(function(){
if (window.innerWidth > 795 ) {
$('.dropdown-menu').removeAttr('style');
}
});
Then, to stop the event from firing again and again, hat-tip to this solution:
$("li.dropdown").unbind().click(function() { ... });

how to disable mouseout visibility="hidden" effect for medias smaller than 768px?

I am pretty new at Javascript. I created this effect where text appears under an image icon when the user hovers over it. I would like the effect to only work when the screen is over 768px and for the text to just stay visible at all times when viewed on smaller devices. I've tried using different variants of
if (screen.width < 768px) {}
and
#media all and (min-width: 768px) {} else {}
to control the effect to my liking but without any luck. Help???
Here is my code:
<section id="s1">
<h1><a href="web/services.html">
<img src="images/ICON-TRANSCRIPTION.png" class="hover"></a></h1>
<p class="text">TRANSCRIPTION</p>
</section>
<script>
$('.hover').mouseover(function() {
$('.text').css("visibility","visible");
});
$('.hover').mouseout(function() {
$('.text').css("visibility","hidden");});
</script>
You do not need any JS to do this. The easiest way to accomplish this is to define the media query to be what you desire, set the element to visibility: hidden; and then add a hover rule to change the visibility attribute.
The visibility would be visible by default (on smaller screens), then set to hidden by the media query with the added hover functionality for larger screens.
#media all and (min-width: 768px) {
.hover { visibility: hidden; }
.hover:hover { visibility: visible; }
}
If you must do it via JS(this can be accomplished with CSS media queries), first you should get the width of the window and set it as a variable, then you can set up your conditional statement like so:
function mouseVisibility() {
var w = $(window).width();
if (w > 767) {
$('.hover').mouseover(function() {
$('.text').css("visibility","visible");
});
$('.hover').mouseout(function() {
$('.text').css("visibility","hidden");});
}
}
mouseVisibility();
Additionally, you should fire the function again if the user resizes the browser window:
$(window).resize(function() {
mouseVisibility();
});

Javascript override of media query

I'm creating a responsive site. I have a media query set up so that when the screen width drops below 768 px a class (lets call it "hiddenClass") is hidden. Then I implement Javascript to toggle this class into view on a button click. The problem I'm running into is that javascript seems to override the media query. So if I shrink the screen below 768px the "hiddenClass" disappears....then I click the button which displays the "hiddenClass".....then click the button once more to hide it on the smaller device again.....now I expand the window and the "hiddenClass" stays hidden even after it gets to the 768px. If I take out the javascript and shrink the window the "hiddenClass" performs like it should...which tells me javascript is overriding it.
Is there a CSS fix to this? I know I could always check for a window resize event in javascript to display the hiddenClass after it reaches 768px. Was just wondering if this can be handled with CSS....or if javascript is the way to fix it.
Update JSfiddle with JS commented out so you can see how it should work...then add in the JS to see the issue described above. The button is the 'menu' navigation element when you shrink the screen down and "hiddenClass" would be the "menu" class in the li's:
http://jsfiddle.net/or5vy17L/1/
HTML:
<ul>
<li class="menuButton">- Menu -</li>
<a href="index.html">
<li class="menu" >
Home
</li>
</a>
<a href="instagram.html">
<li class="menu" >
Instagram
</li>
</a>
<li class="menu">Clients</li>
<li class="menu">Nutrition</li>
<li class="menu">About Me</li>
<li class="menu">Contact</li>
</ul>
css:
li {
display:inline;
color:$font-color--nav;
cursor:pointer;
font-size:1.5em;
padding: .7em .7em .7em .7em;
//for space between margins
margin-right:-4px;
border-radius:.5em;
}
ul {
text-align:center;
}
.menuButton {
display:none;
}
#media (max-width:768px) {
ul {
padding:0px;
}
li {
display:list-item;
border:1px solid white;
padding:.2em .2em .2em .2em;
border-radius:0px;
}
.menu {
display:none;
}
.menuButton {
display:list-item;
}
}
javascript:
/****
$('ul').on('click', '.menuButton', function() {
$('.menu').slideToggle();
});
****/
The .hiddenclass is staying hidden because it is a inline style, and inline styles override nearly all other styles. You have two options, one is to override the inline style with a CSS, as described in this CSS Tricks post:
<div style="background: red;">
The inline styles for this div should make it red.
</div>
div[style] {
background: yellow !important;
}
JSFiddle Demo
According to this article, this CSS solution works in:
Internet Explorer 8.0
Mozilla Firefox 2 and 3
Opera 9
Apple Safari, and
Google Chrome
Or, use JS or JQuery to remove the inline style when the screen is resized:
$(window).resize(function(){
if($(this).width() >= 768){
$('.hiddenclass').show();
}
else{
$('.hiddenclass').hide();
}
});
JSFiddle Demo
I seem to have come across this issue myself and following the advice here, I've come up with this solution:
window.onresize = function() {
var menu = document.getElementById('nav').getElementsByTagName('ul')[0];
if(window.innerWidth >= 1024) menu.style.display = '';
};
function toggleMenu() {
var menu = document.getElementById('nav').getElementsByTagName('ul')[0];
var link = document.getElementById('nav').getElementsByTagName('a')[0];
if(menu.style.display == 'block') {
menu.style.display = 'none';
link.innerHTML = '▼';
}else{
menu.style.display = 'block';
link.innerHTML = '▲';
}
}
Explanation:
The toggleMenu() function controls the display/hiding of the menu, and the issue presented itself after resizing the window from < 1024px (drop-down style menu) to > 1024px, my normal "desktop" menu disappeared completely. Given that JavaScript inserts styles inline (i.e. as a element attribute, ) then on a resize of 1024 or higher, this inline style should be gone.
Problem fixed.

On Hover sublist to drop down without extending the height of the div

please guide me as i'm trying to learn.
1) I am trying to make this list to expand when it hover. It work on my browser but not on jsfiddle. But problem is it wont stop expand and shrink when I move my mouse over it several time.
2) How do I make the list by the time it expand, my div will got grow longer, everything stay inside the div. I have try overflow:hidden but it doesn't work.
3) The hover that I try to make in CSS was to only change the font color of the main name but it change color of the whole name.
my JFiddle http://jsfiddle.net/Y3tc6/1/
THE JQUERY
$(".subli").hide();
$(".mainli").on("click", function (e) {
e.preventDefault();
$(this).find(".subli").slideToggle();
});
Thank You
Try this:
$(".mainli").on("mouseover", function (e) {
$(this).find(".subli").slideDown();
});
$(".mainli").on("mouseout", function (e) {
$(this).find(".subli").slideUp();
});
You will have to make some css changes. But i think this will help you with your slide down and slide up
2) How do I make the list by the time it expand, my div will got grow longer, everything stay inside the div. I have try overflow:hidden but it doesn't work.
#droplist {
display:block;
max-height:212px;
width:250px;
background-color:grey;
overflow:auto;
}
3) The hover that I try to make in CSS was to only change the font color of the main name but it change color of the whole name.
#droplist > ul > li:hover {
color:red;
}
#droplist li ul {
color:#000;
}
JSFiddle http://jsfiddle.net/Y3tc6/4/
For more information of > on CSS.
CSS '>' selector; what is it?
Sorry if it's messy, on the 3rd number.
My last edit! XD
1) Use mouseenter and mouseleave
$(".subli").hide();
$(".mainli").mouseenter(function (e) {
$(this).find(".subli").slideDown();
});
$(".mainli").mouseleave(function (e) {
$(this).find(".subli").slideUp();
});
2 & 3) You need to be more specific in you CSS to get the colors right, and use block, max-height and overflow to make the height of the div constant
#droplist {
display:block;
max-height:250px;
height:250px;
width:250px;
background-color:grey;
overflow: hidden;
}
#droplist .mainli:hover li {
color:initial;
}
#droplist .mainli:hover,
#droplist .mainli li:hover {
color:red;
}
Working demo
Try this:
$(".subli").hide();
$(".mainli").hover( function (e) {
e.preventDefault();
$(this).find(".subli").stop(true).slideToggle();
}
);

Categories