tags:

views:

105

answers:

6

I have fairly simple layout, like this:

<div class="card">
 <span class="attack">1</div>
 <span class="defence">2</div>
</div>

They're arranged on top of each other with simple display: block. What I want to achieve is when a card is in specific areas, "attack" shows on bottom and "defence" is on top. I know I can make it with jQuery, but can I achieve the same effect using pure CSS?

A: 

The first thought is to use absolute positioning within .card.

.card      { width:100px; height:50px; position:relative; }
  .attack  { width:100px; height:25px; position:absolute; top:25px; }
  .defense { width:100px; height:25px; position:absolute; top:0; }

In this example, .attack will be (visually) below .defense. But note, if you disable CSS, the true arrangement will be seen.

Jonathan Sampson
A: 

No, you can't. Even if you decided to try to "hack" it out in CSS, the resultant CSS would be huge, messy, and not easily maintained. The corresponding jQuery code would be very simple by comparison, easily understood, and easily maintained.

md5sum
What's the downvote for here?
md5sum
Because it's wrong. This is easily achievable with absolute/relative positioning in CSS.
Jonathan Sampson
It isn't wrong. Unless you add extra limitations (such as fixed height), then you can't simply swap them.
David Dorward
David, given the information in the OP, this *is* wrong. If "No, you can't" is valid because of potential future information, then this is a valid response to any question. It leads logically to absurdity when used arbitrarily.
Jonathan Sampson
There is no way to arbitrarily define "specific areas" as in the OP, in which cases the first `span` appears below the second `span`. There ARE ways to make the first `span` appear below the second `span`, but not for multiple predefined areas.
md5sum
Yes, height for all three elements is fixed. Width too.
Kuroki Kaze
@md5sum: "specific areas" is simple divs with some class set.
Kuroki Kaze
A: 

If you know the height of the element, you can use position: relative (with positive and negative values, respectively) or position: absolute. But this is all very hacky and comes with a lot of side-effects - I would do it in Javascript instead.

Pekka
A: 

You can do this by using (if you only want to do the swap in div.card):

.card .attack {
   position: relative;
   top: 1em;
}
.card .defence {
   position: relative;
   top: -1em;
}

But as others have mentioned this can have some unintended side-effects. E.g. the above sample will move swap position correctly only for 1 line blocks.

nichromium
+2  A: 

Technically, this is a business rules thing, which is not the domain of your cosmetic layer.

In an HTML document, the order of elements from first to last has semantic meaning - your case is not different, I suspect, in that you are trying to indicate some difference in importance from one element to the next (in the document, not just the visual representation) depending on the context.

So your approach should be JQuery, or some other method of changing the meaning of the relationship of these two elements in terms of their order in the document. CSS is intended to change only their cosmetic appearance.

With situations like this, it can be helpful to think, "what if someone could not see the elements, and had to rely on a screen reader to read them in the order they appear in the document? Would this information (not just the content of the two elements, but their relationship) still be correct and comprehensible?"

You may not intend for this to be accessible to the blind, but that's often a good sanity check for how to approach a problem like this.

Superstringcheese
The cards behave identically. This is case of changing presentation, noth the content.
Kuroki Kaze
I don't mean the content of the cards. There is information in the relationship of the cards in the document order. If there wasn't, you wouldn't care what order they appear in. The fact that you want the order of the cards - nevermind their contents - to change, indicates that it is indeed a document content issue, and not simply cosmetic.
Superstringcheese
Hmm, i suppose you have a point here.
Kuroki Kaze
+1  A: 

I'm pretty sure this will work:

.card {
    width: 100px;
    height: 150px;
    float: left;
}

.attack, .defence {
    width: 100px;
    height: 75px;
    clear: right;
}

/* Play with height and padding-top of .defence to
get the text to the very bottom */
.attack-top .card .attack {
    float: left;
}
.attack-top .card .defence {
    float: right;
    height: Wpx;
    padding-top: Xpx;
}


/* Play with height and padding-top of .attack to
get the text to the very bottom */
.defence-top .card .attack {
    float: right;
    height: Ypx;
    padding-top: Zpx;
}
.defence-top .card .defence {
    float: left;
}

There are a few details missing in your description, so I'll try to fill in my assumptions, and you can let me know if they're valid or not.

  • You said "when a card is in specific areas". I'll assume these areas can be represented by different containing classes (.attack-top and .defence-top, but rename as you see fit).
  • I'm assuming that a .card is 100px wide and 150px tall. If these width and height values are wrong, fill in the correct ones and make the appropriate recalculations. If .card doesn't have fixed width/height, it may still work, but I'm less confident, and you won't be able to get the bottom text to go to the very bottom of the card (just below the top text).
jboxer