Override the JavaScripted style with media query - javascript

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;
}
}

Related

CSS properties changing in HTML instead of Stylesheet

Objective: Change the properties of CSS Stylesheet instead of HTML CSS using Javascript.
Current Issue: using document.getElementById("foo").style.display = "none" causes changes in HTML document that removes Media Query functionality
My website has a button that changes the display of a sidenav bar on smaller screens. This button is not available on screen sizes greater than 768px. The website is dynamic, so the button shows up when the screen is small enough. When the button is clicked, the sidenav (initially set to display:none), is set to display:block, which can then be closed again.
Once the sidenav is closed in a screensize < 768px, and the screen is increased to a size > 768px, the media query no longer changes the display to block because the Javascript changes the HTML, which overwrites the CSS media query.
Below is the code and changes the Javascript does to the HTML.
HTML Before:
<div id="sidenav">foo</div>
<!-- button to change sidenav -->
<div id="menu-button" onclick="openCloseNav(this)"></div>
Javascript
function openCloseNav(x){
if(x.classList != "change"){
document.getElementById("sidenav").style.display = "none";
}
else{
document.getElementById("sidenav").style.display = "block";
}
}
CSS
#sidenav{
display:none;
}
#media only screen and (min-width: 768px){
#sidenav{
display:block
}
}
HTML After div id="menu-button" is clicked twice
<div id="sidenav" style="display:none">foo</div>
<!-- button to change sidenav -->
<div id="menu-button" onclick="openCloseNav(this)"></div>
I have tried a few different things such as attempting to detect screenwidth in Javascript like this:
var currentWidth = window.screen.availWidth;
function showSideNav(){
if (currentWidth >= "768"){
document.getElementById("sidenav").style.display = "block";
}
}
to no avail. If the snippet above does work, I don't know where to place it in my HTML.
Question:
What can I do to make it so that the sidenav will show even after the menu-button div is clicked on screen sizes > 768px?
Whenever possible, change styling via the addition/removal of CSS classes, rather than affecting the element.style object. This not only makes the code cleaner and reduces code duplication, but it eliminates the issue you are having with the CSS being added directly to the HTML element as an inline style, which is the most specific way to add CSS and difficult to override.
You can easily add/remove/toggle and more with CSS classes with the element.classList API.
Here's a simplified example:
document.querySelector("button").addEventListener("click", function(){
document.getElementById("element1").classList.add("hidden");
document.getElementById("element2").classList.remove("special");
// Just to show that classList modifications don't alter the inline HTML style
console.log(document.getElementById("element1"), document.getElementById("element2"));
});
.hidden { display:none; }
.special { background-color:#ff0; color:#800080; }
<div id="element1">Now you see me...</div>
<div id="element2" class="special">Something else</div>
<button>Click to change styles</button>
You could use an extra attribute that controls your navbar, so you can use you JavaScript independent of you CSS. I am not sure that the css I put here is correct but I think you get the idea.
EDIT I just noticed thanks to #Doug that you can just use a class instead.
function openCloseNav(x) {
if (x.classList != "change") {
document.getElementById("sidenav").setAttribute("hideme", true);
} else {
document.getElementById("sidenav").setAttribute("hideme", false);
}
}
#sidenav[hideme=true] {
display: none;
}
#media only screen and (min-width: 768px) {
#sidenav {
display: block
}
}
<div id="sidenav">foo</div>
<!-- button to change sidenav -->
<div id="menu-button" onclick="openCloseNav(this)"></div>

Hide div if nav is opened

I have a very simple page with the standard bootstrap nav which collapses when on small screen. Right below the nav I have a div which I do not want to show if the li has CSS class dropdown open. Is it possible to do this via CSS only or do I have to go down the jQuery/Javascript route?
.navbar-nav > li.dropdown.open {
/*How can I hide the div class="inner-details" here*/
}
If the dropdown element is not wrapped with another one, you could possibly use the adjecent sibling selector like this:
li.dropdown.open + .inner-details {
display: none;
}
Otherwise you could do tricks with negative margin and z-index, effectively sliding content from below the dropdown behind it, but really this will lead to messy layout.
There's no evil in using JavaScript. Bootstrap itself uses it for the navigation if I remember correctly.

How to get media queries to work with style added by a toggle function

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 {
}
})

How to override jquery slidetoggle when screen size changes

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;
}

CSS Hover being de-activated

I am displaying a page of thumbnails, which if you hover over them, their description is displayed.
for this I am using a span element with CSS
.thumb:hover .thumbText {
display: inline-block ;
}
This works fine initially.
But as this needs to work on a touch device and touch does not have hover, I added a button to show all descriptions.
This also works fine, but once I have used the Button Toggle, Description my javascript function has somehow disabled the CSS hover and I can not work out why.
var CaptionsOff = true;
function toggleCaptions() {
if (CaptionsOff) {
/* Turn Captions ON */
$('.thumbText').css("display", "inline-block")
$("#btnCaption").html("Hide Thumb Captions");
CaptionsOff = false;
} else {
/* Turn Captions OFF */
$('.thumbText').css("display", "none")
$("#btnCaption").html("Show Thumb Captions");
CaptionsOff = true;
}
The site is
http://mclportal.net/wcit/June26.html
That Javascript code adds the CSS to a style attribute on the element. For example:
<span style="display:none">Caption</span>
Style attributes take priority over CSS files. To change this, modify your CSS script like this:
.thumb:hover .thumbText {
display: inline-block !important;
}
This code means that the display from the CSS is used, rather than from the attribute.
Also, you are missing semicolons.
Hope this helps.
Alternatives:
Toggle a class
$(".buttonCaption").toogleClass("showCap")
.thumb:hover .thumbText, .showCap {
display: inline-block;
}
Set the display to nothing, rather than none. Assumes that the captions are have display:none as default in CSS. Other two solutions are probably better than this.
$('.thumbText').css("display", "");
Add !important to your class rule. The .css() method adds the style to element's "style" attribute which has higher priority.
.thumb:hover .thumbText {
display: inline-block!important ;
}
Setting inline style to $('.thumbText') in toggleCaptions() overrides the stylesheet. Toggle a class instead of setting inline styles.
add this in else with your code::$('.thumbText').removeAttr("style");

Categories

Resources