Okay this is going to be hard to explain. I have a page with two collapsible menus. One is positioned absolutely to the top left. When I collapse it, the remaining content is all squished to the top left, as expected.
The other menu is positioned absolutely to the bottom right. When it’s expanded (default state when loading the page) it sits in the bottom right, 5 pixels away from the bottom and right, as expected. However when I collapse it, all of the sudden the remaining content starts from 5 pixels away from bottom and right, and then flows off the page both to the right and below, expanding the page and causing scrollbars.
The desired behavior is for the remaining content to be squished into the bottom right of the page, without changing the page dimensions.
It’s going to be tricky to post my code, as a lot of it is generated dynamically via JavaScript.
Each menu consists of two child divs inside a container div. The container div is positioned absolutely (top left or bottom right, depending on which menu). The first child div is the content of the active menu tab, floated left and with a margin-top just tall enough to put it under the menu tabs. The second child div is the menu tabs. This div is positioned absolutely (so as to let the content div flow behind it). Each tab inside the tab div is floated left, so I can add more dynamically.
One of the tabs is always the “hide/show” tab, and basically just toggles display:hidden on the menu’s content div.
So, as I understand it, somehow the floated content div keeps the menu from flowing off the page, and when it’s “collapsed” (i.e. hidden), there’s nothing to keep the absolutely positioned tab div from flowing off the page.
I guess I will attempt to rip out the offending div and css code into it’s own page so I can isolate the behavior, and post some coherent code. In the meantime any suggestions are quite welcome.
Thanks!
== Matt
P.S. Normally I would have just made everything in the menu positioned relatively. The reason I went with an absolutely positioned div on top of a floated content div is so I can control whether or not the bottom of the active tab looks “connected” to the content div. If I had both divs relative and just had the tab div sitting on top of the content div, I have no way of removing the content div’s black top border in just the right place to make it look like the active tab is connected to it. If someone can think of a way around this while still keeping both divs relative, I’d be down for that too.
I don’t have the rep to post images, so here are some links:
Here’s what the menu’s look like expanded:
http://theroach.net/igp_menutest/css_menus1.png
Here they are collapsed:
http://theroach.net/igp_menutest/css_menus2.png
Here is what I’m going for:
http://theroach.net/igp_menutest/css_menus3.png
UPDATE: I’ve stripped out the menu code from my JavaScript as much as possible. Here is a JSFiddle with the working code. For some reason, the onclick events aren’t working inside the JSFiddle, but it’s the exact same code from my test page, so if you can’t get it to work in the JSFiddle, try this link to see the behavior. FYI, the javascript doesn’t normally rely on giant if-else statements, I just did that so I wouldn’t have to post all of the dynamic menu generation code.
P.P.S. I’ve basically only been testing this in Chrome v20, although I just tested Firefox v13 and IE9 and got the same behavior. I don’t care much about cross browser support. This page is being designed only for people using the latest and greatest browsers.
UPDATE2: Updated links. Added relevant portion of jsfiddle code to satisfy new code-in-question requirement:
JS
function tab(id) {
if(id == 'menuCtrlTab1') {
toggle('menuCtrlTab1');
toggle('menuCtrlTab2');
hide('menuCtrlForm2');
show('menuCtrlForm1');
}
else if(id == 'menuCtrlTab2') {
toggle('menuCtrlTab1');
toggle('menuCtrlTab2');
hide('menuCtrlForm1');
show('menuCtrlForm2');
}
else if(id == 'menuCtrlTabHide') {
hide('menuCtrlTab1');
hide('menuCtrlTab2');
hide('menuCtrlFormDiv');
hide('menuCtrlTabHide');
show('menuCtrlTabShow');
}
else if(id == 'menuCtrlTabShow') {
show('menuCtrlTab1');
show('menuCtrlTab2');
show('menuCtrlFormDiv');
hide('menuCtrlTabShow');
show('menuCtrlTabHide');
}
else if(id == 'menuInfoTab1') {
toggle('menuInfoTab1');
toggle('menuInfoTab2');
hide('menuInfoForm2');
show('menuInfoForm1');
}
else if(id == 'menuInfoTab2') {
toggle('menuInfoTab1');
toggle('menuInfoTab2');
hide('menuInfoForm1');
show('menuInfoForm2');
}
else if(id == 'menuInfoTabHide') {
hide('menuInfoTab1');
hide('menuInfoTab2');
hide('menuInfoFormDiv');
hide('menuInfoTabHide');
show('menuInfoTabShow');
}
else if(id == 'menuInfoTabShow') {
show('menuInfoTab1');
show('menuInfoTab2');
show('menuInfoFormDiv');
hide('menuInfoTabShow');
show('menuInfoTabHide');
}
else {
}
}
function toggle(id) {
if(activated(id)) {
deactivate(id);
}
else {
activate(id);
}
}
function hide(id) {
docAddClass(id, 'hidden');
}
function show(id) {
docRemoveClass(id, 'hidden');
}
function activate(id) {
docRemoveClass(id, 'inActive');
docAddClass(id, 'active');
}
function deactivate(id) {
docRemoveClass(id, 'active');
docAddClass(id, 'inActive');
}
function activated(id) {
var e = docGet(id);
if(e.className.search('active') == -1) {
return false;
}
return true;
}
function docGet(id) {
return document.getElementById(id);
}
function docAddClass(id, classToAdd) {
var e = docGet(id);
if(e.className.length <= 0) {
e.className = classToAdd;
}
else {
if(e.className.search(classToAdd) == -1) {
e.className = e.className + ' ' + classToAdd;
}
}
}
function docRemoveClass(id, classToRem) {
var e = docGet(id);
if(e.className.length > 0) {
if(e.className.search(classToRem) != -1) {
e.className = e.className.replace(classToRem, "");
}
}
}
HTML
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<meta name='Author' content='Matt Seng' />
<meta name="Description" content="IGP" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet" type="text/css" href="./style.css" media="screen" />
</head>
<body>
<div id="menuDiv">
<div id="menuCtrl">
<div id="menuCtrlWrapper" class="menuWrapper">
<div id='menuCtrlFormDiv'>
<div id="menuCtrlForm1" class="menuForm">
Tab 1 contents<br>
Lorem ipsum dolor sit amet, consectetur<br>
adipiscing elit. Duis est orci, malesuada<br>
vitae pulvinar nec, varius id felis. Vivamus<br>
et accumsan dui. Donec a nisl id dui gravida<br>
porttitor. Integer sed turpis arcu. Curabitur<br>
nec dolor urna, ac molestie neque. Nunc ac<br>
augue non mi imperdiet semper.
</div>
<div id="menuCtrlForm2" class="menuForm hidden">
Tab 2 contents<br>
Lorem ipsum dolor sit amet, consectetur<br>
adipiscing elit. Duis est orci, malesuada<br>
vitae pulvinar nec, varius id felis. Vivamus<br>
et accumsan dui. Donec a nisl id dui gravida<br>
porttitor. Integer sed turpis arcu. Curabitur<br>
nec dolor urna, ac molestie neque. Nunc ac<br>
augue non mi imperdiet semper.
</div>
</div>
<div id="menuCtrlTabs" class="menuTabs">
<div id="menuCtrlTabShow" class="clickable tab showHide inActive hidden" onclick="tab(this.id);">
Show
</div>
<div id="menuCtrlTabHide" class="clickable tab showHide inActive" onclick="tab(this.id);">
Hide
</div>
<div id="menuCtrlTab1" class="clickable tab secondary active" onclick="tab(this.id);">
1
</div>
<div id="menuCtrlTab2" class="clickable tab secondary inActive" onclick="tab(this.id);">
2
</div>
</div>
</div>
</div>
<div id="menuInfo">
<div id="menuInfoWrapper" class="menuWrapper">
<div id='menuInfoFormDiv'>
<div id="menuInfoForm1" class="menuForm">
Tab 1 contents<br>
Lorem ipsum dolor sit amet, consectetur<br>
adipiscing elit. Duis est orci, malesuada<br>
vitae pulvinar nec, varius id felis. Vivamus<br>
et accumsan dui. Donec a nisl id dui gravida<br>
porttitor. Integer sed turpis arcu. Curabitur<br>
nec dolor urna, ac molestie neque. Nunc ac<br>
augue non mi imperdiet semper.
</div>
<div id="menuInfoForm2" class="menuForm hidden">
Tab 2 contents<br>
Lorem ipsum dolor sit amet, consectetur<br>
adipiscing elit. Duis est orci, malesuada<br>
vitae pulvinar nec, varius id felis. Vivamus<br>
et accumsan dui. Donec a nisl id dui gravida<br>
porttitor. Integer sed turpis arcu. Curabitur<br>
nec dolor urna, ac molestie neque. Nunc ac<br>
augue non mi imperdiet semper.
</div>
</div>
<div id="menuInfoTabs" class="menuTabs">
<div id="menuInfoTabShow" class="clickable tab showHide inActive hidden" onclick="tab(this.id);">
Show
</div>
<div id="menuInfoTabHide" class="clickable tab showHide inActive" onclick="tab(this.id);">
Hide
</div>
<div id="menuInfoTab1" class="clickable tab secondary active" onclick="tab(this.id);">
1
</div>
<div id="menuInfoTab2" class="clickable tab secondary inActive" onclick="tab(this.id);">
2
</div>
</div>
</div>
</div>
</div>
<script type='text/javascript' src='./script.js'></script>
</body>
</html>
CSS
/* removes the top and left whitespace */
* { margin:0; padding:0; }
/* ensure full screen */
html, body {
width:100%;
height:100%;
font-family: "Courier New", Courier, monospace;
font-size: 95%;
}
/* remove the scrollbars */
canvas {
display:block;
}
#menuCtrl {
position: absolute;
margin: 5px;
}
#menuInfo {
position: absolute;
bottom: 0;
right: 0;
margin: 5px;
}
.menuWrapper {
}
.menuForm {
float: left;
margin-top: 22px;
padding: 5px;
background-color: white;
border: 2px solid black;
border-radius: 10px;
border-top-left-radius: 0;
box-shadow: 3px 3px 5px #333;
}
.menuForm table {
padding-top: 3px;
}
.menuForm td, th {
white-space: nowrap;
}
.menuForm th {
text-align: left;
}
.menuTabs {
position: absolute;
white-space: nowrap;
top: 0;
}
.menuTabs div.tab {
float: left;
height: 20px;
min-width: 20px;
margin: 0;
padding: 0 5px 0 5px;
text-align: center;
background-color: white;
border: 2px solid black;
border-top-left-radius: 5px;
border-top-right-radius: 5px;
}
.menuTabs div.secondary {
border-left: 0px;
}
.menuTabs div.active {
opacity: 1;
border-bottom: 2px solid white;
}
.menuTabs div.active.showHide {
border-bottom: 2px solid black;
}
.menuTabs div.inActive {
opacity: .75;
border-bottom: 2px solid black;
}
.clickable {
cursor: pointer;
}
.visible {
text-decoration: underline;
text-decoration-color: black;
}
.invisible {
text-decoration: line-through;
text-decoration-color: red;
}
.hidden {
display: none;
}
Please try the following: http://jsfiddle.net/bQ6vZ/1/.
Is that performing as you desire?
I added the following CSS rules:
And added two lines to the JS, namely the
hide('menuInfoWrapper');andshow('menuInfoWrapper');lines seen below:Hope this helps.