I am attempting to use an accordion slidetoggle nav when the screen width is less than 1200px and then want to disable/remove the slidetoggle functionality when it is greater than 1200px wide.
The problem: When I load the page in Desktop width, all is well because I'm not triggering the slideToggle until screen width is "mobile" sized... <1200px.
If I then resize the screen to mobile, my toggled divs are already visible without even clicking on them. If I resize to Desktop width all is well - the toggle divs have disappeared. If I again resize to mobile and then click on the primary link to toggle the divs and leave one toggled open and then resize to Desktop, my content is invisible, but the nav links are out of alignment. When I look at the css I see that there is an inline css display:block for the toggled div.
Despite my many attempts to override that inline style (.css, .removeClass, .addClass, .attr, etc.) that damn line of code persists.
UPDATE: I wrote an IF statement to check whether the toggled div is display:block whenever there is a screen resize and it is greater than 1200px wide. This test comes back false every time, but I can see the inline css for the element: display:block. How can this happen? Here is the code for the test. Also see images.
if ( $('mobile-child-nav-links').css('display') == 'block') {
console.log("tested true");
$('mobile-child-nav-links').css('display', 'none');
} else {
console.log("tested false");
}
Dev Tools showing that the element has inline style set to display:block
Dev Tools console showing my if statement is not detecting display:block when it is clearly there
What is the deal? Please see code below:
<script>
// Responsive accordian menu jquery
$( document ).ready(function() {
var win = $(this); //this = window
var currentScreenWidth;
var mobileLinksDiv = $('mobile-child-nav-links');
var mobileLinksDivs = $('mobile-child-nav-link');
function getScreenWidth() {
return currentScreenWidth = $(window).width();
}
function enableMobileNav() {
// toggle on click of primary nav link
$('.primary-nav-link').off('click').on('click', function(e) { // prevents multiple click events from screen resizes
e.preventDefault();
$('.primary-nav-link').addClass('mobile-active-primary-link');
// locate the next sub menu div containing sub nav links and toggle it into view
var subNavContainer = $(this).nextAll('.mobile-child-nav-links').eq(0).toggle();
});
}
function disableMobileNav() {
$('.mobile-child-nav-links').addClass('hideEls');
$('.primary-nav-link').removeClass('mobile-active-primary-link');
$('.primary-nav-link').off('click'); // remove click binding to avoid multiple .click events at once
$('mobile-child-nav-links').hide(); // ensure that sub nav div and links are hidden
}
// Checking page width on initial page load
if (getScreenWidth() >= 1200) {
// do nothing
} else {
enableMobileNav();
}
// Screen resizing triggers this function
$(window).on('resize', function(e){
currentScreenWidth = $(window).width();
if (currentScreenWidth >= 1200) {
$('.mobile-child-nav-links').addClass('hideEls');
disableMobileNav();
} else {
enableMobileNav();
}
});
});
</script>
CSS
/* ================= Mobile Accordian Sub Nav ======================= */
/*Sub nav links for mobile device nav */
div.mobile-child-nav-links, div.mobile-child-nav-link {
display: none;
/*visibility: hidden;*/
background-color: #AF251F !important;
color: white !important;
letter-spacing: .1em;
text-transform: uppercase;
padding: .5em;
font-size: .8em;
font-weight: 400;
padding-left: 1em;
}
#media screen and (max-width: 1200px) {
div.mobile-child-nav-links, div.mobile-child-nav-link {
display: block;
/*visibility: visible;*/
}
}
.hideEls {
display: none;
/*visibility: hidden;*/
}
.showEls {
display: block;
/* visibility: visible;*/
}
Inline style and jQuery's .css are different things. You cannot rely on that. Use modernizr media queries.
You could try setting the style attribute to an empty string to remove any inline styles.
$('.styled-nav-link').attr('style', '');
Edit: Be careful with your jQuery selectors. I see several places in your code where there isn't a specification of whether you are selecting a class versus an id. This could be the reason your test is failing. Try double checking your code for errors. I believe the above should work.
For example, this section:
if ( $('mobile-child-nav-links').css('display') == 'block') {
console.log("tested true");
$('mobile-child-nav-links').css('display', 'none');
} else {
console.log("tested false");
}
Should be:
if ( $('.mobile-child-nav-links').css('display') == 'block') {
console.log("tested true");
$('.mobile-child-nav-links').css('display', 'none');
} else {
console.log("tested false");
}
There are other places in your code where periods need to be added too. Double check this and see if this changes anything for you.
Also, yes. jQuery's .css function is just applying the styles inline. Unless I'm mistaken, please let me know how they differ. Adding Modernizr would only add extra page weight.
After countless tests... the only thing that superseded jQuery's inline display:block was specifying an #media screen query for everything greater than 1200px wide. If you look at my CSS, I already specified display:none in the element's css and you would think this would be the style unless overriden, which is exactly what jQuery was doing. However, specifying display:none for Desktop screen widths was the only thing that worked.
/* Overrides jQuerys inline style of display:block at runtime. */
#media screen and (min-width: 1200px) {
div.mobile-child-nav-links, div.mobile-child-nav-link {
display: none!important;
}
Related
I have a mobile-menu which is toggled by js code when user clicks the mobile-menu-icon.
The problem I have is: when re-sizing screen from mobile view to large view, the menu is still open.
I used media query to hide the mobile-menu for large screens, but it seems the toggle method added display:block on the element and the media query cannot override that.
What's your approach to fix this problem?
Instead of using .toggle, use .toggleClass("hidden"). Then you can use CSS
.hidden {
display: none;
}
When the class is removed, it will get whatever styling is default for the media type.
#media only screen and (min-width: 768px) {
.mobile-menu { display: none !important; }
}
Try overriding the same by adding !important to display:none in media query for large screens
Or use a resize script like this:
$(window).resize(function () {
if ($(window).width() > 641) {
$(".mobile-menu").hide();
}
else {
}
})
For my first responsive design I use css #media with display: none; or display:table-cell to show or hide sidebars. This works fine, I need the display:table-cell for a three divs layout.
CSS example:
#div_right { display: table-cell; }
#media screen and (max-width: 700px) { #div_right {display: none; } }
JS is standard ToogleDisplay function (with e.style.display = "table-cell"; in place of e.style.display = "block"; )
On small windows/screen the sidebars are hidden, but a new div with 2 options to display these 2 same navigation sidebars appears: clicking on a link with embedded javascript, allows to toogle display of a sidebar div. It also works fine.
The problem comes when I show then hide the sidebars by clicking on the JS links (on small windows), and then resize the window to a larger width: the sidebars are not displayed this time!
Is there a #media condition to specify "on larger width than xxx" do force display:table-cell; ?
I don't want to use jQuery, and a solution with CSS would be nice.
Just use min-width instead of max-width:
#div_right { display: table-cell; }
#media screen and (min-width: xxx) { #div_right {display: none; } }
Very simple, tells the browser that these rules are to be used if the browser is larger then xxx.
If you want to know everything about #media queries, check out the Mozilla Docs On It.
Could be very helpful to you.
To see it in action, see this JSFiddle
[EDIT]
As noted in the other answer, if you are using jquery, it will override the #media rule.
The correct way to do this, not using !important is to use jquery:
In your js:
$(".menu").show().css("display","block");
This JS shows it as display:block;
Are you using jquery to $.('el').css("display","none") or .hide() the elements? If so jquery will add the style as an inline-style - hence overwriting your media query.
You can try to add !important to your CSS code (the media query) and it might work.
See: http://www.iandevlin.com/blog/2013/05/css/using-important-in-your-media-queries
Also please note the follow rule of thumb:
CSS style is applied in the following hierachy/priority:
!important is always highest priority
The closer styles to your elements will override styles defined before:
inline styles are higher priority
CSS styles are lowest priority
Please check: developer.tizen.org/dev-guide/2.2.1/org.tizen.web.appprogramming/html/guide/w3c_guide/dom_guide/html_priorities_css.htm
Also you might want to use not only min-width, but rather a range like:
#media screen (min-width: xxx) and (max-width: yyy){ }
Check out some standard templates from: http://css-tricks.com/snippets/css/media-queries-for-standard-devices/
I've been fiddling around with my navigation menu and decided to add a feature when you scroll down past a certain point the NAV slides down into viewport so that the user doesn't have to scroll back up to the top of the page to navigate. This is something that's become quite popular lately.
So I fiddled around and this javascript did the trick (note that I am not fluent with jquery at all):
jQuery(document).ready(function($){
$(".menu_wrapper").before($(".menu_wrapper").clone().addClass("shrink"));
$(window).on("scroll", function () {
$("body").toggleClass("slidedown", ($(window).scrollTop() > 700));
});
});
Now I read that as ... duplicate or 'clone' (make another) .menu_wrapper element before the original + add the class .shrink to it ... AND only once we've scrolled past 700px, we'll see this duplicate NAV because of the class .slidedown
CSS:
.shrink { position:fixed; top:-400px; left:0; width:100%; border-top: 0px solid #35d3c3; z-index:99999}
.slidedown .shrink { top:0;}
Now this is working 100% and I'm stoked BUT (it's never smooth sailing is it!!!) now I've got a problem when I change my viewport to a screen width less than 767px - YES my website is responsive and this is where my NAV changes to the typical drop down (even without the javascript / effect above) by using css and javascript:
jQuery(document).ready(function($){
$('.menu_wrapper').prepend('<div id="menu-icon">Menu</div>');
$("#menu-icon").on("click", function(){
$("#menu").slideToggle();
$(this).toggleClass("active");
});
});
My problem is that there is now a duplicate dropdown prepended NAV (1 on top of the other), like so:
+ MENU
+ MENU
The one NAV works but the other doesn't ... anyway regardless, when my media query hits 'mobile status' (below 767px) and the NAV prepends to a dropdown, this is when I DON'T want the whole slide-down-effect-clone (first jquery posted above) thing anymore. I want that rule to almost not exist or not apply when I'm below 767px screen width. How can I do this?
I've tried one of the obvious like:
.shrink { display:none}
.slidedown .shrink { display:none}
which almost seems like I've hit the jackpot leaving me only 1 prepended menu:
+ MENU
but nothing happens when I click on it - it doesn't slidedown and show the menu list items.
but I'm thinking like adding a rule within for the javasacript:
jQuery(document).ready(function($){
$(".menu_wrapper").before($(".menu_wrapper").clone().addClass("shrink"));
$(window).on("scroll", function () {
$("body").toggleClass("slidedown", ($(window).scrollTop() > 700));
});
});
that when we get below a width of 767px, we ignore the clone() function / rule etc?
I've done some googling of removeclass etc but because I'm a bonehead at javascript, I'm probably doing it all wrong.
Any help I'd appreciate it?
Since you want to hide that menu based on certain viewport dimensions, why not use a media query?
#media all and (max-width: 766px){
.shrink{ display: none; }
}
or
.shrink{ display: none; }
#media all and (min-width: 767px){
.shrink{ display: block; }
}
(That might not be the best width values or CSS properties to use there, but that should get you started.)
Edit: If you wanted to do the entire thing in javascript, the matchMedia() API is there for you, too.
If the CSS media query approach that ajm posted does not work for you, you could try only executing your code if a media query is met. The code in handleMediaQuery() will only run if the width is above 767px;
//Media query listeners
var mql = window.matchMedia("(min-width: 767px)");
mql.addListener(handleMediaQuery);
handleMediaQuery(mql);
function handleMediaQuery(mql) {
if (mql.matches) {
// Do stuff here that you want done when the query matches
}
else {
// Do stuff here that you want done when the query does not match
}
}
See https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Testing_media_queries for more info
I'm building a responsive website using css medias and JQuery.
I created a script to check the page width:
if ($(window).width() < 1240) {
$("#menu").toggle(); //hide menu
$('#body-wrap').toggleClass('shifted'); //puts the body width to 100%
$('#navbar').toggleClass('shifted'); //puts the navbar width to 100%
}
But this code only works when I refresh the page.
How can I do it automatically?
Thanks.
Put it in a resize event.
window.addEventListener('resize', function () {
// Your code
});
You may want to consider using CSS to do this instead, though (look at media queries for that)
You have to add it to the onresize event:
https://developer.mozilla.org/en-US/docs/Web/API/Window.onresize
This event will be called each time when you resize the window, so you can respond to those changes.
But I think a better option would be to use CSS media queries, like so:
#media only screen
and (max-device-width : 1240px) {
#menu {
display: none;
}
}
Example and info on: http://css-tricks.com/snippets/css/media-queries-for-standard-devices/
In my page design, I have put a menu button on the small resolutions, which onclick I show the menu items. If the items are in the show state (which is done by JS) and I maximize the browser (it would change to another query conditions) the items did not hide. Even I add the display:none to the css to hide them, but it did not hide. To overcome I put !important there. But it caused another issue: the menu items would not shown by the menu click.
It is appreciated if someone could help me.
Edit for better understanding.
The menu click js is as following:
$("#mobilemenu").click(function(){
var dis = $("#menuitems li").css('display');
if(dis == 'none') {
$("#menuitems li").slideDown("slow");}
else {
$("#menuitems li").slideUp("slow");
}
});
On my media query:
#media {
#menuitems li {display:none;}
}
And on the main css:
#menuitems li {display:none;}
Rather than directly setting the style in your JavaScript code, you should instead give the element a class which allows it to be styled with CSS.
For example, instead of directly setting display: block, you can show the element like this:
JavaScript
myElem.className = 'show';
CSS
myElem.show {
display: block;
}
Then with your media query, you can simply override this:
CSS
#media screen {
myElem.show {
display: none;
}
}