Table cell unnecessarily overflows wrapper in FF and IE - html

I tried to create a box with rotating content, simply using an outer box with a specified width and overflow: hidden, and inner boxes with display: inline-block; width: 100%. Everything worked as expected, until I added an image to each of the three "content boxes". Even though the images were narrow enough to fit well within the available space, the outer box' parent element now started overflowing its parent, in turn making the rotating box wider (since it had a relative width). The problem was the same in FF (28) and IE (11), but things were fine in Chrome.
In the end I boiled it down to this being a table layout issue, since adding table-layout: fixed on a table ancestor stopped the td parent of the rotating box to grow unneccessarily. (There are tables used for layout due to legacy reasons.)
What I wonder now is why this is happening, and if there is something wrong with my approach for the boxes. I've created a minimal example of the problem below (fiddle at http://jsfiddle.net/rvy2V/9/).
(In the example I use overflow: visible instead of hidden to make it easier to see what is going on. I also have whitespace between the inline blocks, which is bad for layout but good for clarity.)
HTML
<div id="wrapper">
wrapper
<table>
<tbody>
<tr>
<td id="cell">
table cell
<div class="niceBox slidePanes" id="outerBox">
<span class="slidePane">
.slidePane
<div class="body">
<div class="inner">inner box</div>
</div>
</span>
<span class="slidePane">
.slidePane
<div class="body">
<div class="inner">inner box</div>
</div>
</span>
<span class="slidePane">
.slidePane
<div class="body">
<div class="inner">inner box</div>
</div>
</span>
</div>
</td>
</tr>
</tbody>
</table>
</div>
CSS
.niceBox {
border: 1px solid #d7d7d7;
background-color: #f6f6f6;
}
.slidePanes {
overflow: visible;
white-space: nowrap;
}
.slidePanes .slidePane {
display: inline-block;
width: 100%;
white-space: normal;
vertical-align: top;
background-color: #bbf;
padding: 5px 0;
}
#wrapper {
width: 525px;
background-color: #888;
}
#cell {
background-color: #bbb;
}
#outerBox {
width: 50%;
}
div.inner {
width: 230px;
background-color: #f88;
}
Note in the fiddle how the table cell (medium gray) is wider than the wrapper (dark gray), but still not wide enough to contain all three content boxes (purple). Also note how, as a result, the rotating box (yellow border) is wider than the intended 50% of the wrapper. Also note how the inner boxes (red), which should be the widest thing in each content box, is not determining the width of each box.

Related

How do i force a table row with 100% width to use a scroll bar if it's children are overflowing?

