Stacking div elements within adjusting container - css

I am having some troubles on how to structure a new widget I am working on. I am trying to implement a geographic map that contains some hotspots, just like an old school image map. However, for various purposes, I want to accomplish it without the use of image maps.
So far, I have gotten to this incomplete solution:
http://jsfiddle.net/nielsbuus/FZJ8E/1/
HTML:
<div class="parent">
<!-- I'm a container, I need to expand in height, when my children expand, so they don't overlap elements beneath me. Sort of like clearing floats -->
<div class="lower">
<!-- I contain an image. My width is fixed, but my height may vary. -->
<img src="http://placekitten.com/300/325" />
</div>
<div class="higher-container">
<div style="top: 20px; left: 30px" class="higher-spot">foo</div>
<div style="top: 80px; left: 50px" class="higher-spot">bar</div>
<div style="top: 85px; left: 70px" class="higher-spot">baz</div>
</div>
</div>
<div class="successor">
Please keep me below all of this.
</div>
CSS:
.parent {
background-color: #ccffff;
padding: 20px;
position: relative;
}
.lower {
position: absolute;
width: 300px;
background-color: rgba(0,0,0,0.2);
z-index: 0;
}
.higher-container {
position: absolute;
background-color: rgba(255,0,0, 0.3);
}
.higher-spot {
position: absolute;
width: 25px;
height: 25px;
background-color: rgba(0, 255, 0, 0.5);
z-index: 1px;
}
.successor {
font-size: 18px;
font-family: sans-serif;
}
The main problem here is the use of absolutely positioned z-indexed divs. They detach from the rest of the layout, causing the parent container to not expand, thereby placing succeeding elements beneath the absolutely positioned elements.
I am looking for ideas on how to stack two divs (lower and higher-container) on top of each other and have the parent container expand to the size of the lower div.

I am not sure why you are using position: absolute on your .lower container. Use it as relative and then give a top: 0 rule to the .higher-container.
Updated fiddle

You really only need one of your children to be absolutely positioned: the one that is placed on top (.higher-container). This way, .lower which will always be taller than .higher-container will stretch the parent container normally, then the higher-container will be layers, aboslutely, on top. We just need to add a top and left positioning to it:
Here's a jsfiddle: http://jsfiddle.net/rgthree/M6jm8/
.lower {
position: relative;
width: 300px;
background-color: rgba(0,0,0,0.2);
z-index: 0;
}
.higher-container {
position: absolute;
top:0px;
left:0px;
z-index:1;
background-color: rgba(255,0,0, 0.3);
}

Related

Css position absolute leaves white space at the top

I want to absolute position a div but it is not sticked to the top but has a blank space. Container has position:relative and inner block has position:absolute css rules. I tried to play with the code and noticed that changing background-position has some effect and I have no idea why.
<header>
<div class="header-wrapper">
<div class="header-slogan-1 text-center">Base info</div>
<div class="header-info">Info</div>
</div>
</header>
What I want is to have the green block at the top (see fiddle).
Here is the fiddle
Please can anyone explain the behaviour and answer why the block is shifted from the top?
It is shifted from the top, because it is relative to its parent .header-wrapper, that has a top margin. In order to get the desired result, you have to remove position: relative from its parent, therefore it will be relative to the viewport and will be placed at the top.
Edit: I realised, that he margin is actually applied to the child of the wrapper, causing margin collapsing. In order to fix this, you need apply overflow: auto to the parent element. By doing that, you can still have a position: relative on the wrapper, as it is not pushed down by the child. Take a look at the demo:
/* header block */
header {
height: 536px;
background-color: #ddd;
background-position: center;
background-size: 100% 536px;
background-repeat: no-repeat;
overflow: hidden;
}
header .header-wrapper {
position: relative;
overflow: auto;
z-index: 2;
}
.header-slogan-1 {
font-size: 32px;
font-weight: 700;
font-style: italic;
margin-top: 88px;
}
.header-wrapper .header-info {
position: absolute;
top: 0;
z-index: 3;
background-color: #4caf50;
max-width: 600px;
padding: 25px 25px 25px 75px;
color: #fff;
}
.text-center {
text-align: center;
}
<header>
<div class="header-wrapper">
<div class="header-slogan-1 text-center">Base info</div>
<div class="header-info">Info</div>
</div>
</header>
If I'm understanding this correctly, you want the header to have no space around it. If this is the case, then just add
body {
margin: 0;
padding: 0;
}
to the top of your css and you should be all set.
I changed margin-top: 88px; into padding-top: 88px; of header-slogan-1 as it does not change my layout. I have an image in wrapper class and it is centered and may exceed the container size, so I need position:relative and overflow:hidden.
Finally I decided to pick my solution. Sorry Adam for not choosing your answer.

