CSS is not changing display value after js function changes it [duplicate] - css

This question already has answers here:
Understanding CSS selector priority / specificity
(4 answers)
JavaScript hide/show element
(13 answers)
Closed 3 years ago.
Referring to the example code below.
CSS is not changing the display value after the js function changes it.
Expected example behaviors:
narrowing window hides "nav display"
widening window displays "nav display"
clicking "toggleNav" toggles visibility of "nav display"
Unexpected example behaviors:
clicking "toggleNav" disables the effect of window width
/* toggle between showing and hiding nav when the user clicks on toggleNav */
function toggleNav() {
var x = document.getElementById("nav");
if (x.style.display === "block") {
x.style.display = "none";
} else {
x.style.display = "block";
}
}
#nav {display: block; } /* display is not restored after js function */
/* narrow window */
#media screen and (max-width: 70rem) {
#nav {display: none } /* display is not removed after js function */
}
<div>
<!-- button to toggle nav display -->
<a href="javascript:void(0);" class="icon" onclick="toggleNav()">
<div>toggleNav</div>
</a><br>
<nav id="nav">
<h1>nav display</h1>
</nav>
</div>
<p>Initially, #media width toggles nav display.</p>
<p>After running toggleNav() function, #media width does nothing.</p>
Apparently, CSS does not change display value after js changes it.
Is there some way for media max-width to change a display value after js changes it?
ANSWER:
The solution is to use js for all show and hide:
<!DOCTYPE html>
<!-- based on https://www.w3schools.com/howto/howto_js_media_queries.asp -->
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>dropbtn</title>
<script src="https://code.jquery.com/jquery-1.8.3.min.js"></script>
</head>
<body>
<div>
<!-- button to toggle nav display -->
<a href="javascript:void(0);" class="icon" onclick="toggleNav()">
<div>toggleNav</div>
</a><br>
<nav>
<h1>nav display</h1>
</nav>
</div>
<p>Initially, #media width toggles nav display.</p>
<p>After running toggleNav() function, #media width does nothing.</p>
<script>
/* toggle between showing and hiding nav when the user clicks on toggleNav */
function toggleNav() {
$("nav").toggle();
}
/* if narrow window, hide nav, if wide window show nav */
function wideShowNav(x) {
if (x.matches) {
$("nav").hide();
} else {
$("nav").show();
}
}
var x = window.matchMedia("(max-width: 70rem)")
wideShowNav(x) // Call listener function at run time
x.addListener(wideShowNav) // Attach listener function on state changes
</script>
</body>
</html>

Related

hamburger dropdown css display property

I have a CSS media query / flexbox style that assigns a "display: none" to a navigation div after it goes to the max-width of 768px. Using Javascript, I was able to toggle display: "block" and "none" using an if/else statement once my hamburger button is pressed.
However, the pain point is that once I toggle it to "display: none", the navbar is now gone once the screen is beyond the designated width; and hamburger menu only appears at the smaller width size.
It seems like the toggle permanently assigns "display: none" to it. How would I remove the "display: none" back to "display: block" without clicking on hamburger button?
const burgerBar = document.querySelector('.burger');
const navigation = document.querySelector('.navigation');
const navbarItems = document.querySelector('.navbar-items');
const navbarItem = document.querySelector('.navbar-item');
burgerBar.addEventListener('click', () => {
if (navigation.style.display != 'block') {
navigation.style.display = 'block'
} else {
navigation.style.display = 'none'
}
})
#media screen and (max-width: 768px) {
/* width below 768 */
.header-container {
padding: 15px;
}
.navigation {
display: none;
}
.burger {
display: block;
}
}
<div class="navigation">
<nav class="navbar-container">
<ul class="navbar-items">
<li class="navbar-item">Home</li>
<li class="navbar-item">Projects</li>
<li class="navbar-item">Github</li>
<li class="navbar-item">About</li>
<li class="navbar-item">Contact</li>
</ul>
</nav>
</div>
<div class="burger">
<div class="bar-one"></div>
<div class="bar-two"></div>
<div class="bar-three"></div>
</div>
what you are doing with javascript is using inline-styles for the tag itself
for eaxmple
navigation.style.display = 'block'
will make it like this
<div style="display:none;"> </div>
but what you are doing with css using classes can't override the inline-styles
due to CSS Specificity
Every selector has its place in the specificity hierarchy. There are
four categories which define the specificity level of a selector:
Inline styles - An inline style is attached directly to the element to
be styled. Example: .
IDs - An ID is a unique identifier for the page elements, such as
#navbar.
Classes, attributes and pseudo-classes - This category includes
.classes, [attributes] and pseudo-classes such as :hover, :focus etc.
Elements and pseudo-elements - This category includes element names
and pseudo-elements, such as h1, div, :before and :after.
solution:
use javascript to toggle a class (instead of changing the property directly) that hides the navigation
solved! The display_toggle class need to be after the media query...I believe that has something to do with specificity that.

