When I try to use position: relative / position: absolute on a <th> or <td> in Firefox it doesn't seem to work.
Easy and most proper way would be to wrap the contents of the cell in a div and add position:relative to that div.
example:
<td>
<div style="position:relative">
This will be positioned normally
<div style="position:absolute; top:5px; left:5px;">
This will be positioned at 5,5 relative to the cell
</div>
</div>
</td>
That should be no problem. Remember to also set:
display: block;
Since every web browser including Internet Explorer 7, 8 and 9 correctly handle position:relative on a table-display element and only FireFox handles this incorrectly, your best bet is to use a JavaScript shim. You shouldn't have to rearrange your DOM just for one faulty browser. People use JavaScript shims all the time when IE gets something wrong and all the other browsers get it right.
Here is a completely annotated jsfiddle with all the HTML, CSS, and JavaScript explained.
http://jsfiddle.net/mrbinky3000/MfWuV/33/
My jsfiddle example above uses "Responsive Web Design" techniques just to show that it will work with a responsive layout. However, your code doesn't have to be responsive.
Here is the JavaScript below, but it won't make that much sense out of context. Please check out the jsfiddle link above.
$(function() {
// FireFox Shim
// FireFox is the *only* browser that doesn't support position:relative for
// block elements with display set to "table-cell." Use javascript to add
// an inner div to that block and set the width and height via script.
if ($.browser.mozilla) {
// wrap the insides of the "table cell"
$('#test').wrapInner('<div class="ffpad"></div>');
function ffpad() {
var $ffpad = $('.ffpad'),
$parent = $('.ffpad').parent(),
w, h;
// remove any height that we gave ffpad so the browser can adjust size naturally.
$ffpad.height(0);
// Only do stuff if the immediate parent has a display of "table-cell". We do this to
// play nicely with responsive design.
if ($parent.css('display') == 'table-cell') {
// include any padding, border, margin of the parent
h = $parent.outerHeight();
// set the height of our ffpad div
$ffpad.height(h);
}
}
// be nice to fluid / responsive designs
$(window).on('resize', function() {
ffpad();
});
// called only on first page load
ffpad();
}
});
Starting with Firefox 30, you'll be able use position on table components. You can try for yourself with the current nightly build (works as standalone): http://ftp.mozilla.org/pub/mozilla.org/firefox/nightly/latest-trunk/
Test case (http://jsfiddle.net/acbabis/hpWZk/):
<table>
<tbody>
<tr>
<td style="width: 100px; height: 100px; background-color: red; position: relative">
<div style="width: 10px; height: 10px; background-color: green; position: absolute; top: 10px; right: 10px"></div>
</td>
</tr>
</tbody>
<table>
You can continue to follow the developers' discussion of the changes here (the topic is 13 years old): https://bugzilla.mozilla.org/show_bug.cgi?id=63895
Judging by recent release history, this could be available as soon as May 2014. I can barely contain my excitement!
EDIT (6/10/14): Firefox 30 was released today. Soon, table positioning won't be an issue in major desktop browsers
As of Firefox 3.6.13, position: relative/absolute do not seem to work on table elements. This seems to be long standing Firefox behaviour. See the following: http://csscreator.com/node/31771
The CSS Creator link posts the following W3C reference:
The effect of 'position:relative' on table-row-group, table-header-group, table-footer-group, table-row, table-column-group, table-column, table-cell, and table-caption elements is undefined. http://www.w3.org/TR/CSS21/visuren.html#positioning-scheme
Try using display:inline-block it worked for me in Firefox 11 giving me positioning capability within the td/th without destroying the layout of the table. That in conjunction with position:relative on a td/th ought to make things work. Just got it working myself.
I had a table-cell element (which was actually a DIV not a TD)
I replaced
display: table-cell;
position: relative;
left: .5em
(which worked in Chrome) with
display: table-cell;
padding-left: .5em
Of course padding usually is added to width in the box model - but tables always seem to have a mind of their own when it comes to absolute widths - so this will work for some cases.
Adding display:block to the parent element got this working in firefox.
I also had to add top:0px; left:0px; to the parent element for Chrome to work.
IE7, IE8, & IE9 are working as well.
<td style="position:relative; top:0px; left:0px; display:block;">
<table>
// A table of information here.
// Next line is the child element I want to overlay on top of this table
<tr><td style="position:absolute; top:5px; left:100px;">
//child element info
</td></tr>
</table>
</td>
The accepted solution kind of works, but not if you add another column with more content in it than in the other one. If you add height:100% to your tr, td & div then it should work.
<tr style="height:100%">
<td style="height:100%">
<div style="position:relative; height:100%">
This will be positioned normally
<div style="position:absolute; top:5px; left:5px;">
This will be positioned at 5,5 relative to the cell
</div>
</div>
</td>
</tr>
The only problem is that this only fixes the column height problem in FF, not in Chrome and IE. So it's a step closer, but not perfect.
I updated a the fiddle from Jan that wasn't working with the accepted answer to show it working.
http://jsfiddle.net/gvcLoz20/
Related
Hello I am trying to make an online chat application.
I have the html:
<body>
<table align="center" width="80%">
<tbody class="scroll">
<!--All of the chat-->
</tbody>
<tbody class="formheight" style="width:100%">
<tr>
<td>
<form style="width:100%" action="Write-to.php" method="post">
<input autocomplete="off" name="txt" type="text" id="usermsg" style="font-size:2.4vw;" value="" />
</form>
</td>
</tr>
</tbody>
</table>
</body>
And the css:
html, body
{
height: 100%;
max-height:100%;
overflow: hidden;
}
table
{
height: 100%;
}
tbody {
overflow: auto;
width:100%;
}
thead > tr, tbody{
display:block;
}
I want the 2nd tbody (The one that contains the form) to lie at the bottom of the page and the first to fill the rest of the page upwards.
Currently I am having to use jquery to (kind of) do what I want. Currently the form is half hidden. I would rather do this all with CSS so that it works better with mobile devices.
How could I do that?
Jquery:
var heighty = $(window).height();
var height = $('.formheight').height();
$(".scroll").css("height", heighty - height + "px");
I also can't for the life of me get the form text input to be 100% width?
Please see JSfiddle
I am also very open to another way of laying out this chat app all together!
This is possible in CSS, but would be very difficult to get working across all browsers. Instead, here is my recommendation:
Create an element that fills up 100% height with a bottom padding set to X px.
Create an element with position:fixed and a height of X px.
Give the latter element a z-index:2 and the former a z-index:1. z-index doesn't need to be assigned manually, elements further down in source code automatically have a higher priority and are displayed over previous elements (if they overlay visually).
If you want, you could use a different unit. Percents are very easy because you can have them add up to 100%, so no need for a margin. Of course each has its respective drawbacks, but in my experience what I've described generally has good compatibility and displays comparably on all devices. You could even use CSS #media queries to change the height, X, for different devices.
You need to use something what we call a "Sticky Footer", In your case, your second body goes in the sticky footer. Have a look at this http://ryanfait.com/sticky-footer/ or this http://www.cssstickyfooter.com/ for the css+html for a sticky footer
I have a div that contains a table. On the click of a button in the table, I want to rotate the div and its contents by 90 degrees and hide everything but the header offscreen. Here is an example of this working in IE10:
However, this does not work in IE7 and IE8. Inspecting the elements via the developer toolbar, it seems that the table is not rotating. The div seems to be rotating, because the outline appears where it should be... However, it's like the actual UI isn't updated to reflect this rotation?
Any ideas what might be happening and how to fix this?
Some relevant css for IE7:
#my-div {
width: auto;
float: left;
position: relative;
overflow-y: auto;
overflow-x: hidden;
max-width: 200px;
min-height: 35px;
height: 100%;
display: block;
}
#my-div.hide
{
overflow: hidden;
height: 35px;
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1);
}
#my-div table
{
width: auto;
}
And the html is nothing special. It's laid out like this:
<div id="my-div">
<table>
<thead>
<tr>
<th>
<button>X</button>
</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
</tr>
...
</tbody>
</table>
</div>
Your code should work for IE7. If you are unable to get it work there is a JavaScript Library called CSS Sandpaper that allows you to use CSS code for rotations and works for older versions of IE.
Edit: I was playing with the example code from the MS Developer Network and noticed that their example works fine on all versions of IE. If I change the position: to relative instead of absolute the rotation stops working in IE7. You might want to test that on your end since you are using relative positioning on your element.
If that does not help you a full sample of your HTML code or a fiddle would be helpful so that the community could better help you.
The issue was that I was using developer tools to switch between browsers. Apparently, this changes some browser security settings. The way this would actually look in IE7/IE8 is not accurately represented by using developer tools in IE10.
I downloaded IETester, and the content is not having this issue anymore. False alarm.
on associated click event of the button use jquery to rotate the div and all its children
function changeOrientation(){
$('#div').attr('webkit-transform', 'rotate(90deg)');
//Loop inside all elements in the div and add the same to all the elemnt
}
javascript code
function changeOrientation(){
document.getElementById('#div').style.webkit-transform = 'rotate(90deg)';
//Loop inside all elements in the div and add the same to all the elemnt
for(var count = 0; count < document.getElementById('#div').children.length; count++){
document.getElementById('#div').children[count].style.webkit-transform = 'rotate(90deg)';
}
}
give a try and let me know if it works.
I have one div displaying as table-cell and I want to position the another one relative to the first one. But it doesn't work in Firefox.
Open this link in Firefox please, and see the difference. How can I fix it?
http://jsfiddle.net/JFAbM/
I saw someones didn't understand what I need exactly. So I updated the code. I need to position the light gray block.
http://jsfiddle.net/JFAbM/7/
Guys, I have already solved it with wrapping extra div
Ex. here jsfiddle.net/JFAbM/8
just change the position:absolute to position:relative, no need to wrap any extra div
see this Fiddle
update : http://jsfiddle.net/JFAbM/5/
Replace position:absolute; with position:relative;
Check fiddle
I'm also searching for an appropriate solution. As jumancy pointed out and as far as I can see you will need a wrapper-element:
<table>
<tr>
<td><div class = "relative-wrapper">
<!-- Other stuff goes here -->
<div class = "pos-abs">Be relative to me, wrap me, show me on hover!</div>
<!-- or here -->
</div></td>
</tr>
</table>
//CSS
.relative-wrapper{
position: relative;
display: block;
}
.pos-abs{
position: absolute;
}
I cannot figure out this positioning problem in Firefox. It doesn't seem to follow the absolute positioning rule. Is there something I'm doing that shouldn't be done, but some browesers handle it and some don't?
JS Fiddle:
Original - http://jsfiddle.net/g9qzh/
Updated - http://jsfiddle.net/g9qzh/2/
Works in IE, Chrome, Safari, Opera
Here's the actual code. Let me know if I'm not following some kind of standard I don't know about.
HTML:
<table>
<tr>
<td>
<div id="three">Three</div>
<div id="two">Two</div>
</td>
<tr>
<tr>
<td>
<div id="three">Three</div>
<div id="two">Two</div>
</td>
<tr>
</table>
CSS:
#two {
position: absolute;
top: 0;
}
td {
position: relative;
}
My only clue is that there is some other value that I should assign to td that would cause it to work. Some other stackoverflow questions have mentioned Firefox misbehaving with this, but I haven't been able to find an answer. I tried assigning both top and left values of zero, but FF won't budge.
Change ID's to classes and also displaying it as blocks fixes it:
http://jsfiddle.net/GchWZ/
It is better and more "proper" to user an inner div though as quoted from this stack overflow post: Does Firefox support position: relative on table elements?
<td>
<div style="position:relative">
This will be positioned normally
<div style="position:absolute; top:5px; left:5px;">
This will be positioned at 5,5 relative to the cell
</div>
</div>
</td>
You are using IDs
IDs are unique. Use Classes if you want to reuse a style assignment.
The problem comes from how FF renders tables. If you set your TDs to display:inline-block; it should display correctly.
Try this:
<tr>
<td>
<div id="wrapper">
<div id="three">Three</div>
<div id="two">Two</div>
</div>
</td>
</tr>
<tr>
<td>
<div id="wrapper">
<div id="three">Three</div>
<div id="two">Two</div>
</div>
</td>
</tr>
and for css:
#two {
position: absolute;
top: 0px;
}
#wrapper {
position: relative;
}
Aside from the duplicate ID issue noted by Brandt, assigning positioning to table cells is dodgy at best - I'm surprised it works in any browsers. If you must use a table, wrap the elements you want to position in a div and assign the wrapper div position: relative:
<table>
<tr>
<td>
<div class="wrapper">
<div id="three">Three</div>
<div id="two">Two</div>
</div>
</td>
<tr>
</table>
CSS
#two {
position: absolute;
top: 0;
}
.wrapper {
position: relative;
}
In case you want to position stuff at the top and bottom of a cell, also in Firefox, I made it work doing the following mix of CSS and (unfortunately) jQuery.
Use a wrapper div (div.inner) inside your td which has position=relative style in the td. Inside the wrapper I added 2 divs which are to be positioned at the top and bottom of the cell.
Positioning at the top (class=interval-start) is for free, via CSS positioning.
Positioning the div.interval-end at the bottom is done via script, which adds the styling shown in the picture. With variable td-heights and the wrapper div being 0-height by default, you need a way to tell the element how far it should go to the bottom. The script is as follows:
$("table .inner .interval-end").each(function () {
$(this).css({top: ($(this).parent().parent().height() - 10) + "px"})
}).show()
I initially made the div.interval-end invisible, set the 'top' style, and then made it visible via jQuery show().
Hope this helps anybody trying to achieve the same. Let me know if there are better methods out there, specially if these methods do not require scripting. BTW: I tried setting the height style of the wrapper div.inner, but it messes with the table layout in Firefox.
There are legitimate reasons to use CSS display: table styling. It eliminates issues that display: block and display: inline-block do not address. These reasons occupy an entire chapter of a book on CSS styling so I won't go into them here. That same book also describes the problem of positioning within items with that display type. CSS 2.1 specs simply don't address the issue and Mozilla has chosen a course that ignores attempts to create a positioning context with those elements. CSS-table positioning is well established, mature methodology, and not "dodgy" - it just takes understanding of its limits - just like any other CSS element. For liquid layouts and other layouts where element size is variable or unknown it's indispensable for vertical spacing and positioning.
One suggestion in this thread has been presented - create a div within the "table-cell" element set to position: relative and use that for the positioning context. The other method is to embed another CSS table within that cell and use it to position elements within a grid. The third method is to wrap your CSS table within another item that creates a positioning context.
I have the following code that I am using to display a search tool with a scrolling results section. In IE the code works fine:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html style="background:black;height:100%;width:100%;">
<head>
<title>Report</title>
</head>
<body style="background:black;">
<table HEIGHT="100%" WIDTH="100%" style="background:red;">
<tr>
<td>
Search Area
</td>
</tr>
<tr>
<td HEIGHT="100%" WIDTH="100%" style="background:orange;">
<div style="overflow-y:scroll;height:100%;">
<table style="width:100px;height:1000px;">
<tr>
<td style="background:white;">
Results Area
</td>
</tr>
</table>
</div>
</td>
</tr>
</table>
</body>
</html>
But when I set the meta tag to use IE8 formatting by adding:
<meta http-equiv='X-UA-Compatible' content='IE=edge' />
The bottom DIV tag expands beyond the page. I have tried a number of options though and can't find a way around it without actually specifying a height for the values. Which will not work as I want the page to take up 100% of the screen no matter the size of the browser window.
Any help would be much appreciated.
This metatag enables correct CSS rendering, and in CSS – by design – height:100% basically doesn't work.
You need to give specific height to every single ancestor of the element, including <body>, <table>, <tr> and even <tbody> element that's automatically inserted by the parser.
Anyway, this layout can be achieved in easier way:
.topBanner {
position:absolute; position:fixed;
height:2em;
top:0; left:0; width:100%;
}
body {padding-top: 2em}
this will degrade nicely in IE6, and unlike overflow, will work properly in Mobile Safari.
Edit:
Removing the DOCTYPE declaration will make height="100%" work but it puts the browser in quirks mode though, which is not desirable.
Generally speaking using tables for layout is discouraged, you should use CSS instead.
For example: http://jsfiddle.net/rf649/7/
HTML
<div id="search">Search Area</div>
<div id="results">Results Area</div>
CSS:
#search {
background-color: red;
position: fixed;
height: 150px;
width: 100%;
}
#results{
background-color: orange;
position: fixed;
top: 150px;
width: 100%;
bottom: 0;
overflow: auto;
}
You should set all margins and paddings for the parent elements to zero in order to get what you want.
Update: Sorry, didn't understand the problem at once. Ben's hint should be the better one I assume. :)
Update 2: Oops, since Ben has deleted his answer my first update doesn't make any sense. Try setting the body's height to 100%, that should solve the problem.
My understanding about cross browser CSS is not that big so it might not be the best solution, but it's a solution.
As far as I've seen, you always have to set the height/width of the container that you want to overflow, so you need to set them.
To deal with the resolution I would suggest you to add a jQuery script at the onReady event that dynamically would fix the height and width making the overflow work.
I had the similar problem like you and finally the solution was to modificate a CSS line entry that had an !important modificator for a fixed height declaration. In the HTML code the class (defined in CSS) had the height assigned to 100%, but the CSS applied the !important during the style loading.