How to reposition CSS-hover popups to stay within a fixed frame? - javascript

I have a page filled with many fixed-size boxes in a grid layout (div's simply piled up with float:left). On hovering the mouse on any of them, a 'popup' - larger div with the same and also additional info is shown over it, as if the box expanded in all directions (but not moving the other boxes, it's shown also over them). Simplified html/css below. It's like thumbnails/full images, but the actual content is a pile of various html data, including links, etc.
The problem is that in this way the 'popup' div for the leftmost/rightmost boxes goes over the screen, triggering the scrollbar; or they are cut off if I don't allow the overflow.
I would like instead to reposition these popups to left/right so that they stay within the total borders. How to approach this need?
I can't do this server-side as the server does not know which boxes will be rightmost/leftmost - it depends on window size, how many columns will fit there. My first idea is to use javascript to change the positioning for all the popups right after the page is loaded, but I don't know how to a) find out which popups would be sticking out of the frame; and even b) find out the size of the popups, since they are hidden normally, which means width=height=0 until they are shown.
Perhaps a completely different approach of showing these popups would be easier than repositioning the div's that I currently have?
Currently Prototype/scriptaculous is used at some other pages, the server side is ruby on rails.
<div class="frame">
<div class="box", id="object123" >
small, fixed size content here
<div class="popup">
large, variable size/width/height content here that describes object123
</div>
</div>
<div class="box", id="object456" >
small, fixed size content here
<div class="popup">
large, variable size/width/height content here that describes object456
</div>
</div>
... many other similar boxes.
</div>
div.frame {
overflow: hidden;
}
div.box {
border:1px solid #efe9dc;
margin:5px;
position:relative;
float:left;
height:70px;
width:150px;
}
div.popup {
min-width:200px;
display:none;
position:absolute;
left:-30px;
top:-30px;
z-index:1000;
}
div.box:hover .popup { display: block; }

right now your div.popup is positioned absolute to div.box; if you removed the position from div.box and put it on div.frame, the popups would be absolute to the frame. you can then set left/top/right/bottom to be offset from the frame's edges instead.
i hope this helped :)

In the end this is what I did.
I replaced the popups with css+jquery script that expands the content box larger/above the normal grid; centers the 'popup' over the place of the original box, and if it goes over the sides, then adjusts the position.
As a bonus, the functionality works on everything that I tag with the 'expands' 'expand_show' 'expand_hide' classes, so no duplication as it is applied in several places.
sample html
<div class="box_grid expands">
<div class="box_content">
basic content that's always visible
<p class="expand_hide>short content summary shown in the small boxes</p>
<p class="expand_show> detailed content</p>
<div class="expand_show> detailed extra content</div>
</div>
</div>
css and javascript to show it
div.box_grid {
margin:5px;
float:left;
height:80px;
width:170px;
}
div.expanded { position:relative; }
div.expanded > * {
position:absolute;
width:auto;
height:auto;
z-index:1000;
min-width:100%;
min-height:100%;
}
div.expands .expand_show { display:none; }
div.expanded .expand_show { display: block; }
div.expanded .expand_hide { display: none; }
$(document).ready(function(){
$('.expands').hover(
function(){
grid = $(this);
expanded = grid.children();
border = $('.content_borders');
grid.addClass('expanded');
var top = (grid.outerHeight() - expanded.outerHeight())/2;
var left = (grid.outerWidth() - expanded.outerWidth())/2;
var left_limit = border.offset().left + 5 - grid.offset().left;
var right_limit = border.offset().left + border.outerWidth() - expanded.outerWidth() - 5 - grid.offset().left;
var bottom_limit = border.offset().top + border.outerHeight() - expanded.outerHeight() - 5 - grid.offset().top;
if (left < left_limit) { left = left_limit }
if (left > right_limit) { left = right_limit }
if (top > bottom_limit) { top = bottom_limit }
expanded.css('top',top);
expanded.css('left',left);
},
function(){ $(this).removeClass('expanded') }
);
});

As my understanding you have multiple small divs which ave the thumbnails and you have a div to sow large content for each image.
So for each image there are two divs.
Tats why you are having difficulty for each div.some will be left , some center , some on right.
Instead of that , use a common div to show large content for all the smaller div.
Pass a parameter on hover and show the content in that div using server side code.
That means your style is fine , you just position only one div in center by using
left:100px
top:100px
you modify it as you want. Put large content in that single div for all smaller divs
Use Firefox Firebug for better understanding of position

Related

Scroll vertically with fixed columns

