Contents
Solution 1 - Using a -ve margin
Solution 2 - Block Span for Body (Float Only)
Preface
Solution 2 below is my preferred solution at the moment.
I was surprised to find that text-indent
was unreliable as a cross-browser method of achieving this.
My test page for all of the following solutions can be found here.
Introduction
I have recently been asked by a legal client to convert their terms and conditions from Microsoft Word into HTML, preserving as far as possible the look and feel of the terms and conditions, and keeping the resulting HTML / CSS as clean as possible.
Not really my job as a lawyer; but something which I could not resist as a programmer.
The quickest approach is to use the built-in Save As HTML features in Microsoft Word, which have improved a lot in Word's later incarnations. Indeed, there must presumably come a point when the export feature from Word will be flawless.
But the perfectionist in me still finds something to be desired. Perhaps it was not having control over the resulting HTML; perhaps it was excessive cruft. So, I started experimenting myself.
The particular effect I was interested in was re-creation of the hanging numbered paragraph.
Here is a screen shot from Word of a paragraph I wanted to reproduce. It is Times New Roman, 12pt, Indent 0.5 inches, Hanging 0.5 inches
.

There were a number of different solutions I came up with, which I thought I would share with you here.
There did not seem to be one golden solution, as each has its advantages and disadvantages.
All of the solutions here have been tested in Internet Explorer, Firefox and Opera. I have not yet got myself a copy of Webkit to test there.
Solution 1 - Using a -ve margin
This involves using a -ve margin margin on the paragraph number.
The are two versions, one using display: inline-block
and one using float: left
on the number.
INLINE-BLOCK
<p style="margin-left:1in; border:1px solid red;">
<span style="display:inline; display:-moz-inline-box; display:inline-block; margin-left:-0.5in; width: 0.5in; position:relative;">1.1</span>This Agreement shall be governed by English Law and the courts of England shall have exclusive jurisdiction in relation to this Agreement.
</p>
FLOAT
<p style="margin-left:1in; border:1px solid red; zoom:1;">
<span style="margin-left:-0.5in; width: 0.5in; float:left;">1.1</span>This Agreement shall be governed by English Law and the courts of England shall have exclusive jurisdiction in relation to this Agreement.
</p>
The resulting paragraph looks like this (with a red border for illustration):-
Inline-Block
1.1This Agreement shall be governed by English Law and the courts of England shall have exclusive jurisdiction in relation to this Agreement.
Float
1.1This Agreement shall be governed by English Law and the courts of England shall have exclusive jurisdiction in relation to this Agreement.
Internet Explorer requires position:relative;
otherwise the number disappears.
The other problem is that with Internet Explorer, the float:left
verson does give you the infamous 3 pixel text jog. By including zoom:1;
on the <p>
element you solve the 3 pixel jog problem for Internet Explorer, at least for the margin only solution.
You can play around with margin
and padding
combinations on the <p>
element if you want the paragraph box to be situated differently:-
Inline Block
Padding
1.1This Agreement shall be governed by English Law and the courts of England shall have exclusive jurisdiction in relation to this Agreement.
Padding/Margin
1.1This Agreement shall be governed by English Law and the courts of England shall have exclusive jurisdiction in relation to this Agreement.
Margin
1.1This Agreement shall be governed by English Law and the courts of England shall have exclusive jurisdiction in relation to this Agreement.
Float
Padding
1.1This Agreement shall be governed by English Law and the courts of England shall have exclusive jurisdiction in relation to this Agreement.
Padding/Margin
1.1This Agreement shall be governed by English Law and the courts of England shall have exclusive jurisdiction in relation to this Agreement.
Margin
1.1This Agreement shall be governed by English Law and the courts of England shall have exclusive jurisdiction in relation to this Agreement.
Solution 2 - Block Span for Body (Float Only)
In this solution, we use two spans, one for the number and one for the body text.
It relies on converting the span for the body text to a block, using display:block
and is only available for float:left
on the number.
This has some possible advantages:-
- It is a better solution for the 3 pixel text jog.
- You can control the body text a bit better.
- The float only version avoids negative margins and relative positioning.
However, following a bit of testing, the -ve margin seems the better solution.
In the float only version, display:block
on the span
is not consistent, cross-browser. display:inline-block
does not allow text-align:justify
in Opera. display:table-cell
seems the best compromise.
The code is this:-
FLOAT ONLY
<p style="margin-left:0.5in; border:1px solid red;">
<span style="width: 0.5in; float:left;">1.1</span>
<span style="display:table-cell; zoom:1; border:1px solid blue;">This Agreement shall be governed by English Law and the courts of England shall have exclusive jurisdiction in relation to this Agreement.</span>
</p>
FLOAT AND -VE MARGIN
<p style="margin-left:1in; border:1px solid red;">
<span style="margin-left:-0.5in; width: 0.5in; position:relative; float:left;">1.1</span>
<span style="display:block; zoom:1; border:1px solid blue;">This Agreement shall be governed by English Law and the courts of England shall have exclusive jurisdiction in relation to this Agreement.</span>
</p>
The resulting paragraph looks like this (with a red border for illustration):-
Float Only
1.1 This Agreement shall be governed by English Law and the courts of England shall have exclusive jurisdiction in relation to this Agreement.
Float and -ve margin
1.1 This Agreement shall be governed by English Law and the courts of England shall have exclusive jurisdiction in relation to this Agreement.
Complete examples are:-
Float Only
Margin-Left 0.5in
1.1 This Agreement shall be governed by English Law and the courts of England shall have exclusive jurisdiction in relation to this Agreement.
Padding-Left 0.5in
1.1 This Agreement shall be governed by English Law and the courts of England shall have exclusive jurisdiction in relation to this Agreement.
Float and -ve margin
Margin-Left 1in
1.1 This Agreement shall be governed by English Law and the courts of England shall have exclusive jurisdiction in relation to this Agreement.
Margin-Left 0.5in Padding-Left 0.5in
1.1 This Agreement shall be governed by English Law and the courts of England shall have exclusive jurisdiction in relation to this Agreement.
Padding-Left 1in
1.1 This Agreement shall be governed by English Law and the courts of England shall have exclusive jurisdiction in relation to this Agreement.
Solution 3 - Position Relative and Absolute
This last solution uses absolute and relative positioning.
The outer <p>
has position:relative;
which then enables you to give the <span>
for the number a position:absolute;
where the co-ordinates are by reference to the <p>
and not <body>
.
There may be problems with this method if you have padding etc.
The code looks like the following, with examples for margin, padding/margin, and padding.
Note the left
value for the span
is different each time, because the 0,0
origin is the corner of the red box.
<p>Margin</p>
<p style="border: 1px solid red; position:relative; zoom:1; margin-left:1in; line-height:15pt;">
<span style="position:absolute; left:-0.5in; width:0.5in; top:0px;">1.1</span>This Agreement shall be governed by English Law and the courts of England shall have exclusive jurisdiction in relation to this Agreement.
</p>
<p>Margin/Padding</p>
<p style="border: 1px solid red; position:relative; zoom:1; margin-left:0.5in; padding-left:0.5in; line-height:15pt;">
<span style="position:absolute; left:0in; width:0.5in; top:0px;">1.1</span>This Agreement shall be governed by English Law and the courts of England shall have exclusive jurisdiction in relation to this Agreement.
</p>
<p>Padding</p>
<p style="border: 1px solid red; position:relative; zoom:1; padding-left:1in; line-height:15pt;">
<span style="position:absolute; left:0.5in; width:0.5in; top:0px;">1.1</span>This Agreement shall be governed by English Law and the courts of England shall have exclusive jurisdiction in relation to this Agreement.
</p>
Which will look like:-
Margin
1.1This Agreement shall be governed by English Law and the courts of England shall have exclusive jurisdiction in relation to this Agreement.
Margin/Padding
1.1This Agreement shall be governed by English Law and the courts of England shall have exclusive jurisdiction in relation to this Agreement.
Padding
1.1This Agreement shall be governed by English Law and the courts of England shall have exclusive jurisdiction in relation to this Agreement.
Points Along the Way
text-indent
I genuinely thought that this may be a solution. It effectively indents the first line of text; so I figured, give it a -ve value along the lines of:-
<p style="margin-left:1in; border:1px solid red; text-indent:-0.5in;">
<span style="">1.1</span>This Agreement shall be governed by English Law and the courts of England shall have exclusive jurisdiction in relation to this Agreement.
</p>
But the problem is, how do I give the span a width, so that the 'This' starts in the right place. So far I cannot get it to work. Internet Explorer makes the span disappear when you give it a width, and Opera's calculations go wrong. I gave up.
tables
Tables were another solution I considered. I.e. a separate table for each paragraph, and empty cells for indent spacing.
I can hear you saying: "Sir, step away from the tables".
But, the fact is, they are possibly the most cross-browser solution.
They are not ideal as:-
- they involve an excessive amount of mark-up for the task involved;
- they probably do not work in text readers;
- semantically they are a nightmare: you are presenting a paragraph, not tabular information.
position:relative;
Internet Explorer seems to need position:relative;
to get the negative left margin to work.
zoom:1;
Internet Explorer seems to need zoom:1;
for the float:left;
solution, to avoid the 3 pixel text jog.
It also seems to need zoom:1;
in the relative / absolute
solution, as making a paragraph position:relative;
causes havoc with line-height
in Internet Explorer.
The issue is something to do with the special IE hasLayout
property.
An alternative solution is to reduce the number width by 3px.
display: -moz-inline-box;
display:inline-block;
is needed for some of the solutions above.
However, Firefox does not support inline-block
. Firefox does have -moz-inline-block
and -moz-inline-box
. The first makes inline element a block element, which is different to the required behavior of inline-block
, and the second makes an inline element a block element that behaves like inline, which is close enough.
When using this, you must include all of the following in this order:-
display: inline;
display: -moz-inline-box;
display: inline-block;
The requirement for inline
first is something to do with ealier versions of IE.
As Firefox does not support inline-block
, it will be ignored, so the previous -moz-inline-box
stands.
Any browser that supports inline-block
will then override the previous two.
Text Readers
I use span
elements to enable graceful degradation in text readers.
If you want to ensure that there is a space between the number and the text in text readers, then include something like this after the number:-
<span class="text-only"> </span>
You set display:none;
in the style sheet, which should be ignored in text readers.
E.g.
<p style="margin-left:0.5in; border:1px solid red;">
<span style="width: 0.5in; float:left;">1.1</span>
<span style="display:none;"> </span>
<span style="display:block; zoom:1; border:1px solid blue;">This Agreement shall be governed by English Law and the courts of England shall have exclusive jurisdiction in relation to this Agreement.</span>
</p>
A final example
Solution 2 gives you a float right possibility as as well, which enables you do do this as well (the "Top" link):-
<p style="padding-left:1in; font-weight:bold;">
<span style="margin-left:-0.5in; width: 0.5in; position:relative; float:left;">1.</span>
<span style="float:right"><a href="#">Top</a></span>
<span style="display:block; zoom:1;">GOVERNING LAW.</span>
</p>
<p style="padding-left:1in;">
<span style="margin-left:-0.5in; width: 0.5in; position:relative; float:left;">1.1</span>
<span style="display:block; zoom:1;">This Agreement shall be governed by English Law and the courts of England shall have exclusive jurisdiction in relation to this Agreement.</span>
</p>
which looks like:-
1. Top GOVERNING LAW.
1.1 This Agreement shall be governed by English Law and the courts of England shall have exclusive jurisdiction in relation to this Agreement.
Sorry, comments have been suspended. Too much offensive comment spam is causing the site to be blocked by firewalls (which ironically therefore defeats the point of posting spam in the first place!). I don't get that many comments anyway, so I am going to look at a better way of managing the comment spam before reinstating the comments.