2

See the notes in the blue areas on the page below to see what I am trying to achieve.

http://www.a3financial.com/subtitleproblem.php

Here I have 2 p's which are subtitles, illustrated in blue, which I'm wanting to fluidly be as wide as possible within the fixed-width content area, while respecting any float:left image's padding/margin.

From what I understand this is the expected behavior when you don't set any width for the p and do have one set for the float:left.. but for some reason my subtitles' background are going behind the image and not respecting its' margins. Perhaps I'm wrong on my expectation. I know liquid widths with floats are difficult/impossible to achieve. Is there any way to do this?

For clarity, I want the page to look like this. I've added borders for additional clarity.

http://a3financial.com/images/clarity.png

To my knowledge, this is all that is being applied to the float:right:

#content .subtitle {
    padding-top: 2px;
    float: right;
    background-color: #8FD2E3;
    letter-spacing: -1px;
    font-family: Arial, Helvetica, sans-serif;
    font-size: 18px;
    color: #969696;
}

And here is the code for the float:left:

img.alignleftimg {
    float: left;
    width: 163px;
    /*margin-right: 30px;F*/
    padding-right: 30px;
}

HTML (apologies for long latin, text is needed to illustrate flow):

<p class="subtitle">Subtitle 1 - should be as wide as possible, respecting the image's padding/margin.</p>
<img src="images/homepage09.jpg" alt="" width="163" height="163" class="alignleftimg" />
<p>nunc nisl velit, fringilla ut ornare non, iaculis in ipsum. Vivamus volutpat quam et dui vestibulum ultricies. Fusce vitae sapien sed ipsum hendrerit dignissim. Lorem ipsum dolor at tellus. Etiam vitae ligula non ante iaculis. Curabitur elementum diam nec etiam lorem ipsum mauris dapibus arcu, sed bibendum libero elit et sem. Nunc at nunc tortor, ut aliquam augue. Etiam ut sem quis tellus iaculis convallis. Nulla viverra, metus eget accumsan. Maecenas pede nisl, elementum eu, ornare ac, malesuada at, erat. Proin gravida orci porttitor enim accumsan lacinia. Donec condimentum, urna non molestie semper, ligula enim ornare nibh, quis laoreet eros quam eget ante. Quisque erat. Vestibulum pellentesque, justo mollis pretium suscipit, justo nulla blandit libero, in blandit augue justo quis nisl. Fusce mattis viverra elit. Fusce quis tortor. Aliquam libero. Vivamus nisl nibh, iaculis vitae, viverra sit amet, ullamcorper vitae, turpis. Aliquam erat volutpat. Vestibulum dui sem, pulvinar sed, imperdiet nec, iaculis nec, leo.Pellentesque tristique ante ut risus. Quisque dictum. Integer nisl risus, sagittis convallis, rutrum id, elementum congue, nibh. Suspendisse dictum porta lectus. Donec placerat odio vel elit. </p>
<p class="subtitle">Subtitle 2 - should also be as wide as possible, pushing text out of the way in this case, to fill 100% of body width.</p>
<p>Aliquam libero. Vivamus nisl nibh, iaculis vitae, viverra sit amet, ullamcorper vitae, turpis. Aliquam erat volutpat. Vestibulum dui sem, pulvinar sed, imperdiet nec, iaculis nec, leo. Fusce odio. Etiam arcu dui, faucibus eget, placerat vel, sodales eget, orci. Donec ornare neque ac sem. Mauris aliquet.</p>

edit: starting to think i'm using the wrong element for this.. perhaps an h2 would function as i'm intending.. continuing to research.

edit 2: it doesn't appear h2 has any discernible difference from using p.

edit 3: added an image to clarify what i'm after.

final edit: Found what I was looking for and answered the question myself! Adding overflow:auto; to the subtitle class made its' background respect the float's margin and padding! See the accepted answer. Cleaned up the question for those searching in the future, as initially I didn't understand how to use floats correctly. Here's a link to the final product:

http://www.a3financial.com/subtitletest.php

mskfisher
  • 3,291
  • 4
  • 35
  • 48