How to add a CSS arrow to an absolutely positioned element

Many time I've successfully used the cssarrowplease technique which imposes the main element (not the arrow) to be relatively positioned. However this time the element I want to add an arrow to is already absolutely positioned.
How to fix this dilemma?
EDIT: here's my code:
HTML
<li id="submenu">
<div id="enquiries_popup">
<div id="enquiries_popup_content">
Content
</div>
</div>
</li>
CSS
li#submenu {
position: relative;
}
#enquiries_popup {
position: absolute;
padding-top: 30px;
}
#enquiries_popup_content {
background: #000;
}
#enquiries_popup_content:after {
bottom: 100%;
left: 50%;
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
pointer-events: none;
border-color: rgba(0, 0, 0, 0);
border-bottom-color: #000000;
border-width: 8px;
margin-left: -8px;
}
Well, It's late I know, Your are right it does not show up because the position is absolute, and the arrow rectangles go out of the box, if you set the bottom to 50% for example you'll see them.
The solution is to put this div in another div with position absolute and give it some padding, then set the popup div position to relative and it will work!
<li id="submenu">
<div id="absolute_div">
<div id="enquiries_popup">
<div id="enquiries_popup_content">
Content
</div>
</div>
</div>
</li>
css
#enquiries_popup {
position: relative;
padding-top: 30px;
}
#absolute_div {
position: absolute;
padding-top: 30px;
}
It will work just fine for your absolutely positioned element. Next time, try it before asking!
All the arrow trick requires is for your element to be positioned in the first place in order for the arrow position to be relative to it. It works with relative, absolute and fixed positioning alike.

Why is the CSS z-index being ignored in position relative using background cover image?

Overview: I have a CSS3 pure navigation system on top of my page. I have a footer/copyright on bottom.
In the middle, I want a background image (parchment) cover, then on top of that parchment, I want a white layer for text with a left column and a right column. I can't seem to make it work using the relative position as my z-index doesn't seem to be working. If I put position "fixed", I can't use the right browser scroll anymore to go down. If I use position "absolute", then the background is right and the content on top is ok, but my navigation footer disappears. If I use position "relative", my navigation system is fine but the background doesn't show up anymore. It is ignoring the z-index....
The weird thing is I am using expression web 4 and it looks correct there...it just doesn't look correct on the web.
This is my site html to reproduce what I am seeing.
<!-- #BeginEditable "content" -->
<div id="page_content_back">
<div id="column_left">
<h1>About</h1>
<p>We are the best-Trust us</p>
</div>
<div id="column_right">
<h4>CONTACTS</h4>
</div>
</div>
<!-- #EndEditable -->
This is my css
#page_content_back {
position: relative;
background-image:url('../images/grayparchment_back.jpg');
background-size: cover;
z-index: 1;
width: 100%;
margin: auto;
padding: 0;
border-top-width: 1px;
border-top-style: solid;
border-top-color: #CCAA77;
}
#column_left {
position: relative;
margin: 0 50px;
padding: 0 2%;
z-index: 2;
top: 0px;
background-color: #fff;
float: left;
width: 65%;
height: 100%;
color: #393939;
}
#column_right {
position: absolute;
z-index: 3;
float: right;
right: 50px;
top: 370px;
width: 20%;
height: 100%;
margin: 0;
padding: 10px;
background-color: #fff;
}
Okay, the problem is your div#column_left. It has a float: left property. Floating an element takes it out of the flow, so there's nothing within the div#page_content_back to give it any height. Remove that float: left property from the inner div and you'll see the image appear behind it. From there, you can add other elements after that nested div and the image will expand to encapsulate the new element. That said, if you use float or position: absolute, you're removing the element from the flow and that background image won't respond to its presence as a result.

Two divs with dynamic height equally high

