Prevent text from expanding div without JS or table-caption - html

My issue is solved using display:table-caption but that seems incorrect (since it's not actually a table caption). So my question is what is table-caption doing that solves my issue, and can that be achieved with different CSS?
My original issue: I have a container div and within that are header, details, and footer divs. The header (and less importantly footer) text should remain on a single line (no wrapping) and the container div should shrink-wrap (expand and shrink width) to fit those single line elements. However, the details div should NOT be allowed to expand the container div. Instead the details text should simply wrap as per whatever width the container happens to be (which would be a result of the length of the header and/or footer text).
I have found that this seems to be achievable using the display:table-caption style.. however this doesn't seem like an appropriate style to use (on something that isn't a table caption).
See example: https://jsfiddle.net/uac032q4/1/
Note the display: table-caption in the .container's style.
.container {
display: table-caption;
background-color: white;
}
.heading {
font-size: 4em;
}
.details {
background-color: yellow;
}
.nowrap {
white-space: nowrap;
}
<div class="container">
<div class="heading nowrap">Strech Dont Wrap</div>
<div class="details">
This is the paragraph that should wrap down once it reaches the available width provided by the container box which in turn is stretched to that width by the nowrap heading text.
</div>
<div class="nowrap">Footer</div>
</div>
So, using only CSS (no JS) and without fixed widths: is there an alternate CSS solution without using table-caption? and what is table-caption doing that is solving the wrapping issue?
Note that there is an existing question that is essentially the same thing, however the accepted answer uses JS and the alternate answer uses display:table-caption:
Prevent text from expanding shrink wrapped div

Related

Why is my inner div with display:block pushed down inside a parent with display:inline?

I have the following HTML+CSS
<div>
<div class="first">text</div>
<div>more text</div>
</div>
div {
display: inline;
}
.first {
display: block;
}
The, somewhat surprising, result of that, is that before the first item, I'm getting an empty line (in Chrome and Firefox anyway).
I'd appreciate someone explaining to me why that happens if the first div inside an inline parent has display: block;
here's a jsfiddle demonstrating the problem
http://jsfiddle.net/kkozmic/fsm9D/1/
As far as I know, you should not embed block elements within inline elements. Block elements use the whole width while inline elements do not - they just use width enough to show text within them
http://www.w3.org/TR/REC-html40/struct/global.html#block-inline
EDIT: Here's a good explanation http://skypoetsworld.blogspot.in/2008/10/dont-ever-put-block-inside-inline.html
Ok the first item contains display: block; according to the definition a block element is an element that takes up the full width available, and has a line break before and after it.
That's why you get a empty line before first element

Make div fill remaining space of parent

I need some help with positioning divs. The HTML structure is as follows:
<div class="container">
<div class="item">
<div class="left">
lorem lorem
</div>
<div class="right">
<p>right</p>
<p class="bottom">bottom</p>
</div>
</div>
</div>
And I have the following CSS:
.container {
float: left;
padding: 15px;
width: 600px;
}
.item {
float: left;
padding: 15px;
width: 570px;
}
.left {
float: left;
padding: 40px 20px;
margin-right: 10px;
}
.right {
position: relative;
float: left;
}
.bottom {
position: absolute;
bottom: 0;
}
The width and height of the left div is dynamic.
What I want to achieve is:
Make the height of the right div equal to height of the left div.
Make the width of the right div fill the rest of the div with class item.
The paragraph with class bottom should be at the bottom of the right div.
Here is a simple image that represents my goal:
And a link to a JSFiddle demo.
Getting the correct position and width of .bottom appears to be the biggest hurdle for a cross-browser, CSS solution.
Options
1. Floats
As #joeellis demonstrated, the flexible widths can be achieved by floating only the left column, and applying overflow:hidden to the right column.
The position of .bottom cannot be achieved in any browser. There's no CSS solution for floated columns with equal, variable height. An absolutely positioned .bottom element must be inside the right column div, so that 100% width would give it the correct size. But since the right column won't necessarily be as tall as the left column, positioning .bottom with bottom:0 won't necessarily place it at the bottom of the container.
2. HTML tables and CSS tables
The flexible widths can be achieved by giving the left cell a width of 1px and not specifying a width for the right cell. Both cells will grow to fit the content. Any extra space will be added to the right cell alone.
If .bottom is inside the right table cell, the position can't be achieved in Firefox. Relative position has no effect in a table cell in Firefox; absolute position and 100% width would not be relative to the right table cell.
If .bottom is treated as a separate table cell in the right column, the correct heights of the right and bottom table cells cannot be achieved in any browser other than Firefox. Table cells aren't flexible in height the same way they are in width (except in Firefox).
3. CSS3 flexbox and CSS3 grids
Flexbox and grids are the promising layout tools of the near future. But flexbox isn't supported by IE9 or earlier, and grids aren't supported by any browser other than IE10. Haven't tested if either can achieve this layout, but browser support may prevent them from being an option at present.
Summary
Floats don't offer a solution for any browser.
HTML tables and CSS tables don't offer a cross-browser solution.
Flexbox doesn't offer a potential solution for IE9 or earlier (and may or may not offer a solution to other browsers).
Grids only offer a potential solution to IE10 (and may or may not offer a solution there).
Conclusion
There doesn't appear to be an adequate CSS solution at present, one that would work in enough relevant browsers, with the possible exception of flexbox (if support for IE9 and earlier isn't required).
jQuery
Here's a couple modified demos that use jQuery to force the columns to have the same height. The CSS and jQuery for both demos is the same. The HTML only differs by how much content is in the left and right column. Both demos tested fine in all browsers. The same basic approach could be used for plain JavaScript.
Taller content on the left
Taller content on the right
To keep things simple, I moved the internal padding for the left and right div to a child element (.content).
Sibling elements of same height and staying on the same row can be achieved by displaying them as table-cell and parent as display: table.
Working fiddle: http://jsfiddle.net/SgubR/2/ (which also display the overflow: hidden along a floating element technique for creating a column. The latter needs a clearfix)
Table-cell in CSS uses any HTML element you want (section, div, span, li, whatever), its semantics is unrelated to table, tr and td elements used for table layout (except that the visual result is the same, that's what we want).
display: table is set on a parent
display: table-row may be used on an element in-between but if it works without it, fine
display: table-cell is set on each child
a width is set on none, some or all these "cells". Browser will adapt both to content and widths set in order to calculate their widths (and total width of parent, obviously)
table-layout: fixed will tell browsers to switch to the other table layout algorithm where they don't care about the quantity of content, only to widths set by CSS
vertical-align: top will be needed in most cases (but you may set other values, great for complex layouts)
margins aren't applied on "cells", only padding. Margins only apply on table itself. Though you still can separate "cells" with border-collapse: separate and/or border-spacing: 4px 6px
Compatibility: IE8+
Fallback for IE6/7 if needed is exactly the same as for inline-block
Longer explanations in previous answers: here and there with also the good old method of faux-columns (your design must be thought with this technique in mind)
Just add an oveflow to the right column and don't float it.
.right {
position: relative;
overflow: hidden;
}
This will make right to fill the rest of the width.
Something like this might work:
http://jsfiddle.net/PCvy9/2/
The main key of what you're looking for lines in the:
.right {
overflow: hidden;
background-color: #C82927;
}
This is due to something called the "block formatting context." Great reasoning and tutorial as to why here: http://colinaarts.com/articles/the-magic-of-overflow-hidden/#making-room-for-floats
However, their heights are not completely linked; in this example, your left side block's height would still need to be manually set (as it's a floated container)