I have a fixed-size container with dynamic content. The content is a series of items of varying heights. I want the items to flow vertically (each visually beneath the previous), but be able to inject a column break on a particular item. I use JavaScript to inject the column breaks, and thus know how many total columns are needed, and thus can inject the total column count somewhere (if helpful).
Here's what I had been using that I thought used to work in Chrome. The desire is to have A1-A5 in one column, and B1-B2 in a second column. The entire section should scroll vertically, not horizontally.
section { width:400px; height:300px; font:9pt sans-serif; overflow:auto }
div { margin-bottom:1em; -webkit-column-break-inside:avoid }
h3 { margin:0; background:#000; color:#fff; padding:4px; font-size:9pt }
span { display:block; height:45px; background:#ddd; padding:4px }
/* The following are injected by JavaScript */
section { -webkit-column-count:2 }
#B1 { -webkit-column-break-before:always }
<section>
<div id="A1"><h3>A1</h3><span>content</span></div>
<div id="A2"><h3>A2</h3><span>content</span></div>
<div id="A3"><h3>A3</h3><span>content</span></div>
<div id="A4"><h3>A4</h3><span>content</span></div>
<div id="A5"><h3>A5</h3><span>content</span></div>
<div id="B1"><h3>B1</h3><span>content</span></div>
<div id="B2"><h3>B2</h3><span>content</span></div>
</section>
As seen in Chrome, the above snippet wraps A4 onto a second column and creates three columns scrolling horizontally. How can I achieve my desire of two columns, scrolling vertically?
It is easy for me to change the global CSS, and to apply new custom CSS to each <div> with JavaScript, but (for complex reasons) it is hard for me to modify the DOM using JavaScript. I'd prefer a solution that does not modify the DOM.
I believe the problem you're having it to do with defining the height of the "section" element in the first css block. Make it so:
section { width:400px; height:auto; font:9pt sans-serif; overflow:auto }
Everything should be fine with that change. jsfiddle here
You will lose the fixed size though. I couldn't find a configuration that didn't fail this requirement.

How to adjust height of a HTML element to cover all free spaces of it's parent?

Suppose we have a DIV element like this:
<div id='parent'>
<!-- The childs will come here -->
<div id='footer'>This is footer</div>
</div>
and this function that create HTML elements dynamically and inserts them into the div#parent
function addChild(name)
{
$("<div></div>").text(name).prependTo( $("div#parent") );
}
CSS:
div#parent
{
height:400px;
background-color:yellow;
}
div#footer
{
/* height: ??? */
background-color:red;
}
Now I want, the element div#footer covers whole available/remaining height of the element div#parent, How I can do this by CSS or Javascript?
Thanks
Another solution using CSS. The solution here is using display:table and display:table-row
div#parent
{
display:table;
height:400px;
width:100%;
background-color:yellow;
}
div{
display:table-row;
height:20px;
}
div#footer
{
/* height: ??? */
background-color:red;
height:auto;
}
http://jsfiddle.net/aawbE/
If you simply want the footer to always be at the bottom of the page, then I would suggest checking out http://www.cssstickyfooter.com/. They have a great concept for making sure that the footer will either be at the end of the content, or touch the bottom of the page.
Example
If you want the footer to cover the entire bottom portion of the screen (beginning where the content ends and ending at the bottom of the screen) then you do need to know the total height being used by all of the elements inside of the "container" element as well as the height of the "container" element.
An easy way to do this is to put all child elements into a different div (the height of which you can easily track.
//find the difference in height between the
//"parent" div (minimum of 100% of page height) and
//the "main" div (the total height of its child elements)
height = document.getElementById('parent').offsetHeight -
document.getElementById('main').offsetHeight;
//Set the top margin of footer to minus the height
//(make footer go up 'height' number of pixels
document.getElementById('footer').style.marginTop = -height+'px';
//Set the height of the footer to 'height'
document.getElementById('footer').style.height = height+'px';
It's important to note that these calculations are based off of the cssStickyFooter code. This makes sure that the bottom of the footer remains at the bottom of the screen (unless it passes the bottom of the screen).
Example
For this example I added a green border around the 'main' div so that you can see where it ends. I also make sure to change the footer whenever the page is re-sized in case the child elements move around (re-size the page to see this happen). I also added a min-height to the footer so there will still be a footer even if #main.height >= #parent.height.
I hope this helps.

How to Click a div and have it change dimensions of other divs and then change back once clicked again

I am trying to do a basic div layout and would like to use plain javascript or jquery to mimic the functionality on this page
http://octopress.org/blog/archives/
There is a content wrapper div and a left article column and a right sidebar column. There is also a skinny div in-between the left and right div that can be clicked on, once clicked on, it either closes or expands the right side div.
The page flow...
1) On page load the right side div should be open.
2)
Once you click the middle div it closes the right side div and expands the left side div's width to cover the space of the left + right side div. The middle div still is visibable, so you can click it again to expand the div back out
3) Also once you click the middle div to collaps the right side div, it collapses it, but it also puts the contents of that div, underneith the left main column div. Like the right side div I think has a float:left valuse so once the left div is expanded, it will push that div down underneith the left div
4) With right side div collapsed, you can click the middle div which is now hugging the right side border of the main div wrapper, it will then resive the left div back down small to allow the right div to fit back into place again
It probably sounds more complicated then it is to describe what I am looking to do, if you view the link though http://octopress.org/blog/archives/ it does exactly what I am talking about.
I have tried disecting the page and rebuilding just the part I am after without any luck, I would really appreciate any help in a doing this with jquery, as well as how to do the css for the divs.
I have seen some plugins that do similar work but not the same, please help if you can
Here are some screen shots of the different phases I am after...
I appears that I just need to have the javascript add and remove some css rules when the middle div is clicked.
the key for the layout is to use negative margin on the sidebar.
You could see the simplified layout example here:
http://jsfiddle.net/9FUQA/
The html
<div id="wrapper">
<div id="content">
<div class="left_column"></div>
<div class="right_column"></div>
<span class="toggle_sidebar"></span>
</div>
</div>
The CSS. First you float both column, and you set the width on the right column and a 100% nagetive margin-right to bring the right column onto the same line as the left-column.
On collapse, you remove both the float and negative margin-right on right-column, and it falls into the normal block flow.
#content {
width:500px;
margin-right:200px;
position:relative;
}
.left_column {
width:100%;
float:left;
}
.right_column {
width:160px;
padding:0 20px;
margin:0 -100% 0 0;
float:left;
}
.toggle_sidebar {
position:absolute;
top:0;
bottom:0;
right:-10px;
}
.collapse .right_column {
float: none;
width: auto;
clear: left;
margin: 0;
}
.collapse #content {
margin-right:20px;
}
.collapse .toggle_sidebar {
right: -20px;
width: 19px;
}
The JS
$(document).ready(function () {
$('.toggle_sidebar').click(function(event) {
$('#wrapper').toggleClass('collapse');
});
});
You could see the simplified layout example here:
http://jsfiddle.net/9FUQA/
Load jQuery 1.7...
$('#left-div').click(function () {
$('left-div').animate({
width: 99%,
}, 5000, function() {
});
});
$('#right-div').click(function () {
$('right-div').animate({
width: 400px,
}, 5000, function() {
});
});
Something like that. Might have to tweak it for your css though.

