How to structure an image to the left and just below text?

Im trying to structure a cellblock but having trouble, i’ve attached an image with what Im talking about.

My key question has to do with the text in blue relative to the image. Is there anyway to get an image to be float’d to the left of text but have it just below the first line of text (regardless of the length of the text)?

Thanks!

Hi,

It can’t really be done (yes it can see posts below) because the heading text can’t change its behaviour half way through the line. You’d have to split the heading into two lines and insert the float between them.

You could do it in reverse if the image was floated right because you could add a spacer at the end of the text and then drag the image up into the gap.

e.g.


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<style type="text/css">
.outer {
    width:350px;
    padding:10px;
    border-top:1px solid #ccc;
    border-bottom:1px solid #ccc;
    overflow:hidden;
    line-height:1.4em;
}
h2 {
    margin:0;
}
.img {
    width:100px;
    height:100px;
    background:red;
    float:right;
    margin:-1.2em 0 5px 5px;
    display:inline;
}
h2 b {
    display:inline-block;
    width:120px
}
</style>
</head>
<body>
<div class="outer">
    <h2>This is the header that may wrap to the next line <b></b></h2>
    <p class="img">Image</p>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis pellentesque mauris pellentesque justo congue in faucibus justo faucibus. Nunc odio sapien, vehicula eget interdum quis,</p>
</div>
<div class="outer">
    <h2>This is the header <b></b></h2>
    <p class="img">Image</p>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis pellentesque mauris pellentesque justo congue in faucibus justo faucibus. Nunc odio sapien, vehicula eget interdum quis,</p>
</div>
<div class="outer">
    <h2>This is the header that may wrap to the next line or maybe three lines<b></b></h2>
    <p class="img">Image</p>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis pellentesque mauris pellentesque justo congue in faucibus justo faucibus. Nunc odio sapien, vehicula eget interdum quis,</p>
</div>
<div class="outer">
    <h2>This is the header that may wrap <b></b></h2>
    <p class="img">Image</p>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis pellentesque mauris pellentesque justo congue in faucibus justo faucibus. Nunc odio sapien, vehicula eget interdum quis,</p>
</div>

</body>
</html>


That’s about as close as you can get I think :slight_smile:

I thought of the sandbag trick to push the image down one line-height:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Untitled</title>
<style type="text/css">
.content div{
	margin:10px auto;
	border:solid;
	width:60%;
	overflow:hidden;
}
.content h2{
	margin:5px;
	font-size:110%;
}
.content div .sandbag{
	float:left;
	width:1px;
	height:2em; /* cleared space above the floated image */
}
.content div img{
	clear:left;
	float:left;
	margin-right:5px;
	background:#fc0;
}
</style>
</head><body>

<div class="content">
	<div><span class="sandbag"></span><img src=" " alt="" width="240" height="160"><h2>Header Header Header Header Header Header Header </h2> Content Content Content Content Content Content Content Content Content </div>
	<div><span class="sandbag"></span><img src=" " alt="" width="240" height="160"><h2>Header Header Header Header </h2> Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content </div>
	<div><span class="sandbag"></span><img src=" " alt="" width="240" height="160"><h2>Header Header Header Header Header Header Header Header Header Header </h2> Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content </div>
</div>

</body></html>

Is the headline text static or dynamic? I.e is it coming from the database?

Edit: I was just playing a little bit with it and just drobt the image in the middle of the headline, like this:


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>

<style type="text/css">
body {
	margin-top: 50px;
}

#wrapper {
	width: 500px;
	float: left;
	position: relative;	
}

#wrapper .headiine{
	font-size: 160%;
	color: #0000FF;
	padding: 0;
	display: block;
}
.lefty {
	float: left;
	margin: 5px 10px 0 0;
}
</style>
</head>

<body>
<div id="wrapper">
<span class="headiine">Long title goes here! <img src="Chrysanthemum.jpg" alt="" class="lefty" />notice how the second line wraps arround the photo.
</span>
</div>
</body>
</html>

It looks good to me or is this absolutely not done?

Hey guys, thaks for the effort so far. Unfortunatly, I cant split the title (by placing an image between the words), the title in fact comes from my database (as part of wordpress).

I tried the “sandbag” trick posted up by Erik, but it doesnt seem to be working?

This is turning out to be alot harder then I thought :frowning:

That’s why my first question, but I thought I give it a try :slight_smile:

I take it back! With a few modifications to the pixel height it now works using Erics sandbag method! Thanks eric, much appreciated and thanks to everyone who chipped in with their efforts. I still dont understand this sandbag method, but I sure do love it, and going to start learning it now to understand what its doing