I have a CSS layout problem. Here's a fiddle
I want a header and footer on the page, with the "content" taking up the rest of the available space. I was doing it with a JQUery plugin that calculated and set the height of the relevant element, but it wasn't playing nicley with some knockout things i had going on on the page so I decided screw that and use CSS.
Setting the sections to be table rows seemed to solve the problem of vertical expansion and the whole thing now nicley fills the page, but i have a table which is causing some issues.
When it has data in it it expands the width of the columns (i don't want the text to wrap). And that means the width of my wrappers also expand (thanks tables) I can't seem to hang a scrollbar on anywhere to prevent it happening.
My question is two fold:
Is there a better way of achieving the header/footer thing?
Can i get my scroll bar back?
The ideal solution would be in CSS rather than using JavaScript. I must support all browsers, including IE down to IE 8, and preferably IE 7.
The HTML:
<body>
<div class="page-wrapper">
<div class="section-wrapper">
<P>I want this at the top</P>
</div>
<div class="content-section section-wrapper">
<P>This is in the middle - taking up all the remaining space.</P>
<P>Making the wrapper a table-row solves the problem nicely...</P>
<div class="table-wrapper">
<table>
<thead>...</thead>
<tbody>
<tr>
But: In this table I have some data which causes the table to overflow the edge of the screen.
</tr>
<tr>
How do I make it have a scroll bar instead?
</tr>
</tbody>
</table>
<p>Ideally the scroll bar would go at the bottom of this section.</p>
</div>
</div>
<div class="section-wrapper">
<P>This goes at the bottom</P>
</div>
</div>
</body>
The CSS:
body, html{
width: 100%;
height: 100%;
}
.page-wrapper{
display: table;
height: 100%;
}
.section-wrapper{
display: table-row;
width: 100%;
background-color: lightGrey;
}
.content-section.section-wrapper{
height: 100%;
background-color: white;
}
table{
white-space: nowrap;
border-spacing: 20px 0;
border-collapse: separate;
}
.table-wrapper{
overflow: auto;
display: inline-block;
}
You could set a max width of the wrapper to the screen with, and make it a block display, then it should show a scroll bar if the table is wider than the available screen. Not sure if that was your question.
.table-wrapper{
max-width: 100vw;
overflow: auto;
display: block;
}
Also, to have the footer at the bottom, you could use flexbox on the page-wrapper.
.page-wrapper {
height: 100vh;
display: flex;
flex-flow: column nowrap;
}
.section-wrapper {
flex-grow: 1;
}
Updated fiddle: https://jsfiddle.net/211sgmjv/

Div growing outside of width constraint despite overflow:auto

I'm attempting to have a horizontally-scrolling (left-to-right) DIV in a dynamic width table cell (DIVs with display:table-cell). The scrolling DIV should be allowed to take up 100% of the containing element without causing it to grow beyond all ancestors' widths. I'd prefer to have a pure markup/CSS fix to this problem, without JavaScript or static widths.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3c.org/TR/1999/REC-html401-19991224/loose.dtd">
<html>
<head>
<style>
#page
{
width: 100%;
max-width: 500px;
}
.tcell
{
display: table-cell;
min-width: 150px;
padding: 10px;
}
#scrollbox
{
width: 100%;
height: 90px;
background-color: red;
overflow: auto;
}
#scrollcontent
{
background-color: green;
width: 900px;
height: 50px;
margin: 10px;
white-space: nowrap;
}
</style>
</head>
<body style="width:100%;">
<div id="page">
<div class="tcell" style="background-color: teal;">Hello world</div>
<div class="tcell" style="background-color: yellow;">
<div id="scrollbox">
<div id="scrollcontent"></div>
</div>
</div>
</div>
</body>
</html>
JSFiddle: http://jsfiddle.net/L69qJ/
The issue is visible in IE8, Chrome, Firefox, and Safari.
In this example, the yellow div is being forced to grow beyond it's container (we expect the entire page to be no larger than 500px. See the max-width style for #page) because the red DIV isn't respecting overflow:auto and therefore trying to expand to show the green DIV completely.
Expected behavior: I'd like for the teal and yellow cells to add up to 100% of their parent (#page). The green cell is so wide that it's making the red cell expand, which is making the yellow cell expand. It's expected that the red cell use a horizontal (left-to-right) scrollbar instead of making the yellow cell expand.
display:table;
table-layout:fixed;
to #page.
There it is:
http://jsfiddle.net/L69qJ/8/
To answer your question, the problem is that you are using table-cells. Table cells inherently take the shape of their children, so if you set something wide inside of a table cell, you can't just add a width to the table cell and expect it to follow that rule. You need to transition to using percentage width inline divs, or floats to achieve your layout.

CSS column layout - DIV with dynamic width and same height as sibling

I've really hit the wall on this one and need some help. I'm trying to create a two column layout with both widths and heights adjusted to the contents of the left column. It seems to be a rather basic layout, but I'm starting to think it can't be done (without resorting to JS).
This fiddle describes what I'm trying to do. It's a container DIV with two DIVs inside, aligned horizontally. The left inner DIV should adjust its size (both width and height) to its content. The right inner DIV (which contains a Google Map) should have the same height as the left one while filling up the remaining width of the container.
<div id="container">
<div id="left">
This DIV should adjust<br/>
both its width and height<br/>
to its content, not taking up<br/>
more space than needed!<br/>
<br/><br/><br/>
More content here...
</div>
<div id="right">
Google Map here.
</div>
</div>
I've tried everything I know and all tricks I've found, but no success!
#container {
background-color: #EEE;
overflow: hidden;
}
#container div {
border: 1px solid black;
padding: 5px;
}
#left {
background-color: lightblue;
display: inline-block;
float: left;
}
#right {
background-color: lightgreen;
height: 100%; /* THIS IS WHAT I WANT, BUT IT WON'T WORK, OF COURSE */
overflow: hidden;
}
I've found many similar questions, but in all those cases the left DIV/column had a fixed width, which makes it a whole lot easier.
Any input is much appreciated, especially if it works in IE9+ (and modern browsers)!
Edit
Some clarification. The purpose of the right column is to hold a Google map and consequently the map is supposed to fill up the entire DIV. Try setting a fixed height (e.g. 100px) for #right in the fiddle that I link to above and you will see the map showing up.
jsfiddle demo
css :
.container {
overflow: hidden;
background-color: #EEE;
}
.column {
float: left;
background-color: grey;
padding-bottom: 1000px;
margin-bottom: -1000px;
}
p {
padding: 10px;
margin-top: 10px;
width: 50%;
}
html
<script src="//maps.googleapis.com/maps/api/js?sensor=false"></script>
<div class="container">
<div class="column">
This DIV should adjust<br/>
both its width and height<br/>
to its content, not taking up<br/>
more space than needed!<br/>
<br/><br/><br/>
More content here...
</div>
<div class="column">
<div id="map"></div>
</div>
</div>
<p>
The right DIV (which contains a Google Map)
should be the same height as the left DIV,
while filling up the remaining width.
</p>
<p>How to do that?</p>
Here what I came up with -> link
When you remove the overflow property of your #right div it stretches as expected. However in this case you won't be able to hide the overflowed content.
CSS
#right {
background-color: lightgreen;
height: 100%; /* THIS WON'T WORK */ // height works as expected
}