How to create a table-like CSS layout with DIVs?

UPDATE 2
I found a tentative solution that currently works for me in Chrome on Mac OS X. You can check out my answer below for details. For those of you who are still trying to come up with CSS only solutions or JavaScript solutions, please keep going and let me know what you come up with! Please :)
UPDATE
The answer below is really close to an all CSS solution, so I'm going to try to make it work. In the meantime, I'm opening up this question to JavaScript solutions as well. How would you do it using JavaScript? All solutions are now welcome :)
Let's see if we can solve this one together!
I'm trying to set up a layout, check out the image...
I'm using the "sticky footer" technique, which works great, and I've set it up so that whenever one of the two columns gets taller, the other will also match its height, as described in this article. The problem, however, is that these two columns don't reach the footer naturally... I'm forcing the height through JavaScript.
Anyway, all the relevant code can be seen in the fiddle...
CODE
http://jsfiddle.net/UnsungHero97/XrJMa/embedded/result/
QUESTIONS
First big problem: how can I set it up so that the height of these columns reaches the footer below? I want it so that when the page loads, both pink and blue columns reach the bottom automatically.
How can I get it so that when the pink column grows beyond its current height, a local scrollbar appears, but when the blue column grows beyond its current height, the overall page scrollbar appears and the footer is pushed down?
- basically, I want the height of the pink and blue columns to ALWAYS be the same height but the height is only determined by the blue column; blue is dominant so it can expand the height of both columns; pink cannot expand the height, just be at the same height as blue
Can this functionality be achieved using only CSS?
Let me know if I need to clarify anything.
There were many issues, so I rewrote it. I have created exactly what you want. Enjoy. =)
http://jsfiddle.net/hRkx8/53/
The trick is to have your main region have a margin-bottom the same height as your footer (which you absolutely position). Thus as your blue thing gets larger, it will start pushing the bottom of the page a bit earlier than it normally would.
(edit: this version moves the footer, which is more difficult to do; however the question asked that the blue area be initialized to be as large as possible, see below for one way to do this)
Here we go! Unfortunately I have to include it inline, since jsfiddle has some severe bugs that prevent proper display. This version has the blue area start all the way at the bottom.
absolutely-positioned elements seem to have some trouble automatically scrolling as the page gets bigger, so I created a dummy #main div much like you did and had it fill the entire viewport, then inside that is both the #footer and #content (your blue and red stuff). The #footer is absolutely positioned so it takes up no space / the document doesn't care about it. As the #content expands, the #main container expands with it, dragging the footer along. The use of a margin-bottom is necessary to prevent the footer from hiding text.
The actual amount of CSS required to do this is, if you remove the demo stuff, just about 5 lines and dummy element.
<html>
<head>
<style>
body {
margin:0; padding:0;
}
* { /* just for demonstration */
box-sizing:border-box;
padding:5px;
border:1px dashed red;
-webkit-border-radius:10px; -moz-border-radius:10px;
background-color:hsla(0,50%,50%, 0.1);
}
/*important to use min-height not height*/
#main {
position:relative; width:100%; min-height:100%;
border:3px solid green;
}
#footer {
position:absolute;
left:0px; right:0px; bottom:0px; height:5em; /*can be anything*/
background-color:lightgrey;
}
#content {
position:relative;
box-sizing:border-box;
background-color:skyblue;
margin-left:auto; margin-right:auto;
padding-bottom:5em; /*must be same as #footer's height*/
margin-top:10%; /*browser bug: actually acts like 20%*/
width:50%;
min-height:80%; /*should equal 100%-marginTop*/
border:3px solid blue;
}
/* dependent elements */
#sidebar {
position:absolute;
top:0px; bottom:0px;
right:100%; width:7em;
background-color:pink;
overflow-y:scroll;
}
#topbar {
position:absolute;
bottom:100%; height:3em;
right:-10%; left:10%;
}
</style>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"></script>
<script>
setTimeout("$('pre').animate({height:1500}, 3000)", 1000);
</script>
</head>
<body>
<div id="everything">
<div id="main">
<div id="content">
<div id="sidebar">
alpha
<br/>
beta
<br/>
gamma
<br/>
etc.
</div>
<div id="topbar">
Menu1 * Menu2 * Menu3 * ...
</div>
This is my site.
Yay.
<pre>
etc.
etc.
etc.
etc.
etc.
etc.
etc.
etc.
etc.
etc.
etc.
etc.
etc.
etc.
etc.
etc.
etc.
</pre>
</div>
<div id="footer">
footer
</div>
</div>
</div>
</body>
</html>
Is it just me, or is the pink elephant in the room sitting on a ...
< T A B L E >
???
Update (April 20th, 11:40AM): Here's the <table> version:
http://juliusdavies.ca/stackoverflow/pink_elephant.html
Be sure to resize your browser window a few times to see it in action.
IE8 - perfect
Chrome - perfect
Safari - no scrollbar, otherwise okay
Firefox - no scrollbar, otherwise okay
based on your most recent answer, I take it you don't need the footer to be full width (only sticky, though yours isn't) and also I presume you know that your version will only work if you know the height of the "foo - not so important content", as you need the that height to set the top co-ordinate for the sidebar .
You version falls down in that when you narrow the window content disappears off the sides.. but based on the thinking behind it - I've used your logic extended it and built in the sticky footer, top menu - everything that was in the original example link.
the footer's not full width, but you can make it look like it is by putting a background image on the html element, I have a plain dummy image in my fiddle but it's not showing up, anyway you would make an image the same height/color as the footer with the 1px border built in
this absolutely relies on you being able to fix/calculate the height of everything above the pink/blue columns
there is a lot less container divs needed for this and the content is now before the sidebar in the source
Here's the fiddle : fullsize : to edit
I see this as a design having a top a middle and a footer. The middle section contains both the pink and blue columns.
Using CSS, place a repeating image in the background of the middle-section behind both the left and right columns. This image would show the edges of both columns. Hopefully your design will accommodate this. I admit I do not know, without really digging into the code, how to make the middle expand all the way down to the bottom. I should think there are some different ways to approach this.
Use css overflow: auto; for your pink column; for the blue, set overflow: auto; on the or tag.
I hope this helps...

How can I prevent one div from overlapping another on resize?

Here's an example: http://la.truxmap.com/truckpage?id=coolhaus
When I make the browser window narrower from the right hand side, the recent tweets div will go underneath the container div. i want to make it so that the recent tweets div can go no further left than the right hand border of the container div. Ive been trying to figure out if it can be done with css, but i cant seem to get it. is there a simple javascript solution that fits the bill?
Thanks!
You can either choose to work with a liquid layout or use the css property position.
Liquid layout:
You got 3 DIV's in your wrapper divand you want them to resize on a smaller browser window, you can do this with percentages that become variable widths :
css:
.wrapper {
width:100%
}
.divleft {
float:left;
width:20%
}
.divmiddle {
float:left;
width:60%
}
.divright {
float:left;
width:20%
}
html:
<div class="wrapper">
<div class="divleft">left</div>
<div class="divmiddle">middle</div>
<div class="divright">right</div>
</div>
As i said, the other possibility is the assigning the css property position to your different DIV's.
Try it yourself, its fairly easy:
http://www.w3schools.com/Css/pr_class_position.asp
You can also keep them from overlapping vertically:
.noOverlap{
float:left;
width:100%;
}

Categories