As the title says, I need two divs to be equally high. They should be as high as it needs to be for the content to fit. The current CSS is:
.portfolioleft{
float:left;
width:189px;
background-color: #436FAC;
min-height: 100px;
height: auto;
color: #FFF;
padding: 20px;
margin-bottom: 20px;
border-radius: 10px;
}
.portfolioleft img{
border-radius: 10px;
}
.portfolioright{
float:right;
width:500px;
background-color: #436FAC;
min-height: 100px;
height: auto;
color: #FFF;
padding: 20px;
margin-bottom: 20px;
border-radius: 10px;
}
.portfolioright a{
color:#FFFFFF;
}
and the html for the divs is:
<div class="portfolioleft"><img src="img" alt="img" width="189" height="311" /></div>
<div class="portfolioright">
<h2>Title</h2>
<p>Text</p>
</div>
<div class="clear"> </div>
CSS alone cannot tackle this feat (unless you want a hack solution where you can use an image). You will need to implement a JS solution. Since the content is dynamic and you do not know how high the columns will be, you will need to access the DOM to determine the height of the tallest column then apply to the indicated columns. I use the following regularly and it works quite well and is easy to implement.
http://www.jainaewen.com/files/javascript/jquery/equal-height-columns.html
Unfortunately this is a tricky problem in CSS. If you only want to extend the background color of your left sidebar to the bottom of the section (with its height defined by the right div), try wrapping them inside a parent div (which scales to the height of the right div), then positioning the left div with position:absolute and height of 100% like so:
<div class="portfolio">
<div class="portfolioleft">...</div>
<div class="portfolioright">...</div>
</div>
.portfolio {
position: relative;
background: white;
}
.portfolio .portfolioleft {
position: absolute;
left: 0;
top: 0;
width: 200px;
height: 100%;
background: #436FAC;
}
.portfolio .portfolioright {
margin-left: 200px;
}
If BOTH sides are dynamic and you need both heights to match, the only surefire way to make it work across all major browsers is to resort to a table-based layout with two columns, as karmically bad as that might be.
cell properties in your left right div
i checked your code and replace the float into display table-cell
you can check to this live http://jsfiddle.net/rohitazad/prMLh/1/

child div not expanding to parent div

So I have three div's
One parent and two child.
The parent is as follows:
#parent {
overflow:auto;
margin: 0 auto;
margin-top:37px;
min-height: 100%;
width:875px;
}
the two child divs are as follows
#child1 {
overflow:auto;
min-height:150px;
border-bottom:1px solid #bbb;
background-color:#eee;
opacity:0.4;
}
#child2 {
height:100%;
background-color:white;
}
The parent div extends 100% as I can see the borders of it till the end of the page but the child2 is not extending down to the end of the page like the parent div.
height doesn't behave the way you seem to be anticipating. When you specify height: 100% that percentage is calculated by looking up the DOM for the first parent of said element with a height specified that has absolute or relative positioning.
You can cheat when it comes to the body tag, so if you had something like this:
<body>
<div style="height: 100%">
</div>
</body>
Some browsers/versions will behave the way you expect by taking up the total height of the page. But it won't work when you go any deeper than that.
Here is the approach I use to strech a div to the bottom of the page, it involves absolute positioning (nice thing about this one is that it is pretty cross-browser compliant and doesn't require javascript to pull it off):
<div id="parent">
<div id="childNorm"></div>
<div id="childStrech"></div>
</div>
#parent
{
position: absolute;
width: 1000px;
bottom: 0;
top: 0;
margin: auto;
background-color: black;
}
#childNorm
{
position: absolute;
width: 1000px;
top: 0;
height: 50px;
background-color: blue;
color: white;
}
#childStrech
{
position: absolute;
width: 1000px;
top: 50px;
bottom: 0;
background-color: red;
color: white;
}
Here is a Jsfiddle for demo: http://jsfiddle.net/t7ZpX/
The trick:
When you specify absolute positioning and then put in bottom: 0; that causes the element to stretch to the bottom of the page; You just have to worry about positioning the elements as a trade off.
Yes, this is one of the annoying things in css. min-height is not considered a "height" for purposes of calculating height. See http://jsfiddle.net/3raLu/3/. You need to have height: 100% on the parent div to make the child full height. Or, if you can have it be absolutely positioned, then this works: http://jsfiddle.net/3raLu/6/.

Resources