Detect overflow when overflow set to hidden - javascript

I have an interesting problem.
Background: I have a simple header. A logo and two links are floated on the left side, while two drop down menu links are floated on the right, all contained in a header div that i 100% width. If I shrink the screen horizontally enough the two drop down menu links dropped below the left-floated elements (of course). After doing some research I decided to use overflow: hidden on the parent header div so that the two drop-down menus would disappear instead of dropping to the next line. This solution works great in my situation. However, I found that the drop-down menu layer was cut off below the header because of the overflow:hidden solution. Just for reference, my drop down menu was created using simple javascript that toggles between css classes to get the drop down effect. I simply added a line to the function onclick events in the javascript that when a menu link is clicked on, overflow changes from overflow:hidden to overflow: none (and of course toggles back to hidden when the menu is unclicked), which works great because there is supposed to never be overflow if the menu buttons are visible (they disappear and are hidden when there is overflow,).
Problem: If a user opens a menu (aka clicks on a drop down menu link) and THEN shrinks the horizontal scrollbar without first closing the menu, the header has an overflow that is still set to none because the user hasn't toggled the header back to hidden because the menu is still open. Thus, my original problem of the two menu links dropping beneath the floated left divs again. Working with what I'm already doing, I'm trying to come up with some kind of onchange() event in the header that will detect when there is overflow, even though overflow is set to hidden. Any thoughts?
Relevant CSS Code:
.level1raise { //header class
background: #F8F8F8;
margin: 0px;
border-bottom: 1px solid #BCD2EE;
height: 55px;
overflow: hidden;
}
.level1drop { //alternate header class
background: #F8F8F8;
margin: 0px;
border-bottom: 1px solid #BCD2EE;
height: 55px;
overflow: none;
}
Sample of Javascript that toggles menu:
function supportdrop() {
if (document.getElementById("support").className == "hidesupportmenu") {
document.getElementById("support").className = "showsupportmenu";
document.getElementById("supportdrop").className = "supportmenuheadclicked";
document.getElementById("supportarrow").className = "uparrowimage";
document.getElementById("help").className = "hidehelpmenu";
document.getElementById("helpdrop").className = "helpmenuhead";
document.getElementById("helparrow").className = "downarrowimage"; //^THESE DEAL WITH MENU
document.getElementById("level1").className = "level1drop"; //THIS IS THE HEADER TOGGLE
} else if (document.getElementById("support").className == "showsupportmenu") {
document.getElementById("support").className = "hidesupportmenu";
document.getElementById("supportdrop").className = "supportmenuhead";
document.getElementById("supportarrow").className = "downarrowimage"; //^MENU
document.getElementById("level1").className = "level1raise"; //HEADER TOGGLE
}
}
If you need me to post more code I will, but I think what I've included kind of shows what I'm doing, let me know otherwise. I'd post an attempted solution, but I'm not really sure what solution to attempt. I'm trying to avoid JQuery. Thanks!

I came up with a solution for any others who are attempting a similar path. Because (1) I use 100% width of the page and the page is dynamic I can disable the horizontal scrollbar and (2) the width of the elements inside the header don't change so I can add up the minimum-required width before the drop down menu links drop to the next line, I can use the following solution:
HTML:
<body onresize="checkwidth()">
Javascript:
function checkwidth() {
var currentwidth = window.innerWidth || document.documentElement.clientWidth ||
document.body.clientWidth;
if (currentwidth < 770) {
document.getElementById("level1").className = "level1raise";
document.getElementById("help").className = "hidehelpmenu";
document.getElementById("helpdrop").className = "helpmenuhead";
document.getElementById("helparrow").className = "downarrowimage";
document.getElementById("support").className = "hidesupportmenu";
document.getElementById("supportdrop").className = "supportmenuhead";
document.getElementById("supportarrow").className = "downarrowimage";
} else {
document.getElementById("level1").className = "level1drop";
}
}
Works beautifully and is cross-browser. A little crude, but oh well.

Related

Resize content when drawer is open in MDL

I'm building a website based on MDL. What I'm trying to achieve is that the drawer doesn't open over the content, but open next to it. I managed to disable the obfuscator and modify the top value.
However, the way I was going to do this is anytime the drawer opens the content area would get a 250px wide left margin (the drawer is 250px wide) and resize its width so that width: calc(100% - 250px). This works just fine, but I don't know if this is the best way to do it, and even if it is, I don't know how to track the state of the drawer.
Here's how the material.js handles the change:
MaterialLayout.prototype.screenSizeHandler_ = function () {
if (this.screenSizeMediaQuery_.matches) {
this.element_.classList.add(this.CssClasses_.IS_SMALL_SCREEN);
} else {
this.element_.classList.remove(this.CssClasses_.IS_SMALL_SCREEN);
// Collapse drawer (if any) when moving to a large screen size.
if (this.drawer_) {
this.drawer_.classList.remove(this.CssClasses_.IS_DRAWER_OPEN);
this.obfuscator_.classList.remove(this.CssClasses_.IS_DRAWER_OPEN);
}
}
};
This is beyond my skills to figure out what is actually going on. I tried tracking it down with Chrome, but it was too complicated.
Is there a trivial way to do this? If not, how do I edit the script?
Cheers!
The .mdl-layout__drawer receives a .is-visible class when it is open/visible.
This small CSS-Rule worked for me:
.mdl-layout__drawer.is-visible ~ .mdl-layout__content {
padding-left: 250px;
}
With this you also don't need to fix the width of the content-area, as you are not using margin but padding. Note that by default the material.css also disables scrolling when the drawer is visible, so you also need to add the overflow-property to the rule:
.mdl-layout__drawer.is-visible ~ .mdl-layout__content {
overflow: auto !important;
padding-left: 250px;
}

