1

I have a form comprising a sequence of <label>, <input> pairs (one per line) as follows:

<ol style="list-style: none;">
  <li class="normal">
    <label>Channel Name</label>
    <input type="text">
  </li>
  <li class="reversed">
    <label>Subscribe to this channel</label>
    <input type="checkbox">
  </li>
</ol>

I'm looking for a pure-CSS way to modify the second line to display the <input> checkbox to the left of the <label> (i.e. exchange their order without modifying the HTML).

The following simple rule works perfectly in Firefox, Chrome, Safari, Opera, IE8+...

li.reversed input {
   float: left;
}

... but it looks awful on IE7: the <input> checkbox floats to the left (as required), but the <label> appears on the preceding line.

The simplest solution I can find that works on all browsers is to abandon float altogether and use absolute positioning, i.e.:

li.reversed {
   position: relative;
}
li.reversed label {
   position: absolute;
   left: 20px;
}

Can anyone suggest a better way? Many thanks...

mskfisher
  • 3,291
  • 4
  • 35
  • 48
Andrew MacLeod
  • 203
  • 1
  • 2
  • 10

2 Answers2

3

Use the following style sheet instead:

.reversed {
  unicode-bidi: embed;
  direction: rtl;
  text-align: left;
}
.reversed * {
  unicode-bidi: embed;
  direction: ltr;
}

This looks a bit contrived, but it turns the element to a directionality isolate where the direction is right to left but inside its sub-elements left to right. The net effect is just that the visual layout order of the sub-elements, the checkbox and the label, is reversed.

Here's a fiddle of the code to see it in action.

ScottS
  • 71,703
  • 13
  • 126
  • 146
Jukka K. Korpela
  • 195,524
  • 37
  • 270
  • 390
  • This works in IE7, IE8, IE9, Chrome 17, Firefox 10, Opera 11 and Safari 5 (on the Mac). For as long as I have to support IE7, I'm abandoning using `` altogether. Thanks, Jukka. – Andrew MacLeod Mar 21 '12 at 17:24
  • +1 for a very cool answer. Not at all contrived in my opinion. Creative uses of css to manipulate elements with as little code as possible is what I love, so thanks for educating me. By the way, do you know the purpose/necessity of the `unicode-bidi: embed` statement in this process? – ScottS Mar 23 '12 at 18:54
  • @ScottS, `unicode-bidi: embed` makes the element an “island” (isolate) in bidirectionality, i.e. the writing direction inside it is not affected by the environment, and vice versa. This simplifies things, because the bidirectional algorithm is fairly complex and might cause surprises. – Jukka K. Korpela Mar 23 '12 at 19:28
1

This worked of me (you would want to target IE7, and maybe tweak the numbers slightly).

li.reversed input {
   float: left;
   margin-top: -1.2em; 
}

li.reversed label {
    margin-left: 20px;
}
ScottS
  • 71,703
  • 13
  • 126
  • 146
  • Thanks Scott - the problem with this approach is that it has a knock-on effect on the next
  • item (not shown in the original abbreviated example). Ideally I want to avoid the CSS to descend into a series of IE7-specific "shims". Is there a more elegant, general rule?
  • – Andrew MacLeod Mar 19 '12 at 23:23
  • @AndrewMacLeod--I have not yet thought of another solution that worked. Personally, I'm surprised that your `float: left` worked on so many browsers, as it used to be a float occurring _after_ an element did not cause that preceding element to float next to it, only following elements (in other words, the IE7 behavior used to be standard). Browsers must have changed that without me realizing it. If I do think of something else, I'll edit and add it. – ScottS Mar 20 '12 at 00:01
  • given that `float`s appear to be inherently unportable between browsers, I am resorting to absolute positioning as a workaround (and have amended my original question accordingly). – Andrew MacLeod Mar 20 '12 at 00:34