Drew Alden
  • 108
  • 7
  • Wouldn't the .subtitle need to be floated 'left' rather than right? That way any float above the .subtitle would be pushed left – Marc Costello Feb 02 '12 at 12:09
  • 1
    And if you want the text to look like the element is floated from the right.. just text-align:right on the .subtitle – Marc Costello Feb 02 '12 at 12:11
  • @MarcCostello: No, all that does is pushes it to the left or right. It does respect the other float:left when this is done, but the div is still not extended to fill the page width as I'm describing. – Drew Alden Feb 02 '12 at 12:22
  • I've updated the OP to illustrate why I'm even floating in the first place. – Drew Alden Feb 02 '12 at 12:25

3 Answers3

3

OK, a couple of things first:

float applies to how a block elment is rendered with respect to the text of the main document. Float is not intended to be a way to control the size or positions of the actual elements themselves.

The best way to see this is an example:

<div id="A" style="float:right;background-color:#0f0;height:20px;">
    my title
</div>
<div id="B" style="background-color:#00f;height:35px;">
     my impressive language skills
</div>

Then this means that div A will float left of the content(text) in the document's main flow (div B is in the main flow). This does not affect the physical size of either div A or div B. You will see that in this example, div B is 100% wide (the backgrounds mark the container's actual size). Div's default behavior is to take up 100% of the available width of its container.

Div A is only as big as it needs to display it's content, so it may seem that its behavior is differnet. This is not really the case though. Because div A floats, it is rendered in its own virtual container outside of the main document. The fake container is set to be the minimum size possible, which is basically 0% wide. So, like any 0% continer, it stretches as much as necessary to accomidate the contents within). In effect, div A is 100% wide in a container that is 0% wide (by default).

You should also note that in this example, div A is not just floating to the right of the content within div B, but it is floating right in regards to ALL content in the main document flow. This is where a div with the "clear:both;" css attribute comes in handy, as this ensures that things that are floating stop floating at a specific point in the document (content that would have floated is pushed down).

Now, when we look at your document in particualr, what your were effectivly trying to do was stack 3 floats with each other... A floating right of B, and B floating left of C. But the containers themselves will just be however big they need to be. This gets very hard to manage, and can be unpredictable on different browsers... and you end up trying to manage everyting's width, height, padding, and margin plus doing all kinds of other still just to keep the containers from overlapping and piling up on top of each other.

The best bet when using floats for positioning, is to ensure that within any one container, you have no more than one thing floating. So in your document's case, something like this:

.subtitle {
    padding-top: 2px;
    background-color: #8FD2E3;
    letter-spacing: -1px;
    font-family: Arial, Helvetica, sans-serif;
    font-size: 18px;
    color: #969696;
}
img.alignleftimg {
    float: left;
    width: 163px;
    /*margin-right: 30px;F*/
    padding-right: 30px;
}

Note that in this CSS, only the image is setup to float. The subtitle doesn't need to float because you always want it 100% wide relative to whatever container contains it.

Then for HTML:

<img src="images/homepage09.jpg" alt="" width="163" height="163" class="alignleftimg" />
<div class="section">
<p class="subtitle">Subtitle 1</p>
    <p>
        my impressive language skills 
        my impressive language skills 
        my impressive language skills 
        my impressive language skills
        my impressive language skills
        my impressive language skills 
        my impressive language skills 
        my impressive language skills 
        my impressive language skills 
        my impressive language skills 
        my impressive language skills 
        my impressive language skills 
        my impressive language skills
    </p>
</div>
<div style="clear:both;"></div>
<div class="section">
    <p class="subtitle">Subtitle 2</p>
    <p>Aliquam libero. and some other stuff</p>
</div> 

Note here that we used a div to group the subtitles and the text to which that subtitle applies into one content container (section). The image is set to float left starting at the first section, so all the text will slide out of the way. We use a clear div to make sure that we stop floating at this point, then we start the container for the next subtitle and text.

As with anything in HTML, the less you specify the better off you are. Instead of managing sizes, floats, positions, and all that junk I recommend that you specify as little as is possible in CSS. It's a subtle art, but it pays off.

Now, in the example I give, the content area's container and the image actually overlap. So if you try background styles, or borders, etc. it can get ugly. So, this is when you might want to specify widths and margins to control the containers themselves; but this is easier is you are careful to keep floating down to just one element within any one container.

You could elminiate container overlap in the above by adding in this CSS (in addition to what was already there):

img.alignleftimg + div.section{
    margin-left: 170px;
}

This is an unusual css selector called the adjacent sibling selector... basically it says, "Applies to all div elements with a class-name of "section", that is also an immediate sibling to an img element with a class-name of "alignleftimg".... blah! Anyway, I just set the margin to a value a little bigger than the width of the image, and overlap is eliminated ONLY in the very specific case we want.

