40

I'm writing a web service, and I want to return the data as XHTML. Because it's data, not markup, I want to keep it very clean - no extra <div>s or <span>s. However, as a convenience to developers, I'd also like to make the returned data reasonably readable in a browser. To do so, I'm thinking a good way to go about it would be to use CSS.

The thing I specifically want to do is to insert linebreaks at certain places. I'm aware of display: block, but it doesn't really work in the situation I'm trying to handle now - a form with <input> fields. Something like this:

<form>
  Thingy 1: <input class="a" type="text" name="one" />
  Thingy 2: <input class="a" type="text" name="two" />
  Thingy 3: <input class="b" type="checkbox" name="three" />
  Thingy 4: <input class="b" type="checkbox" name="four" />
</form>

I'd like it to render so that each label displays on the same line as the corresponding input field. I've tried this:

input.a:after { content: "\a" }

But that didn't seem to do anything.

Priyanga
  • 143
  • 1
  • 3
  • 16

12 Answers12

54

It'd be best to wrap all of your elements in label elements, then apply css to the labels. The :before and :after pseudo classes are not completely supported in a consistent way.

Label tags have a lot of advantages including increased accessibility (on multiple levels) and more.

<label>
    Thingy one: <input type="text" name="one">;
</label>

then use CSS on your label elements...

label {display:block;clear:both;}
thanksd
  • 54,176
  • 22
  • 157
  • 150
BrewinBombers
  • 1,482
  • 1
  • 12
  • 11
  • 1
    I had hoped to avoid the extra wrapping element, as the primary consumer of this page is software, not humans. But it looks like it's necessary. –  Sep 18 '08 at 11:43
  • 2
    All the better for software to have consistent start and stop indicators. – Kzqai Sep 29 '11 at 19:08
  • 3
    (You don't need the for="one" when you wrap the label around the input element.) – Jan Aagaard Dec 18 '12 at 08:14
  • Drop the `for="one"` and `id="one"`, it's totally unnecessary and gets in the way because it's already got a `name` defined. – rvighne Jan 22 '14 at 02:15
  • downvoted cause everyone is free to choose which solution they apply. sometimes another solution is not applicable or not accepted by the client or project manager for some reason. – eyurdakul Jan 30 '14 at 18:28
42

Form controls are treated specially by browsers, so a lot of things don't necessarily work as they should. One of these things is generated content - it doesn't work for form controls. Instead, wrap the labels in <label> and use label:before { content: '\a' ; white-space: pre; }. You can also do it by floating everything and adding clear: left to the <label> elements.

Jim
  • 72,985
  • 14
  • 101
  • 108
  • when having big words `white-space: pre-line` or no `white-space: pre-wrap` worked for me, not sure about cross-browsing experience tho :) – zanona Mar 11 '12 at 15:49
  • Why is \a a newline character (I see it works but cant find any docs about it.) – SamGoody Jun 27 '12 at 21:42
  • @SamGoody it is mentioned in this W3C document http://www.w3.org/wiki/CSS/Properties/white-space although they don't tell why they chose \A instead of \N or \R... – Alexis Wilke Nov 03 '12 at 23:56
  • 10
    A backslash followed by a hexadecimal number is interpreted as a character reference. `A` is the tenth character in Unicode, which is the line feed character. – Jim Feb 08 '13 at 22:39
  • 2
    @AlexisWilke To add to what Jim explained: A = 10 in hexadecimal (like 0xA) and char 10 of Unicode is the newline. They didn't choose explicitly choose `\a` over `\n`. – rvighne Jan 22 '14 at 02:26
  • The link that Alexis provided no longer works. Updated links: 1) https://www.w3.org/TR/1998/PR-CSS2-19980324/syndata.html#strings , 2) https://www.w3.org/TR/1998/PR-CSS2-19980324/generate.html#x16 – Arial May 16 '23 at 18:11
12

It looks like you've got a bunch of form items you'd like to show in a list, right? Hmm... if only those HTML spec guys had thought to include markup to handle a list of items...

I'd recommend you set it up like this:

<form>
  <ul>
    <li><label>Thingy 1:</label><input class="a" type="text" name="one" /></li>
    <li><label>Thingy 1:</label><input class="a" type="text" name="one" /></li>
 </ul>
</form>

Then the CSS gets a lot easier.

Jon Galloway
  • 52,327
  • 25
  • 125
  • 193
4

the following would give you the newlines. It would also put extra spaces out in front though... you'd have to mess up your source indentation by removing the tabbing.

form { white-space: pre }
thanksd
  • 54,176
  • 22
  • 157
  • 150
Jimmy
  • 89,068
  • 17
  • 119
  • 137
2

One option is to specify a XSLT template within your XML that (some) browsers will process allowing you to include presentation with mark-up, CSS, colors etc. that shouldn't affect consumers of the web service.

Once in XHTML you could simply add some padding around the elements with CSS, e.g.

form input.a { margin-bottom: 1em }

DamienG
  • 6,575
  • 27
  • 43
2
<form>
   <label>Thingy 1: <input class="a" type="text" name="one" /></label>
   <label>Thingy 2: <input class="a" type="text" name="two" /></label>
   <label>Thingy 3: <input class="b" type="checkbox" name="three" /></label>
   <label>Thingy 4: <input class="b" type="checkbox" name="four" /></label>
</form>

and the following css

form label { display: block; }
daniels
  • 18,416
  • 31
  • 103
  • 173
2
<style type="text/css">
label, input { float: left; }
label { clear:left; }
</style>

<form>
    <label>thing 1:</label><input />
    <label>thing 2:</label><input />
</form>
Galen
  • 29,976
  • 9
  • 71
  • 89
1

The secret is to surround your whole thingie, label and widget, in a span whose class does the block and clear:

CSS

<style type="text/css">
  .lb {
    display:block;
    clear:both;
  }
</style>

HTML

<form>
  <span class="lb">Thingy 1: <input class="a" type="text" name="one" /></span>
  <span class="lb">Thingy 2: <input class="a" type="text" name="two" /></span>
  <span class="lb">Thingy 3: <input class="b" type="checkbox" name="three" /></span>
  <span class="lb">Thingy 4: <input class="b" type="checkbox" name="four" /></span>
</form>
Webdeveloper_Jelle
  • 2,868
  • 4
  • 29
  • 55
0

I agree with John Millikin. You can add in <span> tags or something around each line with a CSS class defined, then make them display:block if necessary. The only other way I can think to do this is to make the <input> an inline-block and make them emit "very large" padding-right, which would make the inline content wrap down.

Even so, your best bet is to logically group the data up in <span> tags (or similar) to indicate that that data belongs together (and then let the CSS do the positioning).

Thunder3
  • 1,120
  • 1
  • 7
  • 10
0

The CSS clear element is probably what you are looking for the get linebreaks. Something along:

#login form input { clear: both; }

will make sure the no other floating elements are left to either side of you input fields.

Reference

0

The javascript options are all over complicating things. Do as Jon Galloway or daniels0xff suggested.

Doug Moore
  • 1,173
  • 9
  • 23
-1

Use javascript. If you're using the jQuery library, try something like this:

$("input.a").after("<br/>")

Or whatever you need.

Dergachev
  • 348
  • 3
  • 6
  • 2
    Never rely on javascript to do what html/css can easily do because there is no graceful degradation. – Loren Segal Sep 15 '08 at 19:53
  • Always have to rely on js, IF-AND-ONLY-IF your code is generated by some other framework or library. Otherwise we can put any html tags wherever we want :) – sura2k Jun 21 '13 at 17:51