Using inline-block display without the content floating left

I want the width of a div element to be equal to the width of the content inside it, and also (and more importantly) that any content after this div does not start to the right of the div(as though the div was float:left;), but display below the current div.
I know one way is that after this div, I create another empty div and set clear:both;, but in my case that would not be very preferable.
I think that the following may be close to what you need:
The HTML demo code is:
<div>
Some text may be before the element.
<div id="info">This is my bible!</div>And some text may follow. the element.
</div>
And the CSS styles are:
#info {
display:inline;
background-color:#CFFF9F;
color:black;
font-weight:normal;
border:black solid 1px;
}
#info:after {
content:"\A";
white-space: pre;
}
Fiddle reference: http://jsfiddle.net/audetwebdesign/6FNQc/
Explanation of How This Works
Use :after to generate some content (known as a pseudo-element in CSS). The "\A" is interpreted as a line break (linefeed) provided that the white space is preserved, hence you need to set white-space: pre. Finally, the element has to be inline, hence display: inline.
Related References:
CSS to line break before/after a particular `inline-block` item
To learn more about "\A" (linefeed), see:
http://www.w3.org/TR/CSS21/syndata.html#strings

Vertical middle for an element within a variable height container

I have the following situation:
A variable height div (#container) with an image on the inside (image that is placed within another div) that I need to float:right and align vertically in the middle. How to do this?
Thanks.
EDIT:
Maybe I didn't make it clear enough that i do not know beforehand how much content the container has, from a few lines to a wall of text, so any solution relying on its height won't work (and that's my problem :P)
This is a fiddle with an example of possible content to which align the image: http://jsfiddle.net/9DbmN/
You should take a look at Centering in the Unknown by Chris Coyier. Imo it´s a pretty solid solution to the holy grail of vertical centering.
I would not discourage using tables here))) If you use a two-cell table with vertical-align: middle set on its td elements - it will perfectly (and easily!!!) solve your problem.
If you want to have two containers, one of which (the one with the image) will be floated to the right and needed centering - I'd say you'll have to avoid using float property for this. Because a) as far as I understand you don't need you content on the left to be UNDER the image, right? b) floats are block-level elements and you can't change it even if you set display: table-cell, the browser will still render it as display: block - which leads me to the conclusion that you won't manage to center it by css (at least by the means I'm aware of).
If you don't need ie7 support a possible workaround might be this:
html:
<div id="container">
<div class="content">Content goes here, vertically aligned with the image</div>
<div class="i_used_to_be_floated_right">Image goes here</div>
</div>
css:
#container {
display: table;
width: 100%;
}
.content, .i_used_to_be_floated_right {
display: table-cell;
vertical-align: middle;
}
.content {
background: green;
width: 80%;
}
.i_used_to_be_floated_right{
background: red;
width: 20%;
}
The working example live can be seen here: http://jsfiddle.net/skip405/sDXMj/1/
But if you need ie7 - I would vote for the table-solution I stated at the very beginning.

How can I make my DIV just the size of the text it encloses

I have this code:
<div id="one">
<div id="two">my text here</div>
</div>
I have styled the div with id=two and put a box around it. The problem is that it doesn't enclose the text but instead expands to the width of the outer DIV. Is there a way I can make it just size to match the text without specifying width?
You can either
#two {
display: inline; /* or 'inline-block' */
}
Or:
#two {
float: left; /* or right */
}
display: inline; stops the div being displayed as a block-level element, causing it to collapse (for want of a better word) to the size of its contents. If you use the alternative display: inline-block then the div retains its ability to have a defined width and height, which may be required for your layout. However it's worth noting that Internet Explorer 6 and 7 only accepts display: inline-block for those elements that are 'naturally inline.'
float has much the same effect; but using float might/will obviously affect the layout of the page, and may need to be cleared by subsequent elements.
display:inline-block;
This way you keep the block behaviour of your div.