You might want to look at the HTML 5 section element; but I didn't use it here because it is a semantic element and so cross-browser support requires a bit more than just replacing the div tags with section tags.

Also, I want to point out that this entire discussion is the fault of the W3C. We needed real layout mechanisms that did the job of HTML layout tables way back in 1994... 18 years later, CSS grid is STILL not finalized and is probably another 10 years from being widly supported in shipping browsers.

Stephen M. Redd
  • 5,378
  • 1
  • 24
  • 32
  • An amazing answer which makes floats a lot clearer to me. Thanks Stephen! Unfortunately I'm still not achieving what I'm after, and even after that somewhat complex code, I'm still /basically/ manually adding a margin wherever this particular image width applies.. which could just as easily be done by creating a separate "short-subtitle" class. – Drew Alden Feb 03 '12 at 18:39
  • What I'm really after is a way to make the subtitles behave as if they were normal text.. word-wrapping around the left image, yet stretching to fill the line they're on. In the example below (utilizing your code), it fails because as you said its' parent container, section, is /really/ behind the image. http://www.a3financial.com/test.php – Drew Alden Feb 03 '12 at 18:40
  • Since Subtitle 2 isn't adjacent (in terms of code) to the image, the margin isn't even applied. the only way around this, as you described, would be to add a clear:both; which then affects vertical spacing in the text. if there were only one sentence, it would look like that paragraph were specifically tied to that image, when the image is just generic to the whole document. ..perhaps there really is no way to make an

    or
    behave in this manner?

    – Drew Alden Feb 03 '12 at 18:40
  • (sorry for multiple comments.. stupid StackOverflow limits it to 600 some characters? really?) – Drew Alden Feb 03 '12 at 18:42
  • In short, no, you can't do that with HTML/CSS. You can achieve the goal with the text by removing the CSS for the adjacent sibling and removing the clear div. Then all text will behave the way you want. But you would not be able to put borders or backgrounds on the subtitle and have it intelligently stretch right 100%. If you use an inline element, like span, then borders will not overlap the image, but you will still need javascript to set that right edge conditionally. – Stephen M. Redd Feb 04 '12 at 00:12
  • Well, that's new by me. That's an interesting result from the auto attribute. It appears to be behaving the same as overflow:hidden in this case, but the W3C never defined the behavior of auto (it is user agent defined). Fortunately, it seems the major browsers all agree on this behavior (at least when given this case). – Stephen M. Redd Feb 06 '12 at 03:50
2

Turns out this is possible!

By adding overflow: auto; to the subtitle class, it forces it to respect the image's margin and padding! Additionally, adding it to unordered lists has the added benefit of making sure the list stays in-line horizontally until it's complete before word-wrapping around the image.

See my final product here:

http://www.a3financial.com/subtitletest.php

Thanks to the following thread for pointing me in the right direction. I'd given up but happened to stumble upon it looking for a somewhat different issue:

Floated image to left of a ul is ignoring margin/padding

Community
  • 1
  • 1
Drew Alden
  • 108
  • 7
0

To make HTML elements fluid widely, You must set CSS width to:

width:**percent**%

While percent keyword is number between 0 and 100.

This is a calculation. Calculate the padding and margin to set the correct width percent. For example: Setting 3 fluid divs with no Padding or Margin:

<div class="first"></div>
<div class="second"></div>
<div class="third"></div>

CSS

.first, .second, .third{
    float:left;
    width:33%;
}

Hope this helps you.

Alaa Badran
  • 1,848
  • 15
  • 19
  • A simple percentage will not work here for the following reasons: (a) the div is next to a fixed-width image who's width can't be represented as a percentage (b) i want the float:right to fill 100% of the /available/ space.. and setting it to 100% simply makes it will 100% of the content area, pushing it below the float:left. alternatively if i don't float the float:right at all, it simply extends /behind/ the image. neither are what i'm after. – Drew Alden Feb 02 '12 at 13:38
  • In this case you need to use Javascript to set width by calculation – Alaa Badran Feb 02 '12 at 13:42
  • Not that I don't believe you, but that's quite a cop-out.. I find it hard to believe there isn't some CSS trickery to perform such a simple task. Worst case scenario I could create a separate class for a subtitle next to this image at a fixed width, but it'd be cleaner to find an auto-width solution. – Drew Alden Feb 02 '12 at 13:46