Typesetting I: Breaking paragraphs into lines
The process of arranging letters and words onto some medium.
Persian cuneiform and Malnazar illuminated manuscript
Jikji type and Gutenberg bible
Question. What goals might we have in typesetting?
[We are] primarily concerned with high-quality technical manuscripts. […] If you merely want to produce a passably good document—something acceptable and basically readable but not really beautiful—a simpler system will usually suffice. […T]he goal is to produce the finest quality; this requires more attention to detail, but you will not find it much harder to go the extra distance, and you’ll be able to take special pride in the finished product.
Breaking paragraphs into lines.
Input: A plain text paragraph.
Output: locations of line-breaks
Goals:
Placeholder text:
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua.
Felis pellentesque suspendisse tristique in pulvinar erat integer
pellentesque nunc viverra auctor semper. Tempus eros ullamcorper
mauris turpis lacinia dictumst consequat proin facilisis et
conubia curabitur quisque egestas nullam. Nibh erat sodales
maecenas quis pulvinar auctor imperdiet platea litora id leo. Per
fusce lectus ex cursus urna fusce scelerisque. Dolor tempus augue
sit orci elit porttitor ipsum platea erat.
Nonsense Latin, commonly used to demonstrate graphic design
Question. In order to accomplish our task what parameters should we take into account?
Question. Given those parameters, what procedure would you use to find line breaks?
Parameters:
TEXT
(string)document
element
TEXT_WIDTH
maximum width of textWORD_SEP
minimum space between wordsWhat more do we need?
Idea. Process TEXT
Questions.
How to break the string?
What type of element for each word?
<span>
array<span>
are (default) inline document divisions
function getSpanArray (text) {
const words = text.split(/\s+/);
const spans = [];
for (let word of words) {
let elt = document.createElement("span");
elt.innerText = word;
spans.push(elt);
}
return spans;
}
We have
<span>
array, spans
parent
element (say, <p>
or <div>
)How to place the <span>
s on the page?
for (let s of spans) {
parent.appendChild(s);
}
What do we need to fix and how?
We can get the dimensions of an HTML element with
let width = elt.getBoundingClientRect().width;
…but elt
must alread be placed on the document!
Question. How to do this before we’ve decided where to place elt
?
Create a hidden
element
<div id="hidden"></div>
CSS:
#hidden {
position: absolute;
visibility: hidden;
}
JavaScript:
const hidden = document.querySelector('#hidden');
for (let s of spans) {
hidden.appendChild(s);
}
Finally, we can get the width of each word (in pixels).
Question. Now What?
So Far. We’ve mostly measured lengths in pixels (px
)
Problem. Space between words (e.g.) should scale with the size of the font.
Built-in Solution. Distance unit em
Getting the width of an em
inside parent
in pixels:
const em = parseFloat(getComputedStyle(parent).fontSize);
lec17-breaking-lines.zip
greedyLines(spans, parent)
spans
an array of <span>
elements, one per wordparent
an element (<div>
) that will contain wordsTEXT_WIDTH
pixels wide0.5 em
spaceMore:
display
margin
justify-content
span {
margin: 0em 0em 0em 0.5em;
}
span:first-child {
margin: 0em;
}
.first-line > span:first-child {
margin: 0em 0em 0em 2em;
}
:root {
--light-blue: rgb(200,255,255);
--mild-yellow: rgb(255, 255, 200);
/* font-family: 'EB Garamond', serif; */
font-family: 'Libre Baskerville', serif;
font-size: 16px;
}
span {
margin: 0em 0em 0em 0.5em;
background-color: var(--mild-yellow);
}
Can we do a better job of breaking paragraphs into lines?