why is absolute element width limited by inline-block parent - css

I have the following setup:
div {
position: relative;
display: inline-block;
}
div div {
position: absolute;
top: 100%;
background: green;
}
a {
width: 25px;
float: left;
}
<div>
some
<div>
1
2
</div>
</div>
My question is why the div that contains a elements collapses on parent div width? I'd expect a elements to stay in one line but they wrapped. Is it expected behavior? How can I work around it?

I'd expect a elements to stay in one line but they wrapped. Is it expected behavior?
Yes. they're floated left, but the parent is absolute positioned so constrained from the document floats. Has no width set so the inner elements align to the available space (0) even being left-floated.
a elements are inline elements by default.
First of all you'll have to remove float from your anchors, set them rather to be inline-block. Still they're vertically positioned, to fix that set white-space: nowrap; to the parent.
div{
display: inline-block;
position: relative;
}
div div {
position: absolute;
top: 100%;
background: green;
white-space: nowrap; /* needed! for inner inline elements */
}
a {
width: 25px;
display:inline-block; /* needed just for the 25px width! (otherw. remove) */
}
<div>
some
<div>
1
2
</div>
</div>

Related

Why is my CSS table displaying height for an element that has max-height of 0?

I have an outer div which I am displaying as a table, and and 2 inner divs.
The first inner div is floated to the left. The second inner div has a max height of 0.
.d-table {
display: table;
border: solid 1px black;
}
.float-left{
float: left;
}
.hidden{
max-height: 0px;
overflow-y: hidden;
clear: both;
}
<div class="d-table">
<div class="float-left">
hey
</div>
<div class="hidden">
cool
</div>
</div>
Expected result is:
Actual result is:
The table is taking into account the div with a height of 0 for some reason.
JSFiddle
Seems causes due to non-zero line-height of the div and the vertical-align: baseline of the anonymous cell.
I would use display: table-cell in order to be able to style the cell with vertical-align: top
.d-table {
display: table-cell;
vertical-align: top;
border: solid 1px black;
}
.float-left {
float: left;
}
.hidden {
max-height: 0px;
overflow-y: hidden;
clear: both;
}
<div class="d-table">
<div class="float-left">hey</div>
<div class="hidden">cool</div>
</div>
If you need display: table, then you can't style the anonymous table cell, but you can reduce the space with line-height: 0.
.d-table {
display: table;
vertical-align: top;
border: solid 1px black;
}
.float-left {
float: left;
}
.hidden {
line-height: 0;
max-height: 0px;
overflow-y: hidden;
clear: both;
}
<div class="d-table">
<div class="float-left">hey</div>
<div class="hidden">cool</div>
</div>
This is because the .hidden div is still part of the DOM and factors into the position calculations for the .d-table element.
Instead of max-height: 0;, use display: none. This removes the element from the flow of the DOM.
The .hidden element is theoretically being displayed correctly with a height of 0.
But then it has a clear:both, while the other div hass float:left, and their parents is displayed as table.
This is the magic combo, confusing the height of the parent div.
The problem is: you first kind-of take the first div out of document flow. It is placed somewhere new, but still not really there (yes, floats are spooky as f***).
THEN you clear:both the second div, forcing it on a new line. The parent div (having forgotten all about the first div and the 18 vertical pixels it's taking up), can't have a height of 0 (because it's display-table), so it's given a minimum height of something-something.
There's really no other solution known to me than not using that combination. I would recommend actually hidding the hidden div (display:none).

How can I make the ul list the same size as the input element in terms of width?

I have a container that has two fixed sized elements, and one fluid sized element. When the browser is resized, the fluid element takes the remaining size of the window while the other two stay fixed. The problem is, I have a ul that is being inserted after the input element in a container. How can I make the ul list be the size of the input element in terms of width?
jsfiddle: http://jsfiddle.net/vR7E8/
code:
<div class="wrap">
<div class="left">
</div>
<div class="middle">
<input class="my_input" />
<ul class="my_list">
<li> list one</li>
<li> two </li>
<li> three </li>
<li> four </li>
</ul>
</div>
<div class="right">
</div>
</div>
css:
.wrap
{
display: block;
width: 100%;
height: 100px;
background: yellow;
padding-left: 40px;
padding-right: 50px;
position: relative;
}
.left
{
display: inline;
width: 30px;
height: 100px;
background: blue;
}
input.my_input
{
width: 100%;
height: 100px;
display:inline-block;
}
.right
{
display: inline;
background: green;
width: 40px;
height: 100px;
}
.my_list
{
list-style: none;
padding: 0;
margin: 0;
position: absolute;
width: 100%;
border: 1px solid black;
}
btw the ul list needs to be absolutely positioned because i dont want it to shift the content below it.
also, its setting the width of the list to the size of the parent, so i tried adding a wrapper to the div container "middle" but didnt work.
UPDATE:
ok i got it to work, i just had to make a container, and set that container to position: relative.
Can you add this to your middle section?
.middle {
position: relative;
width: 200px;
}
By setting a width in either % or px, and setting the container to relative position, you give both elements the same parent base to size from.
remove the position:absolute from the <ul> element. Absolute positioning takes the element out of the normal flow, and won't automatically fit to the width of the parent element.
Alternatively you could set a fixed width for both the <input> and the <ul>
here's your jsfiddle forked to show the first fix: http://jsfiddle.net/27qeJ/
got it, just create a container element wrapping the div containing the input and list elements, and set that wrapper to position: relative.

position div to bottom of containing div

How can i position a div to the bottom of the containing div?
<style>
.outside {
width: 200px;
height: 200px;
background-color: #EEE; /*to make it visible*/
}
.inside {
position: absolute;
bottom: 2px;
}
</style>
<div class="outside">
<div class="inside">inside</div>
</div>
This code puts the text "inside" to the bottom of the page.
.outside {
width: 200px;
height: 200px;
background-color: #EEE; /*to make it visible*/
}
Needs to be
.outside {
position: relative;
width: 200px;
height: 200px;
background-color: #EEE; /*to make it visible*/
}
Absolute positioning looks for the nearest relatively positioned parent within the DOM, if one isn't defined it will use the body.
Assign position:relative to .outside, and then position:absolute; bottom:0; to your .inside.
Like so:
.outside {
position:relative;
}
.inside {
position: absolute;
bottom: 0;
}
Add position: relative to .outside. (https://developer.mozilla.org/en-US/docs/CSS/position)
Elements that are positioned relatively are still considered to be in the normal flow of elements in the document. In contrast, an element that is positioned absolutely is taken out of the flow and thus takes up no space when placing other elements. The absolutely positioned element is positioned relative to nearest positioned ancestor. If a positioned ancestor doesn't exist, the initial container is used.
The "initial container" would be <body>, but adding the above makes .outside positioned.

Why aren't these elements overlapping?

I have the following markup:
<div class="promo">
<p class="preview"><img src="preview.png"></p>
<p class="caption">Project caption</p>
</div>
.promo .preview img {
display: block;
margin: 0 auto;
width: 80%;
}
.promo .caption {
background: white;
padding: 0.50em;
margin-top: -2.00em;
}
And this is what I get:
Why does the caption element not overlap the image? It does overlap the .preview div without an image in it. It also does not overlap when the image has display: inline.
Force the caption to go up with position: relative; z-index: 2;.
The behaviour of overlap is unpredictable with staticly positioned elements. The z-index property lets you state clearly if you want it above or below another element. The position property is mandatory for this to work.

How to align the top lines of two DIVs?

I want the top lines of two DIVs (<div></div>) to be aligned horizontally, how to do it?
Steven,
In addition to T. Stone's suggestion to float both divs, a simple way to align two divs is to make both have the display: inline-block; CSS rule and give the lower div the vertical-align: top; CSS rule.
Take a look at this simple jsFiddle example to see how this works.
div {
display: inline-block;
}
div#tall {
height: 4em;
}
div#short {
height: 2em;
vertical-align: top;
}
In response to "is there another way to do it", sure you could use display: inline but you have a bunch of hacks to remember to get it to work in IE6/7. This way is generally better (but it all comes down to the individual circumstances)
<style type="text/css">
.keeper {
overflow: hidden; /* expand to contain floated children */
}
.keeper div {
width: 200px;
height: 30px;
float: left;
border-top: 1px solid red; /* so you can see the 'tops' */
}
</style>
<div class="keeper">
<div>
</div>
<div>
</div>
</div>
Float them in a container.
.parent div { float: left; width: 50%; }
<div class="parent">
<div>1</div>
<div>2</div>
</div>
Note: The sum of the width of the child divs can not be greater than 100% of the parent div, including margin and padding.
Alternative
If maintaining flow with the page isn't a requirement, and all that really matters is aligning, them, the divs can always be positioned absolutely.
.abs { position: absolute; top: 100px; width: 50px; }
.left { left: 0px; }
.right { left: 50px; }
<div class="abs left">1</div>
<div class="abs right">2</div>

Resources