There is always alternative ways to solve a problem by CSS and this time I happen to pick one you liked. :slight_smile:

Usually Paul finds the best method on top of his mind. :slight_smile:

For more understanding how the text wraps floats, here are two old SitePoint threads about using the Sandbag technique: Same line-height may wrap differently crossbrowser and then also read at bottom [URL=“http://www.sitepoint.com/forums/showthread.php?t=624772”]why a self-cleared box can overflow the pushed down float.

Good thinking Erik. I should have thought of that as it was the reverse of what I was trying :slight_smile:

Looking at Erik’s test case I see that webkit (at least chrome/win) does not treat anonymous boxes as other browsers do. These show across the floats - interesting behavior…

I think there is a way to do it without the “shim” though. Via negative text-indent and margin.


<!DOCTYPE html>
<html lang="en">
<head>
<title>Float showing in between lines</title>
<style>
div {
	border:solid;
	margin:20px auto;
	width:50%;
	overflow:hidden;
	padding:20px;
}
h2{
	margin-top:-.6em;
	font-size:1.1em;
	text-indent:-130px;
	margin-left:130px;
	line-height:1.5;	
}
img{
	float:left;
	margin:1.2em 10px 0 0;
	background:teal;
	width:120px;
	height:120px;
}
</style>
</head>
<body>
	<div>
	<img alt="float">
	<h2>Header Header Header Header Header Header Header </h2> 
	<p>Content Content Content Content Content Content Content Content Content </p>
	</div>
	<div>
	<img alt="float">
	<h2>Header Header Header Header Header Header Header Header Header Header Header Header Header Header Header Header Header Header </h2>
	<p>Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content</p>
	</div>
</body>
</html>

This is a live example

Ha ha - Beautiful :slight_smile: Don’t you just love CSS.

Thanks! :slight_smile:

Don’t you just love CSS.

There is nothing like it when it comes to pleasure and pain :wink:

Hi thierry,

Nice solution :slight_smile:
I don’t think we can beat it for simplicity and cross browser rendering.

Yes I see what you are talking about with webkit, that is strange. Looks like some more buggy behavior.

Following your lead with the text-indent here is one that uses :first-letter. It works as I expected it too in FF,IE, and Opera but Webkit lets the inline boxes slide past the float’s top margin before anything begins.

Using display:table for test float containment so content does not get clipped in Webkit.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
 "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Testing with :first-letter</title>

<style type="text/css">
div {
    width:50%;
    margin:10px auto;
    display:table;
    border:2px solid #000;
}
div h2 {
    margin:-.075em 0 0;
    font:bold 1.25em/1.2 arial;
}
div h2:first-letter {
    margin-left:-150px;
}
div img {
    float:left;
    width:150px;
    height:150px;
    margin:1.5em 10px 0 0;
    background:#0f0;
}
</style>
</head>
<body>

<div>
    <img src="#" alt="Image">
    <h2>Header Header Header</h2>
    <p>Content Content Content Content Content Content Content Content Content</p>
</div>
<div>
    <img src="#" alt="Image">
    <h2>Header Header Header Header Header Header Header Header Header</h2>
    <p>Content Content Content Content Content Content Content Content Content</p>
</div>

</body>
</html>

Here is another one that uses a pseudo :before float instead of a span for the sandbag. As long as I set the font-sizes the same on the :before and h2 while using percentages webkit complies. I am using a “.” to generate the line height and hiding it with text-indent. Webkit seems to be okay with it now.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
 "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Testing with :before sandbag</title>

<style type="text/css">
div {
    width:50%;
    margin:10px auto;
    overflow:hidden;
    border:2px solid #000;
}
div h2 {
    margin:0;
    padding:0 10px 0 9px;
    font:bold 120%/1.2 arial;
}
div:before {
    float:left;
    width:1px;
    content:".";
    font:120%/1.2 arial;
    text-indent:-2em;
    background:red;
}
div img {
    float:left;
    clear:left;
    width:150px;
    height:150px;
    margin:0 10px 0 0;
    background:#0f0;
}
</style>
</head>
<body>

<div>
    <img src="#" alt="Image">
    <h2>Header Header Header</h2>
    <p>Content Content Content Content Content Content Content Content Content</p>
</div>
<div>
    <img src="#" alt="Image">
    <h2>Header Header Header Header Header Header Header Header Header</h2>
    <p>Content Content Content Content Content Content Content Content Content</p>
</div>

</body>
</html>

Hi Rayzur,

Nice solution :slight_smile:

Thanks!

I think if you give your H2 a left margin, your first solution would work in webkit as well (I’m not sure webkit is wrong on that one though).

I prefer the pseudo-element approach rather than the shim in the markup, but as we know IE 6 and 7 won’t play ball with that one :frowning:

I would think that webkit should honor that top margin on the floated image though.

I prefer the pseudo-element approach rather than the shim in the markup, but as we know IE 6 and 7 won’t play ball with that one :frowning:

Yes, for IE6/7 we would need another element such as the span Erik was using. I was just trying to get the line-heights correct without any actual content in the html.

It seems that Opera is having trouble with that one too for some reason. Not sure what that’s all about but I will look at it closer.

Like I had said, I think you have found the cleanest way to go. :wink:

Actually, there is a similar behavior between the two different methods (negative text-indent and pseudo element) and browsers.

It is the fact that the offset is not applied the same depending on the length of the text.

My guess is that this is due to the algorithm related to wrapping text around floats. If there is wrapping, the point of reference for the offset seems to be the right edge of the float. If there is no wrapping, it appears to be the left edge of the content box.

You’re right though. I’d expect the pseudo-element to come to the right edge of the float and then move to the left due to the negative margin (rather than left in relation to the content box).

As Paul has said in this thread, do we love CSS… :slight_smile:

As Paul has said in this thread, do we love CSS… :slight_smile:
Yes, WE DO! :slight_smile:

I just wanted to follow up on what I discovered about Opera and Webkit when using the sandbags. I do agree that thierry has found the best solution but I wanted to investigate what was discovered in this thread.

In Erik’s example he is using a defined height on the sandbag (2em). That is what Webkit was having trouble with by allowing the h2’s inline boxes to slide on top of the image. It left extra space below the h2’s line-height which is enough to allow another line of text to pass through. That was discussed in the threads that Erik linked to. Reading through that first thread again I see that it was mentioned that Opera needed +1px additional height on the sandbag for text to pass through.

That extra 1px gets Opera working but breaks Webkit, I see this as a flaw in Opera. There is no reason another line box with identical height should not be able to pass through.

Here are my adjustments to the code Erik was using, I’m even using pixel font sizes to steer off any rounding errors.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Untitled</title>
<style type="text/css">
.content div{
    margin:10px auto;
    border:solid;
    width:60%;
    overflow:hidden;
}
.content h2{
    [COLOR=Blue]margin:0;[/COLOR]
    [COLOR=Blue]font:25px/30px arial;[/COLOR]
}
.content div span{
    float:left;
    [COLOR=Red]/*width:1px;*/
    /*height:2em;*/[/COLOR]
    [COLOR=Blue]font:25px/30px arial;[/COLOR]
    [COLOR=DarkGreen]/*padding-top:1px; Gets Opera working but breaks Webkit*/[/COLOR]
    background:red;
}
.content div img{
    clear:left;
    float:left;
    margin-right:5px;
    background:#fc0;
}
</style>
</head><body>

<div class="content">
    <div>[COLOR=Blue]<span>H</span>[/COLOR]<img src="#" alt="" width="240" height="160"><h2>Header Header Header Header Header Header Header </h2> Content Content Content Content Content Content Content Content Content </div>
    <div>[COLOR=Blue]<span>H</span>[/COLOR]<img src="#" alt="" width="240" height="160"><h2>Header Header Header Header </h2> Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content </div>
    <div>[COLOR=Blue]<span>H</span>[/COLOR]<img src="#" alt="" width="240" height="160"><h2>Header Header Header Header Header Header Header Header Header Header </h2> Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content Content </div>
</div>

</body></html>

Hi Thierry, wonderfully simple!

Ray, maybe you could use an escaped hard space as content in your pseudo element version:


div:before {
    float:left;
    width:1px;
    content:"\\A0";
    font:120%/1.2 arial;
    background:red;
}

Ray, maybe you could use an escaped hard space as content in your pseudo element version:

Hi Erik, I never could get it to work in Opera due to that 1px glitch in the h2 line box.

The strange thing about is if you close your viewport enough to force the h2 to wrap down to the width of one word on the right of the image it finally pops the first line up beside the sandbag.

I did some searching for Opera line box bugs but never found anything that explained it, I tried everything I could think of but never found a solution.

Some interesting stuff there guys :slight_smile: Isn’t is strange that opera always seem to be the most awkward to fix in all these types of scenarios. Unlike IE which you can hack into submission you often just hit a brick wall with Opera. It’s a great browser but just a little buggy in places.