I have been trying to figure out how to format a list that has elements (in my case buttons) on the sides. The major problem that I have had is that I do not want the list text to wrap around the buttons, I want it to behave more like a table; text should not wrap into other columns. To complicate things a little further, I do not necessarily know the sizes of the 'Side Elements' in advance.
This is the code I came up with:
<div style='display: table;'>
<div style='display: table-row;'>
<div style='display: table-cell'>
<!--- Variable Width Left Side Element --->
</div>
<div style='display: table-cell; width: 100%;'>
List Text
</div>
<div style='display: table-cell'>
<!--- Variable Width Right Side Element --->
</div>
</div>
</div>
JSFiddle
I have tried this on Firefox, Chrome, Safari and Internet Explorer and it seems to work fine. However, I am still concerned because I do not entirely understand why this works (and I do not like using code that I do not understand). My concern is with width: 100%. Shouldn't this specify that the cell should take up the entire parent, rather than all the space available in that row?
Ultimately, my question is this: Can I trust using width: 100% like this? Is this an appropriate way of solving my problem?
Ultimately, my question is this: Can I trust using width: 100% like this? Is this an appropriate way of solving my problem?
Yes, you can.
Tables are funny that way...when a cell is given a width of 100% it just means take up as much space as you can out of what is left.
So you've already allocated some of the 100% of the parent so the middle div just grabs what's left.
For what it's worth...a `flex-box alternative:
.row {
display: flex;
margin-bottom: .5em;
}
.row div {
padding-left: 5px;
padding-right: 5px;
}
.row div:first-child {
flex-basis: 55px;
}
.row div:nth-child(2) {
flex: 1;
}
.row div:last-child {
flex-basis: 35px;
}
<div class="container">
<div class="row">
<div style="background-color: red"></div>
<div>This text is not too long</div>
<div style='background-color: blue'></div>
</div>
<div class="row">
<div style='background-color: red'></div>
<div>This text is very long. This text is very long. This text is very long. This text is very long. This text is very long. This text is very long. This text is very long. This text is very long. This text is very long. This text is very long.</div>
<div style='background-color: blue'></div>
</div>
</div>
JSfiddle Demo
when you are mixing both absolute and relative measurements, its good to use calc() function. So the width of the middle element will be,
width: calc(100% - 90px)
100% being the full width of parent and 90px being the absolute measurements with you are excluding (55px + 35px).
Browser will automatically compute the actual width of the element based on the parent width (which is the available width minus 90px). Directly giving 100% is not the correct way, imho.
The width of a table-cell depends upon its content. The cells will expand based on their content unless table-layout: fixed is given on the table.
Instead of using tables you can use floats for example follow this link http://jsfiddle.net/osha90/e57dja5u/
<div >
<div class="clearfix" style="margin:10px 0px">
<div style='width: 55px; height: 35px; background-color: red;float:left'>
</div>
<div style='width: 35px; height: 25px; background-color: blue;float:right'>
</div>
<div style="overflow:hidden;">
This text is not too long
</div>
</div>
<div class="clearfix">
<div style='width: 55px; height: 35px; background-color: red;float:left'>
</div>
<div style='width: 35px; height: 25px; background-color: blue;float:right'>
</div>
<div style="overflow:hidden;">
This text is very long. This text is very long. This text is very long. This text is very long. This text is very long. This text is very long. This text is very long. This text is very long. This text is very long. This text is very long.
</div>
</div>
.clearfix:after,.clearfix:before{
content: "";
clear: both;
display: block;
}
Because table rows can't wrap, table cell with 100% width will force the cell to occupy as much space as he can. You other two cell have fixed width, because their content have a fixed width, and the a table cell minimum width is the one required to display the content. This means that the 100% width actual width is 100% - the two fixed cell.
Related
This question already has answers here:
How to match width of text to width of dynamically sized image/title?
(2 answers)
Closed 3 years ago.
I have a fixed-position container element with two children. Both children contain text. I want one of the children to dynamically set the width of the container with its content. I want the other child's text to wrap appropriate based on that width.
For example:
.container {
position: fixed;
}
.wrap {
background: red;
}
.stretch {
background: green;
}
<div class="container">
<div class="wrap">
this text is very very long
</div>
<div class="stretch">
shorter text
<div>
</div>
In this example, I would like the container's width to match the shorter green .stretch div. I want the red .wrap div to have the same width, with the text wrapped inside, like:
The solution's come up with me was:
The child div needs to stretch its width depends on its content -> max-content
The parents's width needs to be as shrink as possible depends on its content -> min-content
The solution code with variant bahaviors:
.container {
width: min-content;
border: 2px solid blue;
margin: 5px;
}
.wrap {
background: red;
width: auto; /* default btw */
}
.stretch {
background: green;
width: max-content;
}
<div class="container">
<div class="wrap">
this text is very very long
</div>
<div class="stretch">
shorter text
</div>
</div>
<div class="container">
<div class="wrap">
shorter
</div>
<div class="stretch">
shorter text
</div>
</div>
<div class="container">
<span class="wrap">
shorter
</span>
<div class="stretch">
shorter text
</div>
</div>
You can read more about min-content and max-content from this answer or the specification.
max-content inline size: the narrowest inline size it could take while fitting around its contents if none of the soft wrap opportunities within the box were taken.
min-content inline size: the narrowest inline size a box could take that doesn’t lead to inline-dimension overflow that could be avoided by choosing a larger inline size. Roughly, the inline size that would fit around its contents if all soft wrap opportunities within the box were taken.
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.
I am new in designing and so have some problems...
I need 3 block to be inline and centered, so I tried:
#main .block{
display: inline-block;
border: 1px solid #ECEDE8;
margin: 10px 10px;
overflow: hidden;
height: 265px;
width: 265px;
}
But, when i add an image in to the block, all others goes down.
P.S.
As I see, this problem is in safari, in Firefox all ok.
P.S.S
<div id="main">
<div class="block">main
<img src="style/images/try.png">
</div>
<div class="block">main</div>
<div class="block">main</div>
<div class="block">main</div>
<div class="block">main</div>
<div class="block">main</div>
</div>
P.S.S.S
As I could figure it out thought Google, all problem is in display: inline-block, in safari works display: inline-table. What solution could be?
You need to set the vertical align property. In this case best option would probably be:
vertical-align: top
So your css should be:
#main .block{
display: inline-block;
border: 1px solid #ECEDE8;
margin: 10px 10px;
overflow: hidden;
height: 265px;
width: 265px;
vertical-align: top;
}
If your blocks are fixed width, why not float them instead and put them in a parent container with a total width and centered using margin: 0 auto
The div element is a block element. The img element is an inline-block element; it has the main features of a inline element (except that it has the block element features of height and width). Therefore, I see two main problems with your code. Firstly, your image is somehow meant to replace the same unit of space as where you as simultaneously displaying the word "main" which can cause a conflict with spacing/display. [I recommend deleting the word "main" from your HTML.] Secondly, you don't specify the height and/or width of the image, which is not really a problem since you have overflow value set to hidden, but still generally you should have a height and/or width value assigned (make them less than the parent container's height and width) as it will make the browsers rendering/displaying more universal/compatible cross-browsers. Implementing a combination of those two things [or of changing your display value to inline-table (which it kind of seems more like what you want since your display seems "tablular")] SHOULD fix your problem. If it doesn't, I would recommend changing your margin value to 0 auto (which will have the effect of centering your image in the middle of your div/parent container), because I have a lingering suspicion that your margin values may also be at play (but only if the other two suggestions don't work). Good luck!
PS: Remember that just because you have overflow: hidden doesn't mean that the browser doesn't "see" the element(s) that are overflowing. Remember the Box Model.
Try this -
<div class="main" id="main">
<div class="block">main
<img src="style/images/try.png">
</div>
</div>
<div id="main">
<div class="block">main</div>
</div>
<div id="main">
<div class="block">main</div>
</div>
<div id="main">
<div class="block">main</div>
</div>
<div id="main">
<div class="block">main</div>
</div>
And instead of #main .block{ just .main {
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>
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>