CSS to simulate tables: inline divs which also have borders and break text?

I'm trying to float two divs inline with each other inside a div of set width. Additionally they have borders and content that requires wrapping. It stops working when there's more content than fits on one line.
I'm trying to be avoid using tables to solve this (see solution below) but but no luck so far. Any one got any ideas?
Edited question: expanding requirements to include:
the divs should minimise their total width and not expand beyond the boundarys of the two main 50% columns. I've managed to achieve the first and second part (please see my own answer below) however I have an additional third requirement in that as these can be nested, the content then still stays within the two main columns but doesn't expand to fill up to a maximum width of 50% of the columns width. I'm working on a javascript solution which I won't be able to post back for some time.
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Demo</title>
<style>
body {
width: 1024px;
}
.a_column {
width: 50%;
float:left;
}
.some_text {
float:left;
display:inline;
border: thin solid green;
}
.a_block {
float:left;
display:inline;
border: thin solid red;
/*width: I can't set this as I don't know how much some_text will need, this can vary from nothing to a lot.*/
word-wrap: break-word; /* this doesn't work without a width specified*/
}
/*solution when using tables */
.some_text_in_table, .a_block_in_table {
vertical-align:top;
}
.some_text_in_table div {
border: thin solid green;
}
.a_block_in_table div {
border: thin solid red;
word-wrap: break-word;
}
</style>
</head>
<body>
<div class="a_column">
<div class="some_text">
some text here.
</div>
<div class="a_block">
Less text and there's no problem.
</div>
</div>
<div class="a_column">
<div class="some_text">
some text here.
</div>
<div class="a_block">
Putting a lot of text into a div that you want a border around will
cause it to move down one line. Instead I'd like it to float inline
with its sibling div; you can remove the float:left but then it
completely messes up the border. An_additional_thing_I'd_like_is_for_long_sentences_to_be_broken_by_the_word_wrap,_but_this_requires_that_the_width_of
a_column be set and I can't do this as I don't always know how much
room some_text will need.
</div>
</div>
<div style="clear:both;"></div>
<h3> With tables, solution with in 7 minutes. So much easier:</h1>
<table style="table-layout: fixed; width: 100%;">
<tr>
<td colspan="2" style="width: 50%;">
</td>
<td colspan="2" style="width: 50%;">
</td>
</tr>
<tr>
<td class="some_text_in_table">
<div>
some text here.
</div>
</td>
<td class="a_block_in_table">
<div>
some text here.
</div>
</td>
<td class="some_text_in_table">
<div>
Less text and there's no problem.
</div>
</td>
<td class="a_block_in_table">
<div>
Putting a lot of text into a div that you want a border around will cause it to move down one line. Instead I'd like it to float inline with its sibling div; you can remove the float:left but then it completely messes up the border. An_additional_thing_I'd_like_is_for_long_sentences_to_be_broken_by_the_word_wrap,_but_this_requires_that_the_width_of a_column be set and I can't do this as I don't always know how much room some_text will need.
</div>
</td>
</tr>
</table>
</body>
</html>
Fiddle with my code here: http://jsfiddle.net/cdepZ/
display:table-cell;
Example: http://jsfiddle.net/TAhAv/
You are right in wanting to avoid tables with this layout - as you mentioned, this is not tabular data which you are chosing to display.
You mention in your CSS that you cannot set a width on .a_block because you do not know how much space you need. However, when you use a table you are actually setting a width (25%) as each cell is equally split amongst the over-all width.
So to achieve what you want to do (which will match the tables layout), you will have to set a width on these elements.
Here is a JSFiddle of how you could achieve this:
http://jsfiddle.net/ndhrd/39/
Set your widths properly with the space you have. Borders take 2px vertically and horizontally as well.
.a_column {
width: 512px;
float:left;
}
.a_block, .some_text{
width: 254px;
float: left;
word-wrap: break-word;
}
.a_block{
border: 1px solid green;
}
.some_text{
border: 1px solid red;
}
I got it working here:
http://jsfiddle.net/cdepZ/7/
Putting a lot of text into a div is now no problem, it will wrap and break any long sentences that go over 50% of it's parent divs' width. And it will minimise any content that it can whilst maintaining good looking borders.
Nesting this structure can keep it with in the limits of the .a_column but then doesn't allow all elements to expand fully.
I think the only solution is a javascript one :|
http://jsfiddle.net/uHEVJ/1/
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Demo</title>
<style>
body {
width: 1024px;
}
.a_column {
width: 49%; /* 49% rather than 50% to cope with the 1 pixel width borders*/
float:left;
border: thin solid blue;
}
.a_container{
display:inline;
}
.a_container > div{
max-width: 49%; /* 49% rather than 50% to cope with the 1 pixel width borders*/
float: left;
word-wrap: break-word;
}
.some_text {
border: thin solid green;
}
.a_block {
border: thin solid red;
}
</style>
</head>
<body>
<h3> Used a "display:inline;" div as a container to position each Div inside which has float:left (to minimise it's size)</h3>
<div class="a_column">
<div class="a_container">
<div class="some_text">
some text
</div>
</div>
<div class="a_container">
<div class="a_block">
Less text and there's no problem.
</div>
</div>
</div>
<div class="a_column">
<div class="a_container">
<div class="some_text">
some text here.
</div>
</div>
<div class="a_container">
<div class="a_block">
Putting a lot of text into a div is now no problem, it_will_wrap_and_break_any_long_sentences_that_go_over_50%_of_it's_parent divs' width. And it will minimise any content that it can whilst maintaining good looking borders
</div>
</div>
</div>
<div class="a_column">
<div class="a_container">
<div class="some_text">
Nesting this structure can keep it with in the limits of the .a_column but then doesn't allow all elements to expand fully.
</div>
</div>
<div class="a_container">
<div class="some_text">
Nesting this structure can keep it with in the limits of the .a_column but then doesn't allow all elements to expand fully.
<div>
<div class="a_container">
<div class="a_block">
some text
</div>
</div>
<div class="a_container">
<div class="a_block">
Nesting this structure can keep it with in the limits of the .a_column but then doesn't allow all elements to expand fully.
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>

How to make a stable two column layout in HTML/CSS

I want a container with two columns. Details:
The container
Width should adjust to 100% of its parent element (easily accomplished).
Height must adjust to contain both columns (i.e. its height should be exactly equal to the larger height of the two columns, so there is no overflow and scrollbars never show)
Should have a minimum size equal to double the width of the left column.
The columns in general
Should be of variable height, adjusting to the height of their content.
Should be side-by-side, such that their top edges are in line.
Should not break the layout or wrap under each other if even a single pixel of border, padding, or margin is applied to either one, because that would be extremely unstable and unfortunate.
The left column specifically
Must have a fixed, absolute width in pixel units.
The right column specifically
Width must fill the remaining space in the container. In other words...
Width must equal the container width minus the width of the left column, such that if I place a DIV block element inside this column, set its width to 100%, give it a height of something like 10px, and give it a background color, I will see a 10px high colored strip that goes from the right edge of the left column to the right edge of the container (i.e. it fills the right column's width).
Required stability
The container should be able to resize (by resizing the browser window) down to its minimum width (specified earlier) or to a much larger width without breaking the layout. "Breaking" would include the left column changing size at all (remember it's supposed to have a fixed pixel width), the right column wrapping under the left one, scrollbars appearing, block elements in the right column failing to take up the entire column width, and in general any of the aforementioned specifications failing to remain true.
Background
If floating elements are used, there should be no chance that the right column will wrap under the left one, that the container will fail to contain both columns (by clipping any part of the column or allowing any part of the columns to overflow its boundary), or that scrollbars will appear (so I'd be weary of suggesting the use of anything other than overflow:hidden to trigger floating-element containment). Applying borders to the columns should not break the layout. The content of the columns, especially of the right column, should not break the layout.
There seems to be a simple table-based solution to this, but under every circumstance it fails miserably. For example, in Safari, my fixed-width left column will shrink if the container gets too small, rather than maintaining the width I specified. It also seems to be the case that CSS width, when applied to a TD element refers to a minimum width, such that if something larger is placed inside it, it will expand. I've tried using table-layout:fixed; doesn't help. I've also seen the case where the TD element representing the right column will not expand to fill the remaining area, or it will appear to (for example a third column 1px wide will be pushed all the way to the right side), but putting a border around the right column will show that it's only as wide as its inline content, and block-level elements with their width set to 100% do not fill the width of the column, but rather match the width of the inline-content (i.e. the width of the TD seems to be completely dependent on the content).
One potential solution I have seen is too complex; the solution needs to work in IE8, Firefox 4, and Safari 5.
Here you go:
<html>
<head>
<title>Cols</title>
<style>
#left {
width: 200px;
float: left;
}
#right {
margin-left: 200px;
/* Change this to whatever the width of your left column is*/
}
.clear {
clear: both;
}
</style>
</head>
<body>
<div id="container">
<div id="left">
Hello
</div>
<div id="right">
<div style="background-color: red; height: 10px;">Hello</div>
</div>
<div class="clear"></div>
</div>
</body>
</html>
See it in action here: http://jsfiddle.net/FVLMX/
Try this: Live Demo
display: table is surprisingly good. Once you don't care about IE7, you're free to use it. It doesn't really have any of the usual downsides of <table>.
CSS:
#container {
background: #ccc;
display: table
}
#left, #right {
display: table-cell
}
#left {
width: 150px;
background: #f0f;
border: 5px dotted blue;
}
#right {
background: #aaa;
border: 3px solid #000
}
Piece of cake.
Use 960Grids Go to the automatic layout builder and make a two column, fluid design. Build a left column to the width of grids that works....this is the only challenge using grids and it's very easy once you read a tutorial. In a nutshell, each column in a grid is a certain width, and you set the amount of columns you want to use. To get a column that's exactly a certain width, you have to adjust your math so that your column width is exact. Not too tough.
No chance of wrapping because others have already fought that battle for you. Compatibility back as far as you likely will ever need to go. Quick and easy....Now, download, customize and deploy.
Voila. Grids FTW.
Over 11 years later. Apply display:grid to the container and divide the available space by grid-template-columns: 100px 1fr. Where 1fr represents a fraction of 100% of the remaining space.
<html>
<head>
<title>Cols</title>
<style>
#container {
display: grid;
grid-template-columns: 100px 1fr;
}
</style>
</head>
<body>
<div id="container">
<div id="left">
Hello
</div>
<div id="right">
<div style="background-color: red; height: 10px;">Hello</div>
</div>
</div>
</body>
</html>
As suggested by mtmurdock it is possible to remove the .clear rule and move it to the pseudo-element #container::after.
<html>
<head>
<title>Cols</title>
<style>
#left {
width: 200px;
float: left;
}
#right {
margin-left: 200px;
/* Change this to whatever the width of your left column is*/
}
#container::after {
clear : left;
display: block;
content: '';
}
</style>
</head>
<body>
<div id="container">
<div id="left">
Hello
</div>
<div id="right">
<div style="background-color: red; height: 10px;">Hello</div>
</div>
</div>
</body>
</html>
Another idea is to include the left div in the right div,
which in turn coincides with the line container:
[right][left] ... [/left] ..... [/right]
x { border: thick solid navy; padding: 2px; }
.lineContainer, .container > p {
padding-left: 100px;
margin: 0;
line-height: 1.5;
}
.left, em {
margin-left: -100px;
display:inline-block; box-sizing: border-box; width: 100px;
vertical-align: top;
}
.div-in-div {
display:inline-block; box-sizing: border-box; width: 100%;
vertical-align: top;
}
<h3>Layout: div-left is contained within the right-div / lineContainer</h3>
<pre>
[right][left] … [/left] … [/right]
</pre>
<div class="lineContainer" style="background:floralwhite; "><div class="left">Hello</div>Hello there</div>
<p>Using the above scheme,
we can make old-fashioned typewriter tab stops as shown here.</p>
<h3>The Capital Cities of the UK</h3>
<div class="container" style="background-color: floralwhite; ">
<p><em>England</em> - The capital is London.</p>
<p><em>Scotland</em> - The capital is Edinburgh.</p>
<p><em>Wales</em> - The capital is Cardiff.</p>
<p><em>Northern Ireland</em> - The capital is Belfast.</p>
<p><em>The capital of the UK is</em> - London.</p>
<p><em>Source</em>- Project Britain, capitals.</p>
</div>
<h3>Div in div</h3>
<div class="lineContainer" style="background:floralwhite; ">
<div class="left">Div in container</div><!--No white space here
--><p class="div-in-div" style="background: red; font-size: x-large; margin: auto 0; ">Hello there</p>
</div>