Multiple click functionality on link in Angular

I have a link that triggers a modal to appear, but also need to apply a class to the body in order to set position: fixed due to the iOS 11 bootstrap modal form field bug. However, this isn't setting the property to the body.
HTML
<body class="" ng-class="{'login-form' : toggle, 'login-form' : !toggle}" window-detection page-class>
<a ng-click="openLoginModal(); toggle = !toggle"
data-rt-id="login--sm">[[ "Login / Join" | translate ]]</a>
CSS
body{
#media screen and (max-width: 414px){
.login-form{
position: fixed!important;
}
}
How can I toggle a class on the body when the user clicks the login button?
Which bootstrap version are you using . Use 3.2 version.
You can use some thing like that
.modal-open .navbar-fixed-top,
.modal-open .navbar-fixed-bottom {
margin-top:70px
}
Change the code like so.
var app = angular.module('myApp', []);
app.controller('MyController', function MyController($scope) {
});
.login-form{
background-color:blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body class="" ng-class="{'login-form' : toggle, '' : !toggle}" window-detection page-class ng-controller='MyController' ng-app="myApp">
<a ng-click="openLoginModal(); toggle = !toggle"
data-rt-id="login--sm">{{"Login / Join" }}</a>
</body>

Lay a .png image partially over (on top of) menu

I have an accordion menu that I have tweaked to suit my needs. My last stumbling block is that I have an image (see attached image) of a FedEx Courier that I need to lay on top of the menu and yet still allow users to click through it to activate (access) the accordion menu. The image is a separate image that is set to the desired alpha as created in Photoshop. The file is merely a snapshot of how it would look if it was the way I wanted it.
If this is even possible, what code would I use and exactly where would I place it? If in the CSS file, where does it go and between which lines?
Original full size Image file
You can apply the css:
pointer-events: none;
to the image above the links.
See fiddle https://jsfiddle.net/4zgcrkyz/
pointer-events: none; is a suitable solution if you do not need to care about IE < 11. More info on compatibility here.
Alternatively you can use elementFromPoint() which has compatibility IE > 5.5
The following trick allow you to select under your cover image without using pointer-events: none;
https://jsbin.com/tuhotagize/edit?html,output
Explanation:
At click on cover image.
Hide cover image temporary.
Get mouse coordinates.
Get HTML element under that mouse coordinates (so you know what under the cover).
Trigger click event on that HTML element.
Show cover image again.
Another alternative solution to your problem, which does not include any JS is:
Trim your image in PhotoShop as should appear inside the menu. Use CSS background-image property on it
Use the courier FedEx image only as CSS background-image the body of your page.
You can achieve the same visual effect using only CSS.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Test</title>
<style>
img {
position: absolute;
top: 0;
left: 0;
opacity: 0.4;
}
a {
display: block;
width: 300px;
height: 20px;
background-color: greenyellow;
}
a:hover {
background-color: #FF0000;
}
</style>
<script>
window.app = {
show: function () {
document.getElementById('cover').style.display = '';
},
hide: function () {
document.getElementById('cover').style.display = 'none';
},
event: null,
start: function () {
document.getElementById('cover').addEventListener('click', function (event) {
this.hide();
this.event = event;
var target = document.elementFromPoint(event.pageX, event.pageY);
this.show();
target.click();
}.bind(this));
var links = document.querySelectorAll('a');
for (var i = 0, len = links.length; i < len; i++) {
links[i].addEventListener('click', function (event) {
alert('click on ' + event.target.id);
}.bind(this));
}
}
};
</script>
</head>
<body onload="window.app.start();">
<img id="cover" src="http://placehold.it/200x200" />
<a id="a1">link</a>
<a id="a2">link</a>
<a id="a3">link</a>
<a id="a4">link</a>
<a id="a4">link</a>
<a id="a6">link</a>
</body>
</html>

fixed position menu with changing background colors

I have inherited a project, and have some questions on how to resolve a particular issue.
There is a fixed left sub-nav, seen below. As the user scrolls, there are 6-10 different "sections" that are stacked vertically. The top section has a background-image (seen below), while the remaining sections alternate between white & various colors, such as:
section 1: background-image
section 2: background-color: white
section 3: background-color: blue
section 4: background-color: white
section 5: background-color: green
... etc
The customer wants the menu items to change colors based on what background each item is over at a given time (so as you scroll, it's changing item by item). As you can see in the image, when I scroll from the header to the first content section, I'm moving to a white background, so my menu is white text on a white background (the 5th menu item is moving into the white background).
The guys that worked on this initially used jquery waypoint to trigger wholesale changes to the menu item color when a particular div scrolled to a certain location. This basically works - but only when the entire section is scrolled to the top of the menu (meaning the menu items are white-on-white until the last menu item is scrolled into the section).
Any thoughts on how to handle this?
[EDIT TO ADD]
I thought I made this pretty clear above. We're already using jquery waypoints. The problem is, waypoint cannot trigger on each menu item (primarily since the menu items are not part of the ancestral tree of the content nodes, which prohibits me from passing in a context to the waypoint handler), unless I create a handler for the section div at each offset of every menu item (which are different for each page). This would result in a crazy amount of waypoint handlers being bound, which I don't think is ideal.
Here is an example of what I'm describing. As you scroll, the menu items change all at once. You can see where this is a problem when you're scrolling down from the header into the first content section. The menu items are white. So is the background of the first content section. So until the waypoint is hit, the menu is effectively hidden. What I am looking to do is change the color of each menu item as it "enters" or "exits" a particular content div. I suppose I could do this on window.scroll, but that seems pretty expensive. Was hoping there's something I'm either missing with waypoints, or a better way to do this.
Alright, so I did solve this by creating an event handler at every offset. Given that I have 6-10 menu items per page (so 6-10 sections), I don't really like a solution where I create 36-100 event handlers, so I'm hopeful somebody has a better one (although I'm starting to doubt it).
SO is telling me I need to post code, so here goes:
HTML
<div class="menu">
<ul>
<li>
<a href='#header'>Header</a>
</li>
<li>
<a href='#getting-started'>Getting Started</a>
</li>
<li>
<a href='#zomglaserguns'>Laser Guns</a>
</li>
<li>
<a href='#pewpew'>Pew Pew</a>
</li>
</ul>
</div>
<div id="header" data-menu-color-down='#fff' data-menu-color-up='#000'>
Some header content
</div>
<div class="content">
<div id="getting-started" data-menu-color-down='#000' data-menu-color-up='#fff'>
some content
</div>
<div id="zomglaserguns" data-menu-color-down='#fff' data-menu-color-up='#000'>
laser guns!
</div>
<div id="pewpew" data-menu-color-down='#000' data-menu-color-up='#fff'>
pew pew!!!!
</div>
</div>
JS:
var myObj = {
menuOffsets: {},
pageSections: [],
init: function() {
myObj.initMenuOffsets();
myObj.initSections();
myObj.initWaypoints();
},
initMenuOffsets: function() {
$('.menu a').each(function() {
var self = $(this),
href = self.attr('href'),
menuItemHeight = self.height();
myObj.menuOffsets[href.substring(1, href.length)] = self.offset().top + self.height();
});
console.log(myObj.menuOffsets);
},
initSections: function() {
var header = $('#header'),
sections = $('.content > div');
if(header.length) {
myObj.pageSections.push('header');
}
sections.each(function() {
var self = $(this);
myObj.pageSections.push(self.attr('id'));
});
console.log(myObj.pageSections);
},
initWaypoints: function() {
var menuItemColor,
key,
i = 0,
len = myObj.pageSections.length;
for ( i; i < len; i++ ) {
for ( key in myObj.menuOffsets ) {
if( myObj.menuOffsets.hasOwnProperty( key ) ) {
(function ( key, i ) {
$('#' + myObj.pageSections[i]).waypoint(function(direction) {
var self = $(this);
menuItemColor = self.data('menuColor' + (direction === 'up' ? 'Up' : 'Down'));
$('.menu a[href="#' + key + '"]').css('color', menuItemColor);
}, { offset: myObj.menuOffsets[key] });
})(key, i);
}
}
}
}
};
myObj.init();
SEE-ESS-ESS:
.menu {
position: fixed;
top: 40px;
left: 10px;
color: white;
}
.menu li {
list-style-type: none;
}
.menu a {
color: inherit;
text-decoration: none;
}
.content {
}
#header {
background: black;
color: white;
height: 200px;
padding: 0 120px;
}
#zomglaserguns {
background: green;
color: #777;
}
.content div {
min-height: 300px;
padding: 0 120px;
}
Well, it's not too difficult to set up some ID's on the page, and use those as anchors for when to trigger the background change.
Say you had an HTML structure like this:
<header>
...
</header>
<div id="getting-started" data-background-color="lightBlue">
...
</div>
<div id="afford" data-background-color="red">
...
</div>
<div id="down-payment" data-background-color="green">
...
</div>
<div id="financing" data-background-color="blue">
...
</div>
And now you include jQuery Waypoints
<script type="text/javascript">
(function($) {
$('#getting-started').waypoint(function() {
var $this = $(this);
$('header').css('background-color', $this.data('background-color'));
});
})(jQuery)
</script>
Keep in mind this isn't a complete solution, just something to help poke you in the right direction.

Parallax scroll a background image into permanent view

The affect I'm going for is something I can only compare to Google+ top navigation effect and through some parallax into that. That is, when you scroll down, the search bar disappears and your left with a small "toolbar". I found some jQuery to help me out and I will mess with after I figure this out.
What I'm trying to do first, is get a background image to scroll from below the bar (see the jfiddle) and scroll up to the bar where it will eventually stay put. This is what I've got so far:
<section id="account-bar" class="shelf navbar-fixed-top">
<div class="navbar-header">
more...
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li>Links</li>
</ul>
</div>
</section>
with the associated css:
section#account-bar {
background-color:#111;
color:#ccc;
font-size:1.1em;
height:3.6em;
line-height:3.4em;
text-align:right
}
section#account-bar:after {
content:'';
width:267px;
height:46px;
background:url('http://lorempixel.com/267/46/') no-repeat 0 0 scroll;
background-size:267px 46px;
top:0;
left:0;
position:absolute;
}
EDIT: Here's that jsFiddle
Although this is not currently possible in pure CSS, by using window.onscroll, scrollTop, and a couple if statements, you can create a lovely state change effect that is similar to what you're looking for
Looking at the Google Plus page, there was some content above the navigation. As a result, I set up my HTML as follows
<div class='topContent'>Top Content</div>
<nav>
<div class='googleSlide'></div> <!--The image that slides in from the left-->
<div class='navContent'>Nav bar content</div> <!-- Everything else in nav -->
</nav>
Here are my important CSS lines to get it functioning
.topContent { height:75px; /* Arbitrary but necessary value */ }
nav { height:44px; width:100%; }
nav div { float:left; }
.googleSlide {
background-image: url(//ssl.gstatic.com/s2/oz/images/sprites/ribbon-nav-1x-69dd561f4c55d6702aadda4e3b4ce787.png);
background-position:0 -100px;
height: 44px; /* More arbitrary but necessary values */
width: 44px;
margin-left:-55px;
transition: all 0.200s; /* To smooth the transition to the new state */
}
And finally, we have the javascript that gets it all working
window.onscroll = function() { // Fires whiles the page scrolls
var navigation = document.getElementsByTagName('nav')[0],
slide = document.getElementsByClassName('googleSlide')[0];
// Conditional to check whether scroll is past our marker, second conditional
// to make sure that it doesn't keep firing when scrolling inside of the range
if(document.body.scrollTop > 75 && navigation.style.background != 'white') {
navigation.style.background = 'white';
navigation.style.border = '1px solid black';
navigation.style.position = 'fixed';
slide.style.marginLeft = '0px';
}
// Same as above but toggles back to the original state
if(document.body.scrollTop < 75 && navigation.style.background != 'grey') {
navigation.style.background = 'grey';
navigation.style.border = 'none';
slide.style.marginLeft = '-55px';
navigation.style.position = 'static';
navigation.style.top = '0px';
}
}
Demo
I'm not sure exactly what you mean by scrolling the background, but a similar approach as this one can get you what you want

Resources