Inner button with `position: absolute` will be placed outside a table - html

Html:
<br/><br/><br/><br/><br/>
<table>
<tr>
<td class="container">
<button class="del">delete</button>
</td>
</tr>
</table>
<br/><br/><br/><br/><br/>
<div class="container">
<button class="del">delete</button>
</div>​
Css:
.container {
position: relative;
border: 1px solid red;
height: 50px;
width: 200px;
}
.del {
position: absolute;
top: 3px;
right: 3px;
}​
Why the button inside a div will be placed on the top right corner of the div, but the one inside a td will be placed outside the table?
How to fix it?
See active demo: http://jsfiddle.net/Freewind/d6Tug/

I think it has something to do with the display style of a td, which is table-cell. If you set it to display:block, it will work correctly.
Just add display:block to your .container style.
As freewind pointed out, it would be better to use inline-block if it is supported in your browser for td since td's are usually displayed in a row.

Giving an element position:absolute; places it relative to its containing block. Since a table cell is not considered a block container (unlike a div), it places it relative to the document body itself. top:3px; brings it 3px from the top border of the document and right:3px; moves it 3px from the right border.
http://reference.sitepoint.com/css/position

Related

DIV as filling block in another DIV

I have a CSS
.nav {
width: 200px;
line-height: 50px;
float: left;
}
.content {
margin: 0px 0px 0px 230px;
}
.container {
border: 1px solid red;
}
And here is the HTML
<body>
<div class="container">
<div class="nav">Some text
<br>more text
<br>even more text
</div>
<div class="content">
<h1>Home</h1>
<p>Text paragraph</p>
</div>
</div>
</body>
This gives me menu on the left and the content on the right. And a red box around the content on the right, but only the half menu on the left.
But I would like to have the red box also around the complete nav-div Can anyone help?
Thanks
Teddy
Add overflow:auto to your container div's CSS:
.container {
border: 1px solid red;
overflow:auto;
}
jsFiddle example
Floating the child div removes it from the flow of the document and the container essentially collapses as if it didn't exist. Adding the overflow restores the behavior you're after.
I think this is a quick fix if you float your container it should solve the problem your having. See here http://jsfiddle.net/1540sscj/
.container {
border: 1px solid red;
float:left;
width:100%;
}
Floating an element removes it from the normal flow of the page with one side effect being that its parent's dimensions won't expand to fit it.
So, what you need to do is clear the floated item. The best way to do this, without using additional markup or using the overflow property, which may cause other issues, depending on your layout, is to use the :after pseudo class on the parent element, like so:
.nav{
width:200px;
line-height:50px;
float:left;
}
.content{
margin:0px 0px 0px 230px;
}
.container{
border:1px solid red;
}
.container::after{
clear:both;
content:"";
display:block;
height:0;
width:0;
}
<body>
<div class="container">
<div class="nav">Xalsdk fjaskldfj alskdfj asädf<br>asdf<br>asdf</div>
<div class="content">
<h1>Home</h1>
<p>Bla bla.</p>
</div>
</div>
</body>
More information on clear
More information on pseudo elements
Best way imho would be to add a div like:
<div style="clear:both;"></div>
Under your floating elements: FIDDLE
This way you don't need to use oveflow:hidden on your container that may give you problems once you have more stuff in your project.
Also you shoudn't use a margin-left for your content as the previous element is already floating left. The best practise if you want to add some margin between nav and content would be to make your content float left as well and then use margin left (the exact size you want) with respect of the nav and not with the left of the window.
Finally, if you don't want to add the clear:both div to the html you could add somethign like
.content:after {
content:'';
display:block;
clear: both;
}
it's a bit less browser (old ones) compatible but cleaner
You have to add overflow:auto to .container in your css
Check my js fiddle
Also the css that modified.
.container {
border: 1px solid red;
overflow:auto;
}
Description of property overflow from MDN
The overflow property specifies whether to clip content, render
scrollbars or just display content when it overflows its block level
container.

Firefox starts the absolute positioning of a div from the top left side of the page rather than div's parent

