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() { ... });
Related
I am making a panel of photos/text. All the panels will have an overlay color on them except the first one which has an active class on page load which removes the overlay. As you hover over the second/third etc panels, the overlay active class will remove from first panel and go onto the one that is hovered.
Right now it is only active on page load, I can't seem to get the class off the first div and onto the second div on hover.
if ( $(".overlay:first") ){
$(".overlay:first").addClass("active");
}
else {
if ( $(".overlay:not(:first)").hover ){
$(".overlay:first").removeClass("active");
}
}
https://jsfiddle.net/egdkuh16/3/
There is no need to use JavaScript or jQuery for this. It's best used in CSS with the :hover pseudo-selector. It's also much easier today.
.overlay:first-child {
background: white;
}
.overlay:first-child:hover {
background: gold;
}
If you insist on using jQuery, you can try this
$(".overlay:first").on("mouseover", function() {
$(this).addClass("active");
}).on("mouseout", function() {
$(this).removeClass("active");
});
.active {
background: gold;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="overlay">First overlay class</div>
<div class="overlay">Second overlay class</div>
This approach is highly frowned upon though
In jQuery, you could do it like this:
$(document).ready(function() {
// Make the first active
$(".overlay:first").addClass("active");
// On hover remove all active classes from .overlay
// and add .active only to the one that is hovered
$(".overlay").hover(function() {
$(".overlay").removeClass("active");
$(this).addClass("active");
});
});
but Richard Hamilton's answer is much better and cleaner.
You can use jQuery's on. For example:
$(".overlay:first").addClass("active");
$(".overlay").on("hover", function(){
$(this).addClass("active");
$(".overlay:first").removeClass("active")
});
My website has had nav dropdowns that I made with CSS but I've recently changed it to jQuery so it's animated. When it was CSS I was able to disable the dropdowns on the smallest breakpoints for mobile. But with jQuery I don't know how to do that. This is my dropdown code. What can I do to it to make it disable when the viewport gets small enough?
$(document).ready(function() {
$('.nav > li').mouseenter(function() {
$(this).children('.nav-content').slideDown(200);
});
$('.nav > li').mouseleave(function() {
$(this).children('.nav-content').slideUp(200);
});
});
This is the website as it is now:
http://mattboy115.github.io/scarymonkeyshow/index.html
You can check the size of the screen with $(window).width() and $(window).height()
So something like
$(document).ready(function() {
if($(window).width() > 800){
$('.nav > li').mouseenter(function() {
$(this).children('.nav-content').slideDown(200);
});
$('.nav > li').mouseleave(function() {
$(this).children('.nav-content').slideUp(200);
});
}
});
The answers given will work, but I'd recommend making a second nav for mobile and using media queries to make the right one show.
Just real simple HTML:
<div class="desktop-nav">
[nav code]
</div>
<div class="mobile-nav">
[mobile nav code]
</div>
then CSS:
#media screen and (min-width: [X]px) {
.mobile-nav {
display: none;
}
}
#media screen and (max-width: [X]px) {
.desktop-nav {
display: none;
}
}
then your jquery is solved by just applying the mouseenter to .desktop-nav:
$(document).ready(function() {
$('.desktop-nav > li').mouseenter(function() {
$(this).children('.nav-content').slideDown(200);
});
$('.desktop-nav > li').mouseleave(function() {
$(this).children('.nav-content').slideUp(200);
});
});
I am uncertain if you are looking to do this at a specific size or if you want it for mobile. For example you can use modernizer to detect if touch is enabled on the device:
Using Modernizr to test for tablet and mobile - Opinions wanted
you can also check user agents to match device types and apply your code that way:
What is the best way to detect a mobile device in jQuery?
You can then apply if it does or doesn't match your conditions based on your detection..
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
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.
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();
}
);