In the code below for a simple menu, if the sub-menu is expanded/showing, then I need the sub-menu to collapse on several conditions:
When the main menu or sub-menu LI is clicked
When the viewport is larger than the defined minimum width
When a click happens anywhere else on the screen
Number 2 works and number 1 works as long as I don't declare the addEventListener for the mainMenuID element. For some reason, when I add that event listener for any mainMenuID element, it takes precedence over anything else thus clicking on a main menu item other than Portfolio or its sub-menu items, expands and collapses the menu, but clicking on the submenuID or the ulID does nothing. As soon as I remove the eventlistener for mainMenuID, clicking on submenuID or ulID expand/collapse the sub-menu.
The second question is, how do I add a click event listener to the rest of the page so that if the sub-menu is showing, the click collapses the sub-menu.
Thank you!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
</head>
<style media="screen">
body{
background-color: black;
}
nav ul {
position: relative;
text-align: left;
}
nav ul li {
display: block; /* WHAT???? REMOVING THIS ACTUALLY MAKES TEXT-DECORATIONS REAPPEAR.... WHY???*/
}
nav a {
text-decoration: none;
}
/* Hide dropdowns by default */
nav ul ul {
position: relative;
display: none;
left: 0;
}
/* Display Dropdowns on Click */
nav ul li.showSubmenu > ul {
display: block;
position: relative;
width: 30%;
}
.menu a {
text-decoration-style: none;
text-decoration: none;
background-color: black;
color: white;
}
.menu a:hover{
background-color: white;
color: black;
}
</style>
<body>
<nav id="mainMenuID" class="menu">
<ul>
<li class="menuItem">Home</li>
<li class="menuItem">About</li>
<li id="submenuItem" class="submenu_class"><span id="submenuID">Portfolio ▼</span>
<ul id="ulID">
<li>Landscape</li>
<li>Architecture</li>
<li>Animal</li>
<li>Other</li>
</ul>
</li>
<li class="menuItem">Information</li>
<li class="menuItem">Contact</li>
</ul>
</nav>
<script>
function openSubmenu() {
if (document.getElementsByClassName('showSubmenu').length == 0){
document.getElementById("submenuItem").classList.toggle("showSubmenu");
document.getElementById("submenuID").textContent = "Portfolio ▲";
} else {
document.getElementById("submenuItem").classList.toggle("showSubmenu");
document.getElementById("submenuID").textContent = "Portfolio ▼";
}
}
function resetSubmenu() {
var submenuElements = document.getElementsByClassName('submenu_class showSubmenu');
for (var i = 0; i < submenuElements.length; i++) {
submenuElements[i].setAttribute('class', 'submenu_class');
document.getElementById("submenuID").textContent = "Portfolio ►";
}
}
function screenWidthFunction(x) {
if (x.matches) {//if it's a narrow screen
document.getElementById("submenuID").textContent = "Portfolio ▼";
document.getElementById("ulID").addEventListener("click", openSubmenu, true);
document.getElementById("submenuID").addEventListener("click", openSubmenu, true);
document.getElementById("mainMenuID").addEventListener("click", openSubmenu, true);
} else {
resetSubmenu();
document.getElementById("submenuID").textContent = "Portfolio ►";
document.getElementById("ulID").removeEventListener("click", openSubmenu);
document.getElementById("submenuID").removeEventListener("click", openSubmenu);
document.getElementById("mainMenuID").removeEventListener("click", openSubmenu);
}
}
var x = window.matchMedia("(max-width: 480px)");
screenWidthFunction(x);
x.addListener(screenWidthFunction);
</script>
<>
Hi Robidu, I had this menu working using just CSS, but I was led to use JS for some of its functionality, which stopped most of the CSS from working.
So at glacier speeds, I’ve been trying to learn JS on the fly. Believe it or not, learning from videos, W3Schools, etc…. I’ve been writing, re-working, and kludging this menu into existence for the better part of 5 or 6 weeks. Totally ridiculous.
It seems you understand and are readily familiar with JS. It would take me many more weeks of trying to figure out how to implement all of your advice, and along the way, I would very likely destroy what already works. Is there any way I could kindly ask you to please save me that pain by providing me with either the code snippets for where they need to go, or just more specific advice.
I’ve excerpted below the parts of your text about which I have questions (because of the character limits on comments, I have to split them across multiple comments):
“…you should use CSS to hide the submenu since I think that this
is to be the default.”
q. Yes, it is the default. I thought I was already doing this in “nav
ul li.showSubmenu > ul {…}” in my CSS.
“…implement an initialization stage that fires on DOMContentReady
to set up a support infrastructure.”
q. This, I would never know how to figure out myself.
“…need a flag that indicates whether or not the menu is open so
that the handler can react accordingly…spare yourself the problem
with "toggle"…have the menu's state at hand…”
q. I thought the “toggling” of the class “showSubmenu” was serving as that kind of ‘flag’. How and where would I use the variable in place of the toggle?
“…spare yourself…repeatedly attaching and removing event
listeners.”, and later on “If the menu is hidden, it doesn't get any
events at all.”
q. Are you saying to assign the listeners to variables anywhere in the JS code? Would I not still need to refer to those variables in the same places where I use the listeners now and in the same manner?
“…attach an event listener that checks for mouse events to the
the item that opens the submenu here.”
q. You mean other than the listener I have on id=“submenuID”? What would be different about what you are advising?
“…attach a resize event handler to the window that performs this
check...”
q. I cropped the screen width code from W3’s examples. How/where would using innerWidth/innerHeight be different?
“…set the bubbling stage to true to intercept the event”.
q. I haven’t been able to find any explanation about bubbling works if you apply one kind to the items in a menu system, and another kind to other elements on a page, etc. I understand the basics, but couldn’t figure out why it wasn’t working on this simple menu when all three listeners were used.
“Collapsing the menu when a menu item is clicked…attach an event
handler to each individual menu item (the best spot would be the links inside the menu”.
q. Would I have to assign an ID to each LI?
Overall question: I used a NAV element with ULs and LIs because
I was told it’s the most accessible for screen readers. Is there a
better way to do what I’m trying to do with this menu or am I sort
of on the right track?
I sincerely apologize for all the follow-up questions/clarifications, but I’m sincerely spinning my wheels on this, going in circles, in rough seas, wearing a blindfold…. and any other analogy you can throw into the mix.
I would truly appreciate any specific coding you can provide to demonstrate the specifics of your advice. (or even point me to examples so that I can try and figure them out).
A bit of retooling should do the trick here.
First of all, you should use CSS to hide the submenu since I think that this is to be the default. Furthermore you should implement an initialization stage that fires on DOMContentReady to set up a support infrastructure. This way you spare yourself the hassle with repeatedly attaching and removing event listeners. You would want to attach an event listener that checks for mouse events to the item that opens the submenu here. You would also need a flag that indicates whether or not the menu is open so that the handler can react accordingly (this way you spare yourself the problem with "toggle" and the likes, plus you immediately have the menu's state at hand if you need to do any additional checks). A simple variable should do the trick here.
The plus side: If the menu is hidden, it doesn't get any events at all.
If you are interested in the window size, I'd recommend that you switch to window.innerWidth / window.innerHeight instead, because that is a numeric value that you get and which can easily be compared to the minimum size that you require. Just attach a resize event handler to the window that performs this check, and you are set. If the window size cuts below your minimum, just force the menu to collapse.
As far as collapsing the menu if the user clicks anywhere within the document, attaching an event listener looking for mouse clicks / key presses to the document object does the trick here (set the bubbling stage to true to intercept the event before anything else can happen).
Collapsing the menu when a menu item is clicked can best be achieved by attaching an event handler to each individual menu item (the best spot would be the links inside the menu - set the bubbling stage to false) that merely closes the menu.
EDIT:
I have done some tinkering now by taking your HTML and CSS, and this is what I have come up with (please note that I have also transformed the file to XHTML - but that's up to you whether or not you want to do that):
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xml:lang="en">
<head>
<title>Submenu Test Case</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<style type="text/css">
body {
background-color: black;
color: white;
}
aside {
width: 15em;
float: left;
}
nav ul {
position: relative;
text-align: left;
list-style: none; /* Kills any list decoration */
}
nav ul ul {
position: relative;
left: 0;
}
nav a {
text-decoration: none;
}
/* This ARIA attribute can greatly improve accessibility and can also be used
to actually hide elements just by tying "display: none;" to it... */
[aria-hidden="true"] {
display: none;
}
.menu a {
color: white;
}
.menu a:hover, .menu span:hover {
background-color: white;
color: black;
}
/* Style definitions that override settings for mobile devices go here! */
#media screen and (min-width: 480px)
{
/* Reposition the submenu if it's on a sufficiently wide window... */
nav ul li > ul {
position: absolute;
margin-top: -1.2em;
left: 7em;
}
}
</style>
<script type="application/javascript">
/* <![CDATA[ */
var submenu_open = false; // Has the submenu been opened?
var need_mobile = false; // Are we on a narrow window?
// Takes care of hiding and showing the submenu
function ToggleMenu(p_event)
{
// Do not activate e. g. on a right click...
if(p_event.button != 0)
return;
if(submenu_open)
{
// If the submenu has previously been open, close it (and adjust the
// controlling menu item if necessary)
document.getElementById('sub1').setAttribute('aria-hidden', 'true');
if(window.innerWidth < 480)
document.getElementById('sub-item1').childNodes[0].childNodes[0].data = 'Portfolio ▼';
}
else
{
// If the submenu has previously been closed, open it (and adjust the
// controlling menu item if necessary)
document.getElementById('sub1').setAttribute('aria-hidden', 'false');
if(window.innerWidth < 480)
document.getElementById('sub-item1').childNodes[0].childNodes[0].data = 'Portfolio ▲';
}
// This prevents the document's root node (i. e. the document object) from
// seeing the event when clicking on the superordinate item for the submenu...
p_event.stopPropagation();
submenu_open = !submenu_open;
}
// Triggered upon clicking anywhere inside of the document...
function CloseMenu(p_event)
{
if(!submenu_open)
return;
document.getElementById('sub1').setAttribute('aria-hidden', 'true');
if(window.innerWidth < 480)
document.getElementById('sub-item1').childNodes[0].childNodes[0].data = 'Portfolio ▼';
submenu_open = false;
}
function CheckWindowSize(p_event)
{
if(window.innerWidth < 480)
{
if(need_mobile)
return;
// On a mobile device, insert the submenu into the main one...
if(submenu_open)
document.getElementById('sub-item1').childNodes[0].childNodes[0].data = 'Portfolio ▲';
else
document.getElementById('sub-item1').childNodes[0].childNodes[0].data = 'Portfolio ▼';
}
else
{
if(!need_mobile)
return;
// If the window is wide enough, we can display the submenu next to the main
// one...
document.getElementById('sub-item1').childNodes[0].childNodes[0].data = 'Portfolio ►';
}
need_mobile = !need_mobile;
}
// Initialization sequence (adds a few event handlers)
document.addEventListener('DOMContentLoaded', function (p_event) {
document.getElementById('sub-item1').addEventListener('click', ToggleMenu, false);
window.addEventListener('resize', CheckWindowSize, false);
document.addEventListener('click', CloseMenu, false);
// If we are on a mobile device, adjust the text of the menu item.
if(window.innerWidth < 480)
{
need_mobile = true;
document.getElementById('sub-item1').childNodes[0].childNodes[0].data = 'Portfolio ▼';
}
}, false);
/* ]]> */
</script>
</head>
<body>
<header><h1>Submenu Test Case</h1></header>
<aside>
<nav class="menu">
<ul>
<li class="menuItem">Home</li>
<li class="menuItem">About</li>
<!-- Assume normal operation here (window width >= 480 pixels) so the
text is set accordingly...
Please note that I have removed some extraneous elements and
attributes. -->
<li class="submenu" id="sub-item1"><span>Portfolio ►</span>
<ul id="sub1" aria-hidden="true">
<li>Landscape</li>
<li>Architecture</li>
<li>Animal</li>
<li>Other</li>
</ul>
</li>
<li class="menuItem">Information</li>
<li class="menuItem">Contact</li>
</ul>
</nav>
</aside>
<main />
</body>
</html>
Please see the annotations in the (X)HTML for details on what's going on there.
By working on this I have discovered that I could greatly simplify the method that I have mentioned yet again so it just boils down to three events:
Resize: Switches the menu layout when the window width undercuts a certain threshold
Mouse click on menu item: Opens or closes the submenu
Mouse click anywhere else: Closes the menu
As for your questions...
ad 1.: I have done a bit of retooling of the CSS that you have provided. I have tossed some definitions out and have tied hiding any elements to the aria-hidden attribute (if that is set to true, the element is not displayed). Said attrtibute also helps a lot in improving accessibility. In this example, if you cannot see it on the screen, a screenreader won't display it, either.
ad 2.: It's rather simple to set up. Just include document.addEventListener('DOMContentLoaded', function (p_event) { }, false);
in the main execution path and add anything that needs to be set up into the function. This is crucial especially for so-called unobtrusive JavaScript (that is, JavaScript that itself attaches hooks to the document where needed instead of hard-coding them into the (X)HTML).
ad 3.: You can get that done with a simple variable (a boolean that indicates whether the menu is open). You can then quickly check on the menu's state without having to query the DOM.
ad 4.: That is extremely tedious and costly at best so handlers are only attached once. The rest should be up to the control logic whether any events are silently ignored (by just returning if certain conditions aren't met).
ad 5.: It takes a handler of the sort that you have implemented, but I have simplified it a bit to avoid calling the DOM where unnecessary (it resorts to the aforementioned flag), plus it also takes into account the window's width for adjusting the text.
ad 6.: innerWidth / innerHeight are numeric values that can easily be returned by the DOM. I don't know about your method, but by my reckon it seems to be a bit expensive, plus when you store the value in a variable, you can perform multiple checks on it (e. g. if you need to check for different widths/heights), which just requires simple comparisons. Your approach would require you to reset the matching condition.
ad 7.: I need to correct myself here, because by chewing on your problem I found that everything (i. e. the third parameter to addEventListener) should be set to false. Otherwise the order of execution is messed up, or some links don't see the event in the first place.
ad 8.: Turned out to be unnecessary as well. I had derived my initial answer from a context menu that I have implemented in JavaScript, but because of its nature I had to resort to these handlers to close it. Here things are a little different so things can be simplified just by omitting these handlers.
ad 9.: You actually have picked the best way here. When implementing a navigation, I'm also using this approach.
I hope I could turn some of your question marks into exclamation marks. However, if you still have questions, by all means, please ask. There's nothing worse than questions left unanswered.
Related
Using the Google Chrome browser, I need to drag-and-drop an item from a menu, in a way so that the menu will automatically close/hide/collapse/disappear/(or something similar) as soon as the dragstart event fires. This has to be done in a way such that the DOM space is freed up, so approaches using "visibility" and "opacity" for instance while possible are not good for this situation.
Instead, it is necessary to do something like display:none or pushing the menu off of the web page (without scrollbar). However, I've gotten stuck trying to accomplish this and could use some help (or if an alternative approach comes to mind that accomplishes the same, please let me know. I also tried a z-index approach without success.):
Approach 1 - Trying to hide dragged item's parent element via absolute positioning
https://jsfiddle.net/gratiafide/4m5r186v/
function dragstart_handler(ev) {
ev.dataTransfer.setData("text/plain", ev.target.id);
ev.currentTarget.parentElement.style.cssText = "position:absolute; right:-5000px;";
}
Approach 2 - Trying to hide dragged item's parent via setting display:none
https://jsfiddle.net/gratiafide/Luj7d089/
function drag(event) {
event.dataTransfer.setData("Text", event.target.id);
document.getElementById('parent').style.display = 'none';
}
You will see in both approaches, the dragged item gets dropped in both instances as soon as the CSS rule gets applied to the dragged item's parent element. I just want to be able to keep dragging the element even though I've hidden or moved the parent element out of sight. Thanks in advance for your help!
You seem to want your parents to disappear by dragging your child's element as it is.
The child element is influenced by the CSS style attribute of the parent element. If parents are erased through css properties such as "display", "visibility", and "opacity", the child element is not visible unconditionally.
Hiding using the "absolute" property(but not z-index -1) is also a way, but unwanted scrollbars may occur depending on the "overflow" attribute of the parent element, and the child element position must be added in reverse and recalculated.
As a result of my test, a dragend event occurred in Chrome when the parent element of the element to be dragged was redrawn. But in Firefox, both of your examples work.
Anyway, to explain based on how it works in Chrome, it is to separate the relationship between Child and Parent and use it as a sibling. Modify your HTML as follows.
<div id='relative_div'>
<div id="parent"></div>
<p id="source" ondragstart="dragstart_handler(event);" draggable="true">Drag me to the Drop Zone below</p>
</div>
Next update your CSS as follows. #parent should serve as a background for filling in #relative_div.
#relative_div {
position: relative;
overflow: hidden;
width: 200px;
height: 100px;
padding: 2em;
}
#parent {
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
background-color: lightgrey;
}
#source {
position: relative;
cursor: grab;
color: blue;
border: 1px solid black;
}
Now, regardless of whether you use #parent's "position" to push it away, or hide it using "display", "opaicty", or "visibility", #source drag does not stop.
ok, I think my comment was wrong and that you want to remove the space on the page occupied by the origin element (rather than freeing up memory).
To achieve this, add document.body.removeChild(document.getElementById('parent')); to your drop handler. I've made a js fiddle to demonstrate (with the id=spacer div removed and an extra paragraph below it to show the element is removed):
https://jsfiddle.net/dj825rbo/
(revision following comment clarifying that the origin element should disappear as the drag begins)
This is horrible, but works (horrible because you can't see the text while it is being dragged). It relies on a hidden element into which the origin's content is stored while the drag is proceeding. Replacing the 'drop' event listener with a 'mouseup' listeners, allows the content of the temp (hidden element to be transferred to the target where the mouse click was released)
https://jsfiddle.net/dj825rbo/1/
When you navigate through form elements or anchors using the tab key (and shift + tab) the browser automatically scrolls to that focused element. If the element is not viewable because it is a part of an overflown content where overflow is set to be hidden, it moves (or scrolls) the content's container to reveal the focused element. I want to either stop or find a way to negate this behavior
Here's something I put together to showcase the issue. I reproduced it in Chrome.
https://jsfiddle.net/charlieko/wLy7vurj/2/
var container = $("#container")
var cur = 0;
function go(increment) {
var next = cur + increment;
if (next < 0) next = 4;
else if (next > 4) next = 0;
cur = next
var newX = cur * 500;
container.css({
transform: 'translate(-' + newX + 'px, 0)'
})
}
$("#left").click(function(e) {
go(-1);
});
$("#right").click(function(e) {
go(1);
});
body {
overflow: hidden;
}
#container {
width: 2600px;
overflow: none;
transition: transform 0.4s;
transform: translate(0, 0);
overflow: hidden;
margin: 0;
}
li {
width: 500px;
text-align: center;
list-style-type: none;
float: left;
margin: 0;
padding: 0;
}
a {
color: black;
font-size: 2.0rem;
}
#ui {
position: fixed;
top: 200px;
}
#ui span {
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
<ul>
<li>Link 1 | ABCD EFG</li>
<li>Link 2 | HIJK LMNO</li>
<li>Link 3 | PQRSTU VW</li>
<li>Link 4 | XYZA BC</li>
<li>Link 5 | DEFG HI</li>
</ul>
</div>
<div id="ui">
<div>
<span id="left">Left</span>
|
<span id="right">Right</span>
</div>
<p>
Use left and right to move. Issue: Use tab key (and shift+tab) to navigate to any of the links. The container of the links shift to show the focused link. Notice the content is decentered when it happens.
</p>
</div>
The issue is that now there are two ways to slide the contents: via interacting with the left|right buttons and via tabbing through the links. When the user chooses to navigate using the tabs it messes up the sliding logic. The content is de-centered, and the index I saved in a variable no longer represents what's visible on the screen. I can handle the accessibility issue programmatically using an onFocus event, so this automatic behavior isn't helping anything.
Is there a way to stop this behavior? I already tried preventDefault() method on onFocus events on the anchor elements.
I was able to figure out a solution. What the browser does is that it scrolls the direct parent of the overflowing content to the position so that the focused element is right in the center. Simply modifying scrollLeft property of the parent element did the trick. So in the onFocus event of the link:
function onFocus (e) {
document.getElementById('content-parent').scrollLeft = 0;
// Code for repositioning the content itself using transform with transition animation
}
Overflow:hidden is usually good for content which is intended to scroll and move, so preventing that will be difficult. If you want the Tab control to stay only on things which are visible (including any buttons or links that update your slider), then you'll need a different method of hiding your content in addition to (or instead of) overflow.
Try display:none on your list items until they are within the open/visible part of div#container. That removes them from the DOM (and therefore from keyboard focus) until you're ready. If you create a class called 'hidden' with just display:none in it, then the only script you'll need is to add/remove the class from the list item when the Left/Right controls are used. I'd edit your code sample to demonstrate but I'm on a tiny screen right now.
The problem then is that your keyboard users can't reach the Left/Right controls. If you change those to button or link elements, then they'll have keyboard support by default in every browser. And then all your users are relying on your Left/Right controls no matter whether they're using a mouse or the keyboard, which gives you more control over how it looks at each stage.
You could just set tabindex to -1 for the links to avoid focusing.
You could set tabindex="-1" for elements that are off the screen. This is suggested by MDN.
https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex
I've created a hidden sidebar navigation menu which, when made visible - moves the site-wrap (main content of the page) to the right to expose the menu:
.nav-trigger:checked + label, .nav-trigger:checked ~ .site-wrap {
left: 16.5em;
}
This all works as I would hope, but the problem is one that arises on mobile, when the user begins trying to swipe around the page. If you touch the left edge of the site wrap and drag it to the left, it scrolls the page in that direction - as if it was dragging the site wrap back across the navigation element behind it.
I have tried adding two variations of overflow hidden to body, but this has no effect:
body{
background: #bodyColor;
color: #headerColor;
font-family: #openSans;
font-size: 16px;
overflow-x: hidden;
overflow: hidden;
}
I did add the following jquery which prevented touch gestures entirely:
var touchDisabled = false;
$("#nav-trigger").click(function(){
if( touchDisabled == false ){
$(document).bind('touchmove', function(e) {
e.preventDefault();
});
touchDisabled = true;
}else{
$(document).unbind('touchmove');
touchDisabled = false;
}
});
but this is not the ideal situation as I'd like to retain vertical scroll if possible, and prevent horizontal scroll/swipe/drag/whatever-you-want-to-call-it.
Part of the reason I'm struggling to solve this is because I'm not entirely sure what to search for, it doesn't seem to be a scroll in the traditional sense, more dragging the div around the page.
The link to demonstrate the problem is:
http://streeten-new.streeten.co.uk/
(obviously only recreatable on mobile). I hope this helps to illustrate the problem as it's not the easiest of things for me to explain in words.
* 12/08 update *
Still having this problem unfortunately.
The problem also manifests itself in both the site-wrap and the .navigation scrolling at the same time as you swipe up on mobile. I would like to be able to tell site-wrap to just stay in place and don't move an inch, no matter how you swipe, and just allow vertical scroll/swipe in the navigation menu.
I've made it so that when you open the menu, overflow: hidden is being added to body and overflow: auto is being added to the navigation. This works perfectly on desktop! When you scroll, only the nav moves and the body is completely frozen. But on mobile it seems to have absolutely no effect.
$("#hamburger").click(toggleMenu);
var menuOpen = false;
function toggleMenu(){
$(".site-wrap, header").toggleClass("slideRight");
$(".navCover").toggleClass("slideRight");
$("#logo").toggleClass("slideLeft");
$("body, #fouc").toggleClass("preventScroll");
$(".navigation").toggleClass("allowScroll");
window.setTimeout(function(){
$("header button").toggleClass("slideLeft");
}, 250);
if (menuOpen == true){
menuOpen = false;
}else{
menuOpen = true;
}
}
.preventScroll{
overflow: hidden;
}
.allowScroll{
overflow: auto;
}
Any help much appreciated.
I have now (mostly) resolved this. I think the edit I made is another issue which I will raise separately.
For the benefit of others who may read this, in order to prevent the site-wrap container from being "swipeable" for want of a better word - whereby it was possible to drag it around the screen in every direction after it had been repositioned on opening the navigation menu - I had to use overflow: hidden
I had initially tried this, but where I went wrong was applying it to the body, which according to this thread doesn't work on mobile:
Overflow-x:hidden doesn't prevent content from overflowing in mobile browsers
I added another div within body, containing all my content and applied overflow: hidden to both body and this new div (belt and braces), which then resolved the issue.
Now when the site-wrap has been shifted to the right after clicking the hamburger icon, it is impossible to drag/swipe it around the screen on mobile.
For a one-page layout website I would need the current section's heading to display in a fixed position on the left side of the screen in order to show the user where he currently is.
The heading will probably have an icon on its left side. I would like the floating heading to be only visible when the user is scrolling on the page, thus disappear when he halts, while the icon stays visible all the time. Is that possible?
This is possible, and most easily done in JQuery. In CSS using
position: fixed;
Will allow you to position a element, then it'll stick where it is on the screen, regardless of the user scrolling up and down the page. Using this JQuery code:
$(window).scroll(function(){
}
Will detect when the user scrolls then will run whatever is inside of the function. If you put this inside of the function:
$("#scrollerbar").css({"display": "block"});
clearTimeout($.data(this, 'scrollTimeout'));
$.data(this, 'scrollTimeout', setTimeout(function() {
$("#scrollerbar").css({"display": "none"});
}, 250));
With this HTML:
<div id="scrollerbar">You're scrolling</div>
And the following CSS:
#scrollerbar{
display: none;
position: fixed;
top: 50px;
left: 0;
}
This will create and position the div scrollerbar 50px down the page and set it to be invisible. Then whenever the user scrolls, it will set the scrollerbar to display: block (which makes it visible). Then stops the timeout "scrollTimeout" (if it's running). Then create the timeout "scrollTimeout" what will wait 250 milliseconds then set scrollerbar to invisible again.
Here's a JSFiddle: http://jsfiddle.net/Xanco/5q6oq8tm/
Please contact me if you have some questions.
EDIT
In order to answer the first part of your question, I've updated the JSFiddle: http://jsfiddle.net/Xanco/5q6oq8tm/2/
The scrollerbar contains a set of list items, each will be bound to a div:
<li id="1read">Reading 1</li>
<li id="2read">Reading 2</li>
<li id="3read">Reading 3</li>
<li id="4read">Reading 4</li>
There's also a new class name:
.active{
font-weight: bold;
}
I've created a function that will remove all "active" class names from the list items in the scrollerbar:
function removeActive(){
$("#1read").removeClass("active");
$("#2read").removeClass("active");
$("#3read").removeClass("active");
$("#4read").removeClass("active");
}
And now whenever the user scrolls, JavaScript will check what the user is currently reading and add the "active" class to the appropriate list items in the scrollerbar:
if ($("#1").is(":hover")) {
removeActive();
$("#1read").addClass("active");
}
if ($("#2").is(":hover")) {
removeActive();
$("#2read").addClass("active");
}
if ($("#3").is(":hover")) {
removeActive();
$("#3read").addClass("active");
}
if ($("#4").is(":hover")) {
removeActive();
$("#4read").addClass("active");
}
EDIT 2
Now, the JavaScript will take the innerText of a child of the hovered div with the ID "articleheader" instead of using a non-standard attribute, as demonstrated by this line of code:
$("#displayaArticleName").text($(this).children("#articleheader")[0].innerText);
Here is the JSfiddle: http://jsfiddle.net/5q6oq8tm/6/
Please note that there are no set of attributes that can only be used, you may use custom attributes, as demonstrated here: http://jsfiddle.net/5q6oq8tm/4/
Is this CSS or javascript? I just need the div to change to display:none if it comes within say 20px of another div. Thanks
Try this
https://github.com/brandonaaron/jquery-overlaps
//Listen to the event that will be triggered on window resize:
window.onresize = function(event)
{
// test if one element overlaps another
if($('#div1').overlaps('#div2'))
{
//Do stuff, like hide one of the overlapping divs
$('#div1').hide();
}
}
Based on your comment:
Yes it is so that if the user makes their browser window small my site
does not look crowded
Instead of answering the question you asked, Here's an answer to the question you didn't ask:
How to resize/position/cssify page elements based on browser size?
There is a new-ish application of css and javascript called Responsive Web Design. Responsive Design allows you to specify different css rules to apply based on different elements. For a great example of this technique, resize your browser around on The Boston Globe's website. They just integrated this technique sometime this week.
Here's an example of the css that would implement this:
#media screen and (min-width: 480px) {
.content {
float: left;
}
.social_icons {
display: none
}
// and so on...
}
example from http://thinkvitamin.com/design/beginners-guide-to-responsive-web-design/
Here is a boilerplate to get you going.
You can add an event handler that gets fired when the window is resized. You could do this with javascript or jquery. jquery makes it easy:
window.onresize = function(event) {
var h=$(window).height();
var w=$(window).width();
if(h<400 && w < 300){
//hide divs
$('#yourdivid1').hide();
}
}
Hope this helps