I have a div that has a table in it.the table has a row and tow columns.I want a div inside the second column and I want it to be positioned absolute from the table column(not the start of the page).so here is what I did:
this is the html file:
<body>
<div id="one">
<table id="table">
<tr id="two">
<td id="three"></td>
<td id="three">
<div id="four"></div>
</td>
</tr>
</table>
</div>
</body>
and this is the CSS:
#one {
width: 100%;
height: 100px;
background-color: #f00;
}
#three {
width: 100px;
height: 80px;
background-color: #b6ff00;
/*margin-left: 100px;*/
/*float: left;*/
position: relative;
}
#four {
width: 50px;
height: 40px;
background-color: #0ff;
position: absolute;
left: 20px;
top: 20px;
}
this code works nicely on Chrome and IE.But it doesn't work on Firefox.In Firefox,the <div id=four> 's position,starts from the top left corner of the page rather than the <div id=three>.What can I do about it?(And I should mention that I should use a table for my design.I can't use anything else here)
I had this EXACT same problem, found none of the above answers fixed it, and then found a solution in a different thread that fixed it for my project.
Put display: block; on the td that is parent to the div. That's it.
You may be interested to know that I tested this with your example code and got it to work as well, without negative effects in other browsers that I've tested so far. Your mileage may vary depending on needs of the project.
One downside is that it does kill the td identity - for some table layouts you will need additional CSS trickery to reformat, for others this may not be feasible.
Linkage to answer I found:
Using Position Relative/Absolute within a TD?
Give the parent position:relative and you are done.

Floating div expands to 100% in IE7

I have the following simple layout:
div.main
{
width: 300px;
border: 2px solid #98999E;
overflow: auto;
}
div.main > div
{
float: right;
border: 2px solid #FF3700;
margin: 2px;
}
div.inner > div
{
float: right;
}
<div class="main">
<div class="inner">
<div>123</div>
<div>456</div>
</div>
<div>999</div>
</div>
In Chrome and Firefox, this is rendered as expected - all the content is within the same line:
However, when testing this in IE7 (or actually IE8 in compatibility mode, to be exact), the first div under the main one takes a width of 100%, and therefore the second is pushed beneath it:
An example can be found here.
How can that be fixed?
(Edit:
It turns out that this is happening in IE9 in compatibility mode as well)
(Edit 2: It seems that this is happening with float:right only, and doesn't with float:left)
Apply display: inline; or display: inline-block; to the inner div.
w3.org - 9.2.2 Inline-level elements and inline boxes
IE might need a width...technically you're supposed to have a width assigned when you are floating an element.
Try adding a div with a style of clear:
div.main{
width: 300px;
border: 2px solid #98999E;
overflow: auto;
}
div.main > div {
float: right;
border: 2px solid #FF3700;
margin: 2px;
}
div.inner > div {
float: right;
}
div.clear{
clear:both;
}
<div class="main">
<div class="inner">
<div>123</div>
<div>456</div>
</div>
<div>999</div>
<div class='clear'>
</div>
This MUST be done with a div (or some other block level element). It's always good CSS form to clear your floats at the same level at the same level as you create them, after all the floated elements. Let me know if it works for you. Cheers.
I'd suggest that you specify width for floated <div>. That way, you will be more sure about the layout; rather than relying the rendering completely on the browser. Also, it'd hopefully help you visualize what layout you're trying to get at.
Just from the example above, maybe using floating <span> inside a <p> will accomplish what you need? Or, just right-align a paragraph.

absolute positioning inside a table

I need to position something with absolute positioning inside a td. To get around the fact that a td is undefined when setting it to relative, I use a div set to relative inside my td then inside that div I have an inner div set to absolute. This all works great when I have content filling up the td. When I set the content of the td to display none then the absolute positioning gets all screwed up.
Does anyone know why this would be.
HTML:
<table>
<tr>
<td>
<div class="relative">
<div class='absolute'>
<p>A</p>
</div>
</div>
<div class="slot"></div>
<div class="slot"></div>
</td>
<td>
<div class="relative">
<div class='absolute'>
<p>B</p>
</div>
</div>
<div class="slot hidden"></div>
<div class="slot"></div>
</td>
</tr>
</table>
And CSS:
td{
border:1px solid red;
width:100px;
height:60px;
vertical-align:bottom;
}
.slot{
width:100px;
height:29px;
background-color:#999;
border:1px dashed blue;
}
.relative{
position:relative;
}
.absolute{
position:absolute;
top:5px;
left:5px;
}
.hidden{
display:none;
}
And a live version: http://jsfiddle.net/HgEtQ/
In the fiddle above you can see the first table cell works correctly. The absolutely positioned div is in the correct space. The second one has hidden the top slot and now the absolute positioning is not in the top left corner anymore. If you take out both slots then it really screws up the absolute positioning. I need to positioning it absolute because some of the elements will be shifted depending on the element.
There are a couple things going on here.
You have this:
td {
/*...*/
vertical-align:bottom;
}
That will push the content of the cells to the bottom.
Also, an absolutely positioned element is removed from the normal flow so it won't contribute to its parent's height:
It is removed from the normal flow entirely (it has no impact on later siblings). An absolutely positioned box establishes a new containing block for normal flow children and absolutely (but not fixed) positioned descendants.
In particular, this means that your div.relative elements have a height of zero but they will still have an upper left corner so your absolute positioning offsets are anchored somewhere.
Then you have <div class="slot hidden"> and the hidden removes the <div> from the layout so you effectively have just this:
<div class="relative"></div> <!-- Height zero -->
<div class="slot"></div> <!-- Height 29px -->
That combined with the vertical-align: bottom means that your second div.absolute will be positioned 5px from the top of the div.slot and that is 25px from the bottom of the table cell.
The first cell works fine because the two visible div.slot elements push the div.relative right to the top of the cell, then the div.absolute is positioned 5px from the top of the div.relative and that is 5px from the top of the table cell.
Unfortunately, adding position: relative to a <td> is a bit dodgy as far as browsers go so you'll need some hackery to get your positioning right while keeping vertical-align: bottom. You could re-structure the <td>s like this:
<td>
<div class="relative">
<div class='absolute'>
<p>A</p>
</div>
</div>
<div class="nonsense">
<div class="slot"></div>
<div class="slot"></div>
</div>
</td>
And the CSS like this:
td{
border:1px solid red;
width:100px;
height:60px;
vertical-align: top;
}
.slot{
width:100px;
height:29px;
background-color:#999;
border:1px dashed blue;
}
.relative {
position:relative;
}
.nonsense {
height: 62px; /* td[height] + 2 for the borders */
display: table-cell;
vertical-align: bottom;
}
.absolute{
position:absolute;
top:5px;
left:5px;
}
.hidden{
display:none;
}
Live example: http://jsfiddle.net/ambiguous/aV4nT/
Or you could use visibility: hidden:
hidden
The generated box is invisible (fully transparent, nothing is drawn), but still affects layout. Furthermore, descendants of the element will be visible if they have 'visibility: visible'.
instead of display: none for your .hidden class:
.hidden {
visibility: hidden;
}
This will leave both div.slot elements taking up space and affecting the layout but only the second one will be seen.
Live example: http://jsfiddle.net/ambiguous/RcdNh/

Avoid an Element from being cut off when they are inside a "overflow: hidden" element

I'm using the equal heights CSS trick as outlined on this page.
It was all working fine until today when I need to add a dialogue box inside one of the columns, which is absolutely positioned to take it out of the flow. The problem is that since the container has "overflow: hidden" on it, the dialogue is being cut off when it overflows.
Aside from bringing the dialogue outside of the container element, is there any possible way to get it to show via CSS?
Here's a small example demonstrating what I've mentioned.
<style>
.container { overflow: hidden; margin-top: 30px }
.col {
float: left;
padding-bottom: 2000px;
margin-bottom: -2000px;
border-right: 1px solid black;
width: 100px;
background-color: grey;
}
.col.third { border-right: none }
#div-a { position: relative }
#div-b {
position: absolute;
background-color: red;
width: 35px;
height: 350px;
bottom: 0;
right: 0;
margin: 5px;
border: 2px solid black;
}
</style>
<div class="container">
<div class="col first">
<p style="height: 100px">One</p>
</div>
<div class="col second">
<p style="height: 300px">Two</p>
<div id="div-a">
<!-- this gets cut off by the "overflow: hidden" on div.container -->
<div id="div-b">
Foo
</div>
</div>
</div>
<div class="col third">
<p style="height: 200px">Three</p>
</div>
</div>
You see that div#div-b is cut off at the top when it overflows in the div.container element.
Unfortunately what you want to do is impossible without bringing the dialogue outside of the container element.
Your best bet is to make the dialog element a sibling of the container and position it that way.
Unfortunately no... I don't think there's a way to circumvent overflow: hidden with absolute position. You may experiment with position: fixed, but you won't be positioning under quite the same conditions if you use it.
One option would be to place the content of your overflow:hidden container into a sub-container (a child div perhaps). Then, make the sub-container match the dimensions of the container and move the overflow:hidden from the container to the sub-container.
Then, you can make the dialog a child of the container (a sibling of the sub-container), and it will now exist in an element that does NOT have overflow:hidden.
I haven't tested this, and removing the overflow:hidden from the container may break your design. If that is the case, I would suggest doing as others have and moving the dialog box outside of the container entirely. This could even be done via Javascript if you don't have the option of putting the dialog box's code anywhere else. (Javascript could make the dialog box a child of BODY, or some other tag, when you need it displayed)