How to prevent swipe after an element has been repositioned by a transition

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.

How to use angularjs $anchorScroll on div only if div is hidden?

I'm using angularjs to develop a web application. I have several nested div. Each of them correspond to an item that the user can select.
A good example of my div display is in the official angularJs documentation :
http://plnkr.co/edit/qncMfyJpuP2r0VUz0ax8?p=preview
In my code each div have a ng-click="gotoAnchor(x)" event so when I click on a div if it is partially hidden, it pull it up on the page and the user can see all the clicked div.
But I have a header in my page so the first div with an anchor and a click event is not directly at the top of the page. And if I click on the first div, it will scroll and the header won't be visible.
So my question is, is there a way to activate the anchor only if the div isn't fully displayed on the screen ?
If you have an other solution than anchors, I take it.
Thank you in advance.
If I understand your question correctly the issue is that when using $anchorScroll your header is either
a: Being covered up by the div scrolled into frame,
or
b Partially covering up the div that is scrolled into frame.
Either way there are two solutions you should review:
First
make sure you're employing CSS to properly layer your elements, your header (if fixed) should have a z-index that supersedes your divs.
.header { position: fixed; top:0; width: 100%; z-index: 99}
.content { position: relative; margin-top: 10px; z-index: 1;}
REMEMBER Z-index only works on positional elements (See ref)
Second
Employ $anchorScroll.yOffset to make sure your scroll distance is bumped down to compensate for the header height. As seen in the Angular docs, you can use this method in your application:
.run(['$anchorScroll', function($anchorScroll) {
$anchorScroll.yOffset = 50; // always scroll by 50 extra pixels
}])
Update 50 to be the pixel height of your header.
Regarding visibility
There are a few great libraries and directives for checking the visibility of an element - try https://github.com/thenikso/angular-inview as you can specify whether you want to enable an action when only the top, bottom or none of the div is visible.
Note Posistioning the first div correctly on the page will prevent any scroll from being necessary as seen in this plunkr.

div (menu) not pushing div (maincontent)

For a website i'm making I have a little problem. I have a mobile menu which activates when I press the menu button (done with javascript).
I want it to push the div with the 3 blocks (the maincontent div) down, but sadly it's not doing what it's supposed to.
I have tried everything with positions and so on, without success. You can check out the website at dev.hotelkom.nl
It's not working because your main menu is positioned absolutely and its parent has a fixed height. Also your wrapper-content is positioned absolutely hence it's not moving.
Few reasons how you may fix it:
.mainmenu {
position: relative;
height: auto;
}
.wrapper-content {
position:relative;
}
Apply these properties on mobile.

Javascript height to impact content not just div

I am working on a form on a webpage. I want to have a button on a panel which when pressed expands a div (underneath the button) to make it visible and then invisible again when the button is pressed again - a kind of further details popout box. So far i have got this:
function blockappear() {
var ourblock = document.getElementById("theblock");
ourblock.style.transition = "all 2s";
if (ourblock.style.height == "0px") {
ourblock.style.height = "220px";
} else {
ourblock.style.height = "0px";
}
}
and this:
#theblock {
background-color: #a83455;
height: 220px;
width: 100%;
padding: 0;
margin: 0;
display: block;
}
and this:
<p><button type="button" onclick="blockappear()">Try it</button></p>
<div id="theblock">
Some text
</div>
And it seems to work which is quite pleasing (even though it has taken hours to get this far). The problem is this. I want the div to change from 200px to 0px including the contents not just to the extent it can according to the contents. At the moment the div shrinks, but the content "some text" stays put on the page. I have tried changing the display attribute of the div to 'block' and 'table' and still no joy. I thought that the point of a div was that it enclosed the content with the group tags and that the content could not exist without the div. If the div has 0px height how can the text still show?
Incidentally, if i just use display:none; on the div it works (without the transition of course). I need the content of the div to respond to the height of the div somehow - i suspect using the css properly.
I think this has been covered before by using jquery, but i want to use javascript now that i have started as it will probably take me another few hours if i start again with a whole new language :-)
Thanks for any help...
Add overflow: hidden; to your div. This will hide the content which doesn't fit into the container.
You want to use this CSS property on your div:
overflow: hidden;
This will make any content of #theblock bigger than #theblock itself invisible. So - if #theblock has height of 0px - all of its contents will be hidden.
Default value is overflow: visible;, so even content bigger than containing element itself will still be there for all to see. That's all there is to it.
Read more: overflow CSS property (MDN)

Categories