I have a red div at a fixed position : top and bottom are fixed.
This div contains a table in which a cell contains a scrollable div, so that the content can't overflow the red div.
It looks like this on Chrome :
But on Firefox, the content grows and overflows out of the red box :
Here's my HTML :
<div id=a>
<div id=b>
<table id=c border=1>
<tr><th height=20 width=20>
<input type=button id=but value="Fill cell">
</th><th>A</th></tr>
<tr><th>dataname</th>
<td><div id=val class=scrollable>cell content</div></td>
</tr>
</table>
</div>
</div>
and the CSS :
#a {
position:fixed; top:20px; left:20px; bottom:50px;width:200px;
background:red;
}
#b { height:100%; }
#c { width:100%; height:100%; }
.scrollable {
width:100%; height:100%;
overflow-y:auto;
}
And here's a fiddle for the tests : http://jsfiddle.net/xusqc/
I'd suggest you test your proposal on FF before submitting an answer.
How could I fix my code to have on Firefox and IE9+ the behavior I have now on Chrome ?
Note that the height of the first line of the table may change dynamically in my application. And the solution must be applicable if my data table has more rows and cells.
As I couldn't find a cross-browser pure HTML/CSS solution, I had to use some JavaScript (and jQuery but it could have been done without it if I hadn't many event handlers bound with jQuery in my cells).
The idea is to empty the cells containing a .scrollable div, compute their heights, refill the cells then set the heights as fixed.
Here's the function I wrote :
function resetScrollableHeights(){
$sp = $('.scrollable').closest('td'), heights = [], contents = [];
$sp.each(function(){
$(this).css('height', 'auto'); // without this, window shrinking would be badly handled
contents.push($('.scrollable', this).detach()); // let's empty all scrollables
});
$sp.each(function(){ //now store the heights
heights.push($(this).height());
});
$sp.each(function(){ // refill the scrollables and fix the heights
$(this).append(contents.shift()).css('height', heights.shift());
});
}
The function is called when the window is resized :
$(window).resize(resetScrollableHeights);
And it must also be called when the content of a .scrollable div changes.
I tested it on Chromium/Ubuntu, Chrome/Android, Firefox/Ubuntu and IE9/Win7. As it's useless on WebKit based browsers where I hadn't any bug with pure HTML/CSS it could be deactivated with some detection but I prefer my code to be free from browser detection.
Demonstration
Change the <td> to <td class="scrollwrap">, the one that contains your target div.
Update your CSS:
:
.scrollwrap { position:relative; }
.scrollable {
position:absolute; width:100%; height:100%; top:0; left:0; right:0; bottom:0;
overflow:auto;
}
But be aware:
height:100% only works when parents also have a specific height, doesn't always work with calculated heights;
when using left&right or top&bottom on position:absolute elements, some browsers can't calculate width & height
overflow-y or overflow-x have some usage limitations.
Related
<div id="header">
<div>My</div>
<div>Header</div>
</div>
<div id="content"></div>
In the above markup, how can I get the content to fill the rest of the screen (no-scrolling)?
I know how to do this with absolute positions if the header was of a fixed height, but my header's height is dynamically set by its contents (so the site is responsive on mobile devices.)
Btw: I'm looking for a CSS only solution, because I think JavaScript is not made for this kind of task.
Thanks a lot,
The simpliest way is to draw the background in body and keep #content translucide. DEMO 1.
This way, you do not mind #header nor #content heights.
If you do not mind about IE7 and less, then display:table/table-row/table-cell taken from defaut display of HTML table elements can be what you need , in the case header has unknown height. DEMO 2
Your structure will need a bit of update in order to act as wished and to avoid gaps in layout render from header part to the content part.
If you reset display to be used as table properties, it will do so and can draw cols and rows.
Since it is only the row properties that will be usefull, Structure must be rendering as one single col and multiple rows.
Basic structure needs to turn this way :
<div id="header" class="row">
<div class="single">
<div>My</div>
<div>Header than can grow</div>
</div>
</div>
<div id="content" class="row">
<div class="single">
<p>My Content that will fill remaining space untill page has to scroll</p>
</div>
</div>
And basic CSS turns this way :
html, body {
height:100%;
width:100%;
margin:0;
}
body {
display:table;/* it will allow to grow over initial width specified */
/* table-layout:fixed; only if you want to control width within value specified*/
background:#edc;
}
.row {
display:table-row;/* we want these elements to stack on top of each other, not to become cells aside each other */
}
.single {
display:table-cell;/* this 'buffer' element is used to avoid layout to turn into multiple cols */
}
#content {
height:100%;/* since layout is the one taken from table properties, it means fill all space avalaible that #header doesn't use */
background:#cde;
}
In the case, *#header has a known*** height, it can be set in fixed or absolute position.
#content can be 100% height DEMO 3, better: min-height:100%; DEMO 4
display:flex could be useful too but for real young browser only :).
Example with display:flex;
html {
height:100%;
}
body {
margin:0;
min-height:100%;
background:#edc;
display:flex;
flex-direction:column;
}
#header {
/* nothing needed here */
}
#content {
flex:1;/* since it is the only one getting a flex attitude, it will fill up all space avalaible*/
background:yellow;
}
Here's my example.
If you have two table columns, one with taller content than the other, then divs inside the other column don't expand to the first column's, even with height:100%. How can I create this behavior with CSS?
<table>
<tr>
<td class="one">
<ul>
<li>fasdf</li>
<li>asgasdf</li>
<li>afdsaggrea</li>
<li>asgasdf</li>
<li>afdsaggrea</li>
</ul>
</td>
<td class="two">
<div class="three">
First div
<div>
Second div
</div>
</div>
</td>
</tr>
</table>
i.e. in my jsfiddle, the behavior I want is the green box filling the entire yellow box.
The reason your div wont grow when you assign it a height of 100% is that the parent doesn't have a height.
ie. You have a list that is causing the table to grow larger.
To remedy this, you can add a height to the parent cell and give the child a height of 100% as shown in this fiddle
.two{
background-color:yellow;
height:100px;
}
.three{
background-color:green;
height:100%;
}
You can add oveflow auto as well.
.three {
height: 100%;
overflow: auto;
}
It will work in some smart browsers like chrome. But it will be an issue in others because the parent doesnt have a known height at the time of rendering.
You can set height to your .two class and then height and overflow properties in .three class should fix your problem.
Or use javascript :)
If you don't want to have to set a concrete height, and you want it to work in all browsers, I added a nicely coded javascript solution to your forked JSFiddle.
var tableCritter = new function TableCritter(){
var critter=this;
var $window = $(window);
var $two = critter.$two = $('.two');
var $three = critter.$three = $('.three');
function adjustHeight(){
$three.css({ height:$two.height() });
};
adjustHeight();
$window.on('resize',adjustHeight);
critter.stop = function(){
$window.off('resize',adjustHeight);
};
};
What I am trying to do is the following.
I have a list of hidden images.
I have a button activated with Jquery onclick that replaces the html of a div to include the images
The button functions as a cycle button and gets a big list of images.
My problem is that the images do not scale to the size of the parent div. Even if I give them a .horizontal and .vertical class
Any ideas?
I want to keep the format of the hidden list of images inside a div because i do some other things with the lists. I originally thought that by having two classes for the images it will work and now that I am finishing I realised that the whole idea has a problem !
http://jsfiddle.net/alexnode/ttQHt/
HTML
<div id="artdiv2">
<div id="artslide1nextbutton">></div>
<div id="artslide1"></div>
</div>
<div class="hidden">
<div id="1slide1">
<img class="horizontal" src="http://farm8.staticflickr.com/7366/9160515864_7dc851a598.jpg" alt="Rezando a los antiguos Dioses - Praying to the old Gods">
</div>
<div id="1slide2">
<img class="vertical" src="http://farm6.staticflickr.com/5519/9158661396_4828a06655.jpg" alt="Drain">
</div>
</div>
Jquery
//i get everything called 1slide like that.
var artslides = $('[id^=1slide]');
idxs1 = 1;
//this is my button that cycles through the image
$("#artslide1nextbutton").on(
"click", function () {
$("#artslide1").html(artslides.eq(idxs1).html());
idxs1 = idxs1 == 1? 0 : idxs1 + 1;
});
CSS
.hidden{display:none;}
#artdiv2{ position:absolute; top:8%; left: 20%; height:70%; width:100%; background:DimGray;}
#artslide1nextbutton{position:fixed; top:0px; left: 0px; height:auto; width:10%; background:DarkRed;pointer:cursor;}
.horizontal {position:relative; width:100%; height:auto;}
.vertical {position:relative; height:100%; width:auto;}
EDIT : answer updated to fit closer to question.:
you could play width min and max value and center img with text-align:center.
demo
http://jsfiddle.net/ttQHt/2/
#artslide1 {
width:100%;
overflow:hidden;
height:100%;
text-align:center;
}
#artslide1 img {
min-height:100%;
max-width:100%;
}
Some other option to play with image
here is an idea of what happens if you can set line-height. http://codepen.io/gcyrillus/pen/BdtEj and adding min-width/min-height http://codepen.io/anon/pen/kfIbp
Use the JQuery variable .height() and .width()
I'm on mobile, so I can't try this myself, but what about putting a width and height attribute directly on the image elements, and using the button to just change the image source? That would make every image have the same width and height.
With refrence to this question and the accepted answer, I tried doing something similar.
.Content
{
position:absolute;
top:0;
left:0;
padding-top:75px;
width:inherit;
height:inherit;
}
.Header
{
position:absolute;
top:0;
left:0;
height:75px;
width:inherit;
background-color:Blue;
text-align:center;
}
<form id="form1" runat="server" style="width:100%;height:100%">
<div id="Content" class="Content">
<div id="Header" class="Header">
<h1 style="color:White">Report Portal</h1>
</div>
</div>
</form>
I want the content area to fill the entire page, no more. But vertical scroll bars appear for the web page with the above html. How can I correct that?
You shouldn't make the header absolute also remove the padding-top: 75px.
Consider this fiddle: link
EDIT: Updated fiddle: link
Do you have width and height set to 100% on the body and hmtl?
Also, the padding is creating a vertical scrollbar, remove this and it will work as expected.
http://jsfiddle.net/Kyle_Sevenoaks/MqKXH/
You have put Height > inherit for "Content".
CSS Inheritance (http://dorward.me.uk/www/css/inheritance/)
CSS inheritance works on a property by property basis. When applied to an element in a document, a property with the value 'inherit' will use the same value as the parent element has for that property.
Overall, "Content" height is already 100% of the browser which is inherited from "form" tag. After adding padding from top ie "75px" ..its total height becomes "browser height + 75px". It reasons to scroll the page.
Solution :
1] Avoid the top padding to "Content". Give that padding to its inner container
2] use style
body, html{
overflow:hidden;
}
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/