I'm rewriting a webpage from HTML4 Transitional to HTML5 and I want it to look the same after the rewrite. However, I cannot make a div containing multiple lines of text to have the height of each line automatically adjusted to the largest font size of the text in that line.
To illustrate, same content with transitional (1) and modern strict (2) doctypes:
<iframe width="100" src='data:text/html,
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<style>
.box {
width: 20em;
border: 1px solid black;
margin: 5px;
}
.text-big {
font-size: 12px;
}
.text-small {
font-size: 9px;
}
</style>
</head>
<body>
<div id="div-1" class="box">
<span class="text-big">Aaaa</span>
<span class="text-small">Bbbb bbbbb bbbbbbbbbbb bbbbbbbbbbb bbbbbbbbbbb bbbbbbbbbbb bbbbbbbbbbbb bbbbbbbbbbb bbbbbbbbb bbbbbbbbbb bbbbbbbbbbb bbbbbbbb bbb</span>
</div>
<div id="div-2" class="box">
<span class="text-small">Bbbb bbbb bbb bbbb</span>
<span class="text-big">Aaaaaa aaaaaaaaa aaaaaa aaaaaa aaaaaaaaaa aaaaaaaaaa aaaaaaaa aaaaaaaaa aaaaaaaaaa aaaaaaaa aaaaaaaa aaaaaaa</span>
</div>
</body>
</html>
'></iframe>
<iframe width="100" src='data:text/html,
<!DOCTYPE HTML>
<html>
<head>
<style>
.box {
width: 20em;
border: 1px solid black;
margin: 5px;
}
.text-big {
font-size: 12px;
}
.text-small {
font-size: 9px;
}
</style>
</head>
<body>
<div id="div-1" class="box">
<span class="text-big">Aaaa</span>
<span class="text-small">Bbbb bbbbb bbbbbbbbbbb bbbbbbbbbbb bbbbbbbbbbb bbbbbbbbbbb bbbbbbbbbbbb bbbbbbbbbbb bbbbbbbbb bbbbbbbbbb bbbbbbbbbbb bbbbbbbb bbb</span>
</div>
<div id="div-2" class="box">
<span class="text-small">Bbbb bbbb bbb bbbb</span>
<span class="text-big">Aaaaaa aaaaaaaaa aaaaaa aaaaaa aaaaaaaaaa aaaaaaaaaa aaaaaaaa aaaaaaaaa aaaaaaaaaa aaaaaaaa aaaaaaaa aaaaaaa</span>
</div>
</body>
</html>
'></iframe>
When the above website had the HTML4 DOCTYPE, it was displayed by a web browser (Firefox) in a limited-quirks mode and, as a result, the height of each line of the text was adjusted to the largest font size of the text in that line:
.
However, when the website has the HTML5 DOCTYPE (so it is displayed in the no-quirks mode) in each <div>
all lines of the text have the same height regardless of the font size of the text they contain:
.
I tried various CSS options (line-height:
, font-size:
, display:
, etc.) for <div>
and <span>
, as well as wrapping the text in additional <p>
, <div>
, etc., but in HTML5 all lines of the <div>
still have the same height. I want the website to look as it was in HTML4: a line containing only small text should have a small line height, and a line containing both small and big text, or only big text, should have a big line height.
The texts vary a lot. Sometimes there is a short big text and a long small text (as in the 1st <div>
of the example), sometimes there is a short small text and a long big text (as in the 2nd <div>
of the example), and so on, so I cannot manually divide the text into lines and set their line heights individually.
Fighting the Quirks mode may seem futile, and clearly if there is any other option we should stick to standards-compliant mode, but as everything, it should not be impossible to emulate main quirks in the standards mode. It will be potentially difficult and/or tedious.
Honestly I don't know all the peculiarities of the quirks mode, but it cannot be dark magic after all. Your problem reminded me of one dirty trick that was quite common in the distant past, that was used for eliminating unwanted spacings doing font-size: 0
on wrappers, what in effect reduced line and word spacing of line boxes inside, what was often desirable when doing "inline layout".
Since your sample (luckily) does not contain any text content directly inside the .box
wrapper, and all text content is in span
s, it might work -- at least it seems so from where I am standing. After some fiddling, it seems that adding
.box {
width: 20rem; /* or calc() with former inherited font-size */
font-size: 0; /* nuke whitespace */
word-spacing: 4px; /* remedy spacing between spans with extra spacing */
}
.box * {
word-spacing: 0; /* no extra spacing here */
line-height: 1.18; /* "works on my machine" */
}
to the "HTML5 variant" does the trick, somewhat. Used this exploratory test-bead with a reduced test-case:
function setContent(str) {
for( const f of document.querySelectorAll('[data-prefix]') ) {
f.src = f.getAttribute('data-prefix') + str +
document.getElementById('x0').value +
document.getElementById(f.getAttribute('data-extra')).value
}
}
t.oninput()
iframe,
textarea {
width: 300px;
height: 165px;
border: none;
}
<!doctype html>
<table border>
<tr>
<th>Shared code
<th>Quirk
<th>HTML5
<tr>
<td>
<textarea id="t" oninput="setContent(value)">
<body>
<div>
<span>aaaa aaaa aaaa aaaa</span>
<b>ha!</b>
<span>aaaa aaaa aaaa aaaa</span>
</div>
</textarea>
<td>
<iframe data-extra="x1"
data-prefix='data:text/html,<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">'
></iframe>
<td>
<iframe data-extra="x2"
data-prefix='data:text/html,<!DOCTYPE HTML>'
></iframe>
<tr>
<td>
<textarea id="x0" oninput="t.oninput()">
<!-- For both -->
<style>
div { border: solid; width: 60px; }
div span { font-size: 10px; }
div b {font-size: 20px; }
</style>
<style>
</style>
</textarea>
<td>
<textarea id="x1" oninput="t.oninput()">
<!-- For Quirk -->
<style>
</style>
</textarea>
<td>
<textarea id="x2" oninput="t.oninput()">
<!-- For HTML5 -->
<style>
div {
font-size: 0;
word-spacing: 4px;
}
div * {
word-spacing: 0;
line-height: 1.18;
}
</style>
</textarea>
</table>