0

I don't understand why these two examples behave differently. The objective of the HTML and CSS is simply to align the divs horisontally and let the last div (to the right) take up the remaining space (remaining width of container).

using specific id for right item:

<style type="text/css">
#left {
    float: left;
    padding: 0 1cm;
    background-color: #ff0000;
}
#right {
    width: 100%;
    background-color: #00FF00;
}
</style>
<div>
    <div id="left">item 1</div>
    <div id="left">item 2</div>
    <div id="right">last</div>
</div>  

using :last-child:

<style type="text/css">
#left {
    float: left;
    padding: 0 1cm;
    background-color: #ff0000;
}
#left:last-child {
    width: 100%;
    background-color: #00FF00;
}
</style>
<div>
    <div id="left">item 1</div>
    <div id="left">item 2</div>
    <div id="left">last</div>
</div>
pb2q
  • 58,613
  • 19
  • 146
  • 147

7 Answers7

3

You are using IDs incorrectly. An ID represents a unique element of a page. Try this:

HTML

<div class="list">
    <div>item 1</div>
    <div>item 2</div>
    <div>last</div>
</div> 

CSS

.list div {
    float: left;
    padding: 0 1cm;
    background-color: #ff0000;
}
.list div:last-child {
    width: 100%;
    background-color: #00FF00;
}

Edit

Your #right example displayed differently because it was not inheriting float: left;. If you want to mimic that functionality, add float: none; to the CSS like so:

.list div {
    float: left;
    padding: 0 1cm;
    background-color: #ff0000;
}
.list div:last-child {
    float: none;
    width: 100%;
    background-color: #00FF00;
}
rrowland
  • 2,734
  • 2
  • 17
  • 32
  • But his use of `id` wasn't the problem, the problem was the floating (which didn't happen when he used the `id` of `right`). – David Thomas Oct 10 '12 at 22:12
  • @DavidThomas: You're right; I updated my answer to address the float functionality. – rrowland Oct 10 '12 at 22:19
  • The last div now fills the remaining space ok, but it puzzles me that now this div doesn't inherit the padding set on .left. why is that the case? See details i my reply further down this thread. – user1736283 Oct 12 '12 at 12:48
  • Change padding to margin and you will see what is really happening. – rrowland Oct 12 '12 at 19:29
1

The difference between these two examples is pretty simple:

In the first example, the first two elements are floated left and the third is just placed in the normal document flow.

In the second example, the third element also matches the "#left" rule (the first one) in the stylesheet, which means it's also made to float to the left.

When the third element isn't floated, the first and second elements actually sit on top of the third. When all three are floated, they won't overlap, so the third is shunted down onto the second line.

I hope that makes sense!


Edit: As per David's comment (and others) it's worth noting that the use of multiple identical IDs is invalid. It "works" because browsers are very tolerant of mistakes, but can't be relied on and is in general a very bad idea.

If you replaced all instances of "id=" with "class=" in the HTML and "#"s with "."s in the CSS they'd be perfectly correct, but still behave in the same odd manner!

(And on a personal note - not complaining about someone's incorrect usage of HTML/CSS isn't the same as encouraging it :p)

tr00st
  • 331
  • 4
  • 15
  • 1
    Your explanation is right, but please: don't encourage/support the use of `id`s where a `class` is appropriate (and an `id` is entirely invalid). – David Thomas Oct 10 '12 at 22:09
0

I like :last-child too, but it isn't supported in browsers like IE7 and below (hope I've got the version right)

kalpaitch
  • 5,193
  • 10
  • 43
  • 67
0

HTML is invalid...

Try:

<style type="text/css">
#left1, left2 {
    float: left;
    padding: 0 1cm;
    background-color: #ff0000;
}
#right {
    width: 100%;
    background-color: #00FF00;
}
</style>
<div>
    <div id="left1">item 1</div>
    <div id="left2">item 2</div>
    <div id="right">last</div>
</div>  

Your ID's must all be different(unique). You cannot have more than one ID with the same name. With valid ID's it should behave the same as using :last-child. However, while :last-child is the modern way to code it, it is not supported in IE8 or below.

You could also use same classes instead of unique ID's.

<style type="text/css">
.left {
    float: left;
    padding: 0 1cm;
    background-color: #ff0000;
}
.right {
    width: 100%;
    background-color: #00FF00;
}
</style>
<div>
    <div class="left">item 1</div>
    <div class="left">item 2</div>
    <div class="right">last</div>
</div> 
Xarcell
  • 2,011
  • 6
  • 33
  • 65
0

The difference is because in the second example, the last child is floated left (because of the ruleset for #left), whereas in the first example, the last child has no id of left and so is not subject to the rule.

I've cleaned up your duplicate IDs to make a demo showing the effect you want here: http://jsbin.com/acomaw/1/edit

The CSS rulesets like k.left are effectively commented out; move the k prefix to the two other rulesets to see how they all have the same effect.

tuff
  • 4,895
  • 6
  • 26
  • 43
0

Ok so the answer has pretty much been stated with regards to what was causing the problem, however no one has provided the most succinct answer with regards to css. The following is the best, most concise and supported way to achieve what you want to do.

  1. You should never need to apply width:100% to a div unless you are overriding a previously set width, even in that case it would be best to use auto.
  2. You don't need to duplicate the "left" class each time (unless you are going to place other div markup within) - this cuts down on needless markup.. also as rrowland partially states, use a wrapping class - this gives you more flexibility in the future.
  3. If browser support is low for a feature that you can achieve in another more supported way - use the other way. last-child isn't fully supported yet, so just define a class to target your last item. for more information you could read Using the last-child selector

So the markup and css should be:

<style type="text/css">
  .cols div {
    float: left;
    padding: 0 1cm;
    background-color: #FF0000;
  }
  .cols .last {
    float: none;
    background-color: #00FF00;
  }
</style>
<div class="cols">
  <div>item 1</div>
  <div>item 2</div>
  <div class="last">last</div>
</div>

I realise they are subtle changes, but one of the major gripes I find with reading css is the overuse of needless declarations.

  • class="never ending list of classes ..."
  • float:left
  • position:relative

being the worst offenders.

Community
  • 1
  • 1
Pebbl
  • 34,937
  • 6
  • 62
  • 64
0

Thank you all for a lot of usefull answers!

I completely agree the comments regarding the misuse of id vs. class. This i due to my lack of experience with CSS, but also that the web is full of similar examples...

However, I still have an additional question:

With your corrections my example now reads something like this (disregarding the relevant comments regarding :last-child):

<style type="text/css"> 
.left {
    float: left;
    padding: 0 1cm;
    background-color: #ff0000;
}
.left:last-child {
    float: none;
    background-color: #00FF00;
}
</style>

<div>
    <div class="left">item 1</div>
    <div class="left">item 2</div>
    <div class="left">last</div>
</div>

The last div now fills the remaining space ok, but it puzzles me that now this div doesn't inherit the padding set on .left. why is that the case?