I would like a way to prevent columns of flowing text from becoming too narrow. For example, in a column of HTML text, there is an image floated to the left. Text flows down the right-hand side of the column around the image, as expected:
However, if the image is almost as wide as the column, then the text ends up being very narrow:
In this case I want the text to simply not flow past the image, but to drop below it as if the image were a block:
I am trying to find a simple and general way of doing this. It's for a blog - I want to be able to add the image and text, maybe add a class or paste in a bit of markup (sigh), and have the flow work. I would prefer to do it with CSS and HTML only because it's hard to insert JavaScript to the blog posts. I have a couple of methods (see my answers) but neither is satisfactory. Can you do better?
When you set display: inline-block; to an element, the element will be flowed with surrounding content.
So you would need to add a line-break <br> to produce a line break in text, but the vertical space of the line will remains as you mentioned. [and one more thing happens is the horizontal scroll-bar which will appear if you decrease the width of the panel.]
Introduction
Using <table></table> element has a lot of benefits here.
When you use <table> element (as the following), it causes the content goes to the next line. And when the remain horizontal space gets lower than width of the <table>, it'll go to the next line and push the content down.
And also, horizontally scroll-bar won't appear in this case, because browsers won't display the <table> when it hasn't any element inside or any specific height or border properties.
(different browsers have different behavior, Mozilla Firefox doesn't display table element with a specific border property but Google Chrome does.)
HTML:
<img src="http://placehold.it/100x50" alt="">
<table></table>
Lorem ipsum dolor sit amet...
CSS:
img { float: left; }
table { width: 12em; }
Here is the JSBin Demo.
The Solution
As a pure CSS way, I used ::before pseudo-element to create a element which behaves like the <table> HTML element.
HTML:
<div>
<img src="http://placehold.it/400x400" alt="">
<p class="content">
<!-- Here is the content... -->
</p>
</div>
CSS:
img { float: left; }
.content:before {
content: ' ';
display: table;
width: 10em; /* <-- Change the current width size */
}
Here is the JSBin demo.
A better solution is to give every paragraph an invisible CSS pseudo-element with the desired minimum paragraph width. If there isn't enough space to fit this pseudo-element, then it will be pushed down underneath the image, taking the paragraph with it.
If the img is flot: right, add clear: left to the p:before.
And if the img is float: left, add clear: right to the p:before
p:before {
content: "";
width: 10em;
display: block;
overflow: hidden;
clear: left; //use clear:right if img is float:left
}
I tried adding an extra element before the text. I think this would probably just about work. Something like this:
<style>
.shim { display: inline-block; height: 0; width: 12em; }
</style>
<img class="floated">
<div class="shim"></div><br>
If one examines Derridaist reading...
This is OK - if the flow column is narrow then the shim drops below the image and the text follows it. I have to add the <br> to stop the text being indented by 12 ems, which adds a line of vertical space. I guess I could reduce the line-height on the <br>but the whole thing might end up being a bit verbose.
The simplest method I found is to set the minimum width of the column by preventing the first few words from wrapping:
<style>
.chunk { white-space: nowrap; }
</style>
<p><span class="chunk">If one examines</span> Derridaist reading...
This works well, but:
I have to manually edit the text each time I do this
I can't precisely control the column width (in ems or pixels)
Related
I know this is probably really simple, but i'm stuck on it for a while trying fiddle around with it.
Basically, this is my html setup :
<div id="main-div"><!-- Blue -->
<div id="sub-div"><!-- Red -->
<div class="content-div">
<p>This is the text. I need the button to be placed in content-div, which technically is, but it appers outside the div.</p>
BUTTON
</div>
</div>
</div>
Here is the fiddle with the CSS classes :
http://jsfiddle.net/03knuf7z/1/
What I'm trying to achieve is to have the <p> paragraph and <a> button both inside the sub-div surrounded by main-div
I've been trying to achieve this without a fixed content-div height, so I'm trying to put in height: auto; into my css hoping the content-div will stretch enough to cover both <p> and <a> elements, but that doesn't do the job, because the button still appears outside the content-div box, just like in the fiddle.
I can achieve the desired result by putting fixed height to the content-div, so if I'll change the auto in height: auto; to height: 150px;, it works and both elements, the paragraph and the button are in the box.
But thinking of responsivity on small screen devices, phone screens for example, I'd like to avoid fixed values.
Is there a way to do this without fixed height ?
You need to add an element with clear after the button with float.
You can add this to the HTML, or use the CSS :after pseudo-element to create a virtual element at the end of your content-div:
.content-div:after {
content:'';
clear:both;
display:block;
}
Updated fiddle
This can be fixed easily with a clear class. I have updated your JSFiddle.
I have added the following class:
.clear {
clear: both;
}
And this after your button:
<div class="clear"></div>
You can also use the :after property. Then you will have the use the following CSS:
.content-div:after {
display: block;
content: " ";
clear: both;
height: 0;
}
Add overflow-hidden; to .content-div.
.content-div{
font-size: 18px;
overflow: hidden;
}
So I have two pictures that describe the problem. They're below.
The only relevant css is this:
h1 {
display: inline-block;
background-color: pink;
}
In example one, the title (which is an <h1> tag) is short enough that it hasn't wrapped. As you can see from the background color, the tag's width is only as wide as the letters it contains. This is what I want all the titles to look like.
Here, the text has word-wrapped and the tag's width is not the width of the text, it is 100% of the container. (I know the text itself is almost the width of the container, but not quite--there's a little room)
So, I'm looking primarily for an explanation of what is going on. Is wrapped text always going to effectively have width: 100%;? Is there any way around this limitation?
Here's a fiddle that demonstrates the same thing.
Thanks!
You could change your css to:
h1 {
display: inline;
background-color: pink;
}
JSFiddle here
Now looks like:
Edit: Since you're not too keen in the display:inline idea, you could wrap your text in a span element, and put the background colour on that element instead.
eg:
h1 {
display: inline-block;
}
span {
background-color: red;
}
<div class="container">
<h1><span>Mine eyes have seen the glory of the coming of the lord</span>
</h1>
<h1><span>frog</span></h1>
</div>
Your Updated JSFiddle here
I've got the following layout:
<article>
<h3><a>...</a></h3>
<h3><a>...</a></h3>
</article>
The first header has dynamic content, the second has a fixed width set.
I'd like the headers to be inline, and when the content of the first one grows, for it to stretch until the sum of both headers' widths is 100%, and then for overflow text to be ellipsis.
I've been running into the problem of once I make the first div inline or float, its width no longer stays contained by the parent, making text overflow everywhere, or with overflow set to hidden, I can't get the second header to be positioned on the same line with it.
P.S.: Unfortunately this will need to support as many old browsers as possible, back to I.E. 6 would be the best (/barf) but whichever solution reaches as far back as possible will be the most valuable. Thanks you!
If I understood the question right, it's easily achievable with flexible boxes:
article {
display: inline-flex;
width: 100%;
}
article > h3:nth-child(1) {
flex: 1;
}
article > h3:nth-child(2) {
flex: 0 0 150px;
}
a {
width: 100%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
display: inline-block;
}
JSBin.
If I'm understanding the issue properly, the following JSFiddle may have the solution:
http://jsfiddle.net/modenadude/QntUm/2/
The code:
keeps the two <h2>s inline
if the width of the first <h2> gets wider than the width of the second <h2> + <article>'s width, it adds the ellipses to the first <h2>
I set max-width on the <h2>s (to 50%) just in case, and added outline to show the widths clearly.
I used jQuery to figure out the widths of the <h2>s onload, but the same can be done with pure JS by using getElementByID (I can set that up too if you'd like). And of course it was designed to be used on only two <h2>s and one <article> so simple editing could make it more expandable.
I have a div in which there are rows of 3 images each. The images are all the same size. I had been using small completely clear transparent image which I would then explicitly give height and width to form spaces between the images. An example would be something like :
div begin
space image width=15, height=1 actual image (no explicit dimensions)
space image width=10, height=1 actual image (no explicit dimensions)
space image width=10, height=1 actual image (no explicit dimensions)
space image width=900, height=20 (this is to separate rows, which should be 900 wide, space + 3 x image)
space image width=15, height=1 actual image (no explicit dimensions)
space image width=10, height=1 actual image (no explicit dimensions)
space image width=10, height=1 actual image (no explicit dimensions)
div end
These rows may or may not be generated via code and there are sometimes hrefs. I realize that I could perhaps use margins/padding on the image/or anchor element to create space. But this would require setting a class on each image. That does not seem like a good way to go about this. For a few reasons : the space would be inside the anchor tags, making it linkable. I would not be opposed to using divs and using specific classes on those. I have tried this however, and they do not seem to work as I would expect. They create line breaks, so now the images appear in a column, and they don't seem to take up any actual space anyway.
How about 2 divs, one for each row. Then set the margins on those.
<div class="row"> Your images or anchor tags</div>
<div class="row"> Your images or anchor tags</div>
Then
.row{
margin-top:10px;
}
or however much space you want between rows of images.
You may use divs for the images in order to position them on the screen better. Especially wanting to avoid adding a margin to an anchor tag.
div.img{
display:inline;
}
.firstcol{
margin-left:15px;
}
.col{
margin-left:10px;
}
and
<div class="img firstcol">The first image of teh row</div>
<div class="img col">The second image of teh row</div>
etc.
Using spacer images is rather clumsy and hardly ever needed. The simplest approach is probably to wrap all images inside a elements, using just <a><img ...></a> for those that aren’t meant to be links. Then you can set margin on the a element, without making the margin clickable.
You can also format the image gallery in rows of three images without making such division part of the HTML code. Example:
.gallery img { border: 0; margin-bottom: 20px; }
.gallery a:nth-child(3n+1) { margin-left: 15px; }
.gallery a:nth-child(3n+2) { margin-left: 10px; margin-right: 10px; }
.gallery a:nth-child(3n+3):after { content: "\A"; white-space: pre; }
This effectively makes the layout table-like, without hard-coding the division into columns in HTML. The last rule is a bit tricky (but valid) way of causing a line break after every 3rd element.
jsfiddle
P.S. This creates a 20px margin below the last row of images, too. If this is an issue, you can nullify it by setting .gallery { margin-bottom: -20px }.
This is what I have gotten to work :
.row {
margin-left:20px;
}
.space {
margin-left:12px;
display: inline;
}
.row-space {
margin-bottom:20px;
}
div class=row
a href=x img
div class=space /div
a href=x img
div class=space /div
/div
div class=row-space /div
I needed the display-inline to avoid a line break. I had read and have used float: left, in the past, but this has some other side effects which are not good for this purpose.
How can I make image caption width same as image? Now I have the following code:
<div class="image">
<img src="foo.jpg" alt="" />
<div>This is the caption.</div>
</div>
I've tried a lot of things (floating, absolute positioning etc), but if the caption is long, it always makes the div wide instead of going on many lines. The problem is that I don't know the width of image (or the length of caption). Is the only way to solve this use tables?
So the problem is that you don't know how wide the img will be, and the caption for the img may exceed the width of the img, in which case you want to restrict the width of the caption to the width of the img.
In my case, I applied display:table on the parent element, and applied display:table-caption and caption-side:bottom on the caption element like this:
<div class="image" style="display:table;">
<img src="foo.jpg" alt="" />
<div style="display:table-caption;caption-side:bottom;">This is the caption.</div>
</div>
You can apply display:table; and an arbitrary initial width, eg. width:7px; to the parent block like figure and everything will work as expected!
Here is a live demo:
http://jsfiddle.net/blaker/8snwd/
This solution's limitation is that IE 7 and earlier do not support display:table; and IE 8 requires your doctype to be !DOCTYPE.
Sources:
http://www.lifeathighroad.com/web-development/forcing-to-wraps-to-the-width-of-an-image-using-css-only/
W3Schools (can't post link due to stackoverflow's 2-link limit for people with less than 10 rep)
If the problem is the caption being too long, you can always use
div.image {
width: 200px; /* the width you want */
max-width: 200px; /* same as above */
}
div.image div {
width: 100%;
}
And the caption will stay static. Also, the tag name is img, not image.
Or, if you want to detect your image width, you can use jQuery:
$(document).ready(function() {
var imgWidth = $('.image img').width();
$('.image div').css({width: imgWidth});
});
That way, you're getting the image width, then you set the caption width to it.
The only way to do captioning properly is to enclose the image and caption in a table constructed from span elements with table, table-row and table-cell css attributes.
Any other method (including HTML5 figure tags) either gives width mismatches or causes unwanted line breaks.
If your method must work in a non-css3 browser, then a table is probably the best bet.
You could try to set the image div wrapper display:inline-block
http://jsfiddle.net/steweb/98Xvr/
If the caption is long, the only solution will be to set a fixed width, or set the .image div width by js. I'm trying to think about a pure css solution, but I think it's an hard challenge :)
The key is to treat the image as having a certain width some length. In the example below I checked and my image was 200px wide. And then treat the caption as an inline-block.
HTML:
<div style="width:200px;">
<img src="anImage.png" alt="Image description"/>
<div class="caption">This can be as long as you want.</div>
</div>
CSS:
.caption {
display: inline-block;
}
You can also replace the inline-block with text that is left justified, right, or stretched over the exact image width by replacing above css with one of the following:
.caption {
/* text-align: left; */
/* text-align: right; */
text-align: justify;
}