The `hanging-punctuation property` in CSS
chriscoyier.net
chriscoyier.net
⸻
1. I did it in TeX. I had to make modified versions of the fonts that had a separate hyphen character which went past the margin and insert manual \penalty0 points after en- and em-dashes since they no longer automatically were breakpoints since the hyphen was not the hyphenchar.
2. Despite my typographic background, I generally try to avoid spending time on manuscript formatting beyond the absolute basics.
3. Still not exactly half-hung punctuation with this trick. The exact hung fraction is left as an exercise to the reader.
You never want it to stand out, you just want everything to look balanced.
A slight amount of hanging looks like it's not hanging at all -- it just looks right. The same way the top and bottom of an 'O' are higher/lower than the top and bottom of an 'X', even though it doesn't look like it.
It's all about visual weight -- how the eye perceives it.
Fully hanging punctuation is just way overdoing it.
https://typography.guru/uploads/monthly_2020_01/overshoot.th...
Or this:
https://ilovetypography.com/img/2015/03/Caslon-overshoot-500...
Or this:
https://ktla.com/wp-content/uploads/sites/4/2020/06/GettyIma...
Or this:
https://live.staticflickr.com/5300/5482446696_1fa1ff2b45_b.j...
Hideous.
Try to follow that baseline with your eye. It's a roller coaster of chaos.
Type designers like to add overshoots merely out of habit, not aesthetics. They might have made sense in the lead type era, but simply look like mistakes today.
Please show me an example of type that looks more _uniformly sized_ with overshoots than without, and I'll agree with you.
https://en.wikipedia.org/wiki/Kabel_(typeface)#/media/File:K... https://www.freefonts.io/kabel-font-free/
Are you thinking of a different typeface?
Sorry for the late response. I didn't see your reply.
I've definitely gone through similar machinations to achieve something less extreme than full "Roman Hanging Punctuation". If you ever need to do this again, Adobe's "Optical Margin Alignment" and Affinity's "Optical alignment"¹ are worth checking out.
¹ https://affinity.help/publisher/en-US.lproj/index.html?page=...
Even if you think it looks stylish, it nonetheless creates a semantic distraction: it makes paragraphs that start with quotation marks look different from paragraphs that don't, when there is no intended difference in meaning. It costs the reader effort to remember that things that look different are actually supposed to be the same, and reduces your dynamic range for visually conveying meaningful differences.
If you want to stylize a quotation mark or draw attention to it, make it a special graphic element, clearly outside the container. Be deliberate. But don't violate the container boundary by misaligning a quotation mark that's part of the text flow; that just looks like an error.
Quite the opposite. When you look at most fonts in detail, the topmost parts of e.g. AEO will differ slightly; this is because visually, the pointed top of the A has much less 'mass' than the flat bar that is the top of E; the O will be higher than the top of the E bar as well. The same applies to the left and right edges; it's not a matter of taste, it's physiological. In so far a truly 'optical margin' or whatever Adobe chose to call it would have to take into account the shape of each singly glyph, not only punctuation. Quotes are only always mentioned because they're the most obvious application; full stops, commas, hyphens—all of these dittels have a minimum of 'flesh' and should therefore be pushed further than, say, an X or an M.
But I agree that putting a double quote 100% outside the left margin is a bit too much of a good thing; my guess is that it should be more like 50% or somesuch to avoid the "bumpy and messy"ness that you rightly dislike.
See the examples in my other comment: https://news.ycombinator.com/item?id=38449636
The idea that overshoots are necessary to create the appearance of equal height is a myth; you can see for yourself that they are clearly visible as irregularities when you run your eye along the baseline, mean line, or cap line.
It's not like typographers can't see that these orderly lines that you crave are 'overshot' by the glyphs, they sure do! And it's not necessarily an effect that works at constant ratio for every magnification either; the overshoot in a font intended for footnotes is probably different from the overshoot in a font designed to be displayed a meter high on the sides of a van.
In your other comment you say it's a 'holdover' from metal type. "Holdover" is such a dog whistle word you know, it always comes from people who want to do away with accumulated wisdom, who claim that "we can do this better now" (i.e. now that we have digitized every aspect of life); they more often than not are not willing and not prepared to recognize Chesterton's fence, they just want to rid the world of any kind of perceived messiness. All lines must be straight.
Other than that, there certainly are details in type design that are there solely to accommodate for hot metal typesetting, but overshoot as such is not. And your super-macro-closeups aren't proof of anything, they just demonstrate that overshoots are big enough to be clearly seen when enlarged. Type designers have been aware of this fact for centuries. Also, as for the https://live.staticflickr.com/5300/5482446696_1fa1ff2b45_b.j... one, where you write "Hideous. Try to follow that baseline with your eye. It's a roller coaster of chaos." that's just you disliking a type design that is somewhat playful.
You prolly dislike cursive handwriting for all the same reasons. You do you, but BRRRR.
You say it's wrong to judge overshoots by these examples because the text is too large. Okay. Show me an example of appropriately sized type that looks more _uniformly sized_ with overshoots than without, and I'll agree with you. (Remember, the justification for overshoots is uniform optical size, not playfulness!)
The first emphasizes that overshoot is just one of many aspects of typography that require the designer to tweak forms; the platonic, geometric ideal has to be adapted to the realities of human perception:
Typefaces are born from the struggle between rules and results. Squeezing a square about 1% helps it look more like a square; to appear the same height as a square, a circle must be measurably taller. The two strokes in an X aren't the same thickness, nor are their parallel edges actually parallel; the vertical stems of a lowercase alphabet are thinner than those of its capitals; the ascender on a d isn't the same length as the descender on a p, and so on. For the rational mind, type design can be a maddening game of drawing things differently in order to make them appear the same.—Jonathan Hoefler & Tobias Frere-Jones [1]
This fact has been well known the world over and throughout the ages; for example, in the game of go, the stones, which are black and white, are of slightly different sizes (black slightly larger), to give the appearance of being the same size [1]
Likewise the Parthenon in Athens: "[The Greeks] achieved global perfection through deliberate departure from local precision. Minor geometric irregularities were incorporated by the architects to enhance the beauty of the building. It is paradoxical that these modifications create the impression of great geometric perfection, even though they involve deliberate departures from strict regularity." [2]
As for type design, the maybe most geometric-in-appearance modern typeface in wide use, Futura by Paul Renner (1927) is not perfectly geometric: The design of Futura [...] makes subtle departures from pure geometric designs that allow the letterforms to seem balanced. This is visible in the apparently almost perfectly round stroke of the o, which is nonetheless slightly ovoid, and in how the circular strokes of letters like b gently thin as they merge with the verticals. Renner's biographer Christopher Burke has noted the important role of the Bauer Foundry's manufacturing team in adapting the design for different sizes of text, a feature not seen in digital releases.
As becomes evident from the last sentence and as is widely known by graphic designers, many / most digital typefaces forego adaptation to different perceived sizes (I'd say that is one major culprit in what makes the FedEX logo so awkward: they just took a design that would have worked well for a magazine headline and blew it up to cover a room-sized area). In so far overshoots are not a holdover from metal type; rather, digital type through it's negligence of established designer sensibilities has produced awkward and ugly results that more traditional craftspeople would've been ashamed of (this BTW is quite parallel to the discussion around putting two spaces after the full stop).
I refuse to show you another image to which you will doubtlessly just reply "meh, overshoot bad". It's also a matter of taste.
* [1] https://en.wikipedia.org/wiki/Overshoot_(typography)
* [2] https://www.irishtimes.com/news/science/optical-refinements-...
Otherwise, why bother with design?
Both essentially involve solving problems.
If we consider art .. sculpture and painting do require planning, preparatory sketches or a maquette. Design thinking allows us to build and solve.
Reading EPUB 3 specs is almost comical when compared with the feature set of real world EPUB publications and reader software: CSS trickery (such as pointless SVG wrappers around raster images), yet not using floated elements even for the few cases where it's a good fit (initials, flowed images), using Unicode quotations and mdash/ndash, not using CSS paged media for pagination and line numbering, EPUB 3 reference examples crashing reader software, Amazon and Apple using proprietary EPUB extensions for these reasons anyway (and having good technical reason to) while not contributing to W3C, Inc's spec., ...
The last useful EPUB spec version appears to be 3.0. from 2014 before IDPF merged into W3C, Inc. Later versions reference the "HTML living standard" and CSS snapshots (with CSS-everything that no reader software is going to support, ever). To bring old reference examples into compliance with 3.3/epubcheck, the only thing the WG bothered to do was to put secondary headings into <p> elements where they used <h2> in <hgroup> to match the changed spec (removal of the so-called HTML outlining algorithm). Great so this makes the reference examples nominally conformant, but leaves the installed base of eBooks out there without backward compatibility (and e-readers are far from evergreen browsers). Not that it matters anyway: calibre's conversion manpage strongly recommends and defaults to EPUB 2 anyway, supporting EPUB 3 only since 2019. In a way, EPUB 3.3 with its generic forward compat reads like the last spec its authors intend to publish, before the major organizational and funding changes at W3C, Inc in 2023.
I'm seriously beginning to wonder if PDF is the better format for reading and archival after all as 7+ inch reading devices become the norm (or don't they?)
Actually, slap `hyphens: auto` onto the CSS (since its default value is `manual`), and whatever your ebook reader does for things like hyphenation and justification is almost certainly spec-compliant, because all of that stuff is explicitly UA-defined these days.
You might be surprised at how little of browsers’ existing functionality in these areas is actually defined, or in progressive cases how much is defined as being up to the browser.
When I mention things like Knuth-Plass: all current browsers use a greedy first-fit line-breaking algorithm, but IE actually had something better long ago in some situation (I forget), and until recently, the entire thing was simply undefined. Now, the default is declared to be UA-defined (text-wrap-style: auto) <https://www.w3.org/TR/css-text-4/#text-wrap-style> with the option to declare a preference for alternative modes like stable, balanced or pretty. Long before this, Firefox had a bug open about implementing Knuth-Plass or similar <https://bugzilla.mozilla.org/show_bug.cgi?id=630181>, and the only oppositions have been on technical implementation grounds, not that there’s anything wrong with the concept, which people generally agree is desirable.
As regards heuristics, you can define the heuristics to use completely, or you can leave it to browsers with some suggestions, or you can leave it to browsers. There’s plenty of precedent for all three of these.
Yeah, it can screw with layout. We recently removed it because it had seemed harmless to have it enabled so Safari users could enjoy it and other browsers would just ignore it, but then we discovered it was screwing up the layout on the main page's lists (https://gwern.net/index) and was not harmless after all. :(
See for example Paged.js [1], a way to use HTML and CSS to produce printed books, with complete control over the rendering and an attention to details almost of TeX level's. Using web technologies as source format tremendously facilitates the production of various electronic formats in addition to the printed/PDF version, such as ePub and well, web pages, which need free flow text that print-oriented format do not allow for obvious reasons.
All this to say, I agree with your feeling if we stick to web browsers, but CSS is so much more nowadays.
In other words: you’ve already lost!
Again, I'm not saying CSS is coherent nor that this is a good thing in the absolute sense, as I already said, I agree with your feeling, I'm just saying that I understand where the need of more precise control/tweaking over details that is sometime in the standard comes from.
(Can’t say I never have…)
It is a code mirror app that outputs md styled like dnd books. It’s very much a “round peg in square hole” project, using html/css to create print materials, but for many it is good enough. It is just html and css, and allows customization, and precise styling requires precise css properties.
As you noted, it does only work well in one browser, Chrome on desktop (even though I think all the devs use FF as their daily driver). But as another commenter noted, the answer is that you design on one machine and share via pdf.
In the spirit of "not a bug but a feature" I'd say they use is demonstrating the "full potential" of CSS...
Text layouts being undefined is the last great tragedy of HTML, and we should fix it.
I was once like you, thinking like "It's the web! I know this!" Turns out, no...actually you don't. I've been soaking in this for a couple weeks, trying to rid my life of the last few Word documents that I use frequently and haven't converted.
Writing HTML to mimic print layout is a bit creaky, but it's trivial compared to the kinds of shenanigans that EPUB often requires.
Despite what you might tell yourself, reader applications are not web browsers, and come with their own set of idiosyncrasies and corner cases, and will gladly barf all over your HTML or (worse) sit still and refuse to move no matter how much you cajole them.
https://getyarn.io/yarn-clip/34d4f471-2bf6-4e55-ba95-1419f20...
If web standards sometimes make you feel like ants trying to reach the top of a hill with bits of grain, EPUB might as well be rolling Sisyphus' boulder.
"It is not the web, it's the web as rendered by a schizophrenic, half crazed hamster in a wheel"
-John Siracusa
At the least, that requires specifying the language of the text, probably even subtle differences such as those between UK and US english (although those can probably be handled very conservatively most of the time, as long words are fairly rare in English, compared to, say, Dutch or German)
Input:
- URL1
- URL2
- https://longurl3
Output: - URL1
- URL2
-
https://longurl3He programmed his site builder to insert two elements at the site of the punctuation:
<dquo-open-push></dquo-open-push> <dquo-open-pull> “That’s</dquo-open-pull>
and styles them with this CSS: dquo-open-push { margin-right: 0.5em }
dquo-open-pull { margin-left: -0.5em }
E.g. the first elements pushes the following element further back, but the second element pulls itself back in that negative margin. The resulting effect is that in normal flow both the positive and negative margin of these cancel each other out, leading to quasi normal inline flow: text text text text PUSH↔PULL text text
But if there is a line break between the elements the the push element pushes invisible into the right margin and the pull element pulls itself in the left margin, leading to hanging punctuation: text text text text text text PUSH→
←PULL text text text text text text
So the trick with negative margin not only works at the beginning of block elements but inside the inline flow without leading to a negative experience - e.g. it also works with unpredictable line lengths.An example is on this page: https://practicaltypography.com/are-two-spaces-better-than-o...
I really like the going of the extra mile, although now with `hanging-punctuation` it is unnecessary.
Note: Butterick programmed his own site builder - Pollen - and designs his own fonts - that makes such customisability more achievable, I assume. Not the biggest fan of using custom elements instead of span but modern HTML and web components makes this syntax valid.
But, I don't think those `dquo-open-*` tags would get in the way at all.
It's definitely not a 'regular user' thing, but I'm fairly sure it's more common than things like 'r/unixporn', or theming Linux to look like Windows XP or macOS, that are themselves quite large niches.
(P.S. get off my lawn)
Large FE projects often have multiple developers, which come and go .. and have differing levels of ability.
Tailwind provides a framework that's easy to jump into, provides consistency and is widely known.
--
However, that doesn't mean I can't think this particular technique isn't a good idea.
If it's generated, does it matter?
dquo-pull::before { margin-right: -made-up-string-width(“); }
dquo-pull { margin-left: calc(-1 * -made-up-string-width(“)); }
She said: <dquo-pull>“That’s</dquo-pull>
(I think you can do something like that with container query units [1], but I haven't managed to do it just yet.)UPD: container query wouldn't work here because if you set `container-type: inline-size` on dquo-pull, it will get inline size set to zero, as if it had no content [2].
[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/length#cont...
[2]: https://drafts.csswg.org/css-contain-3/#containment-inline-s...
> although now with `hanging-punctuation` it is unnecessary
`hanging-punctuation` only works at the start of the block element though. Maybe that'll change in the future though!
<dquo-pull><::before></::before>... </dquo-pull>
In that case the ::before element doesn't linebreak independently from its "parent" element and so those two elements are always together, even at a break before the start of a new line. And then she said:
<char-hang><span>“</span></char-hang>Hello,
handsome! What a day, huh?
which will be rendered like this: "And then she said: "
<!-- push: -->
<char-hang::before />
<!-- pull: -->
<span>“</span>
"Hello, handsome! What a day, huh?"
Without adding another element, you can use a hack though: make the quote mark transparent and use text-shadow to “move” it back instead: https://jsfiddle.net/utjxnv1r/3/And if we allow JS, we can just create a custom element and avoid those hacks altogether (also you don't have to calculate / eyeball the offset you need anymore): https://jsfiddle.net/c72uLtma/
It's missing some tools you'd need for full printed & bound books but it can cover pretty much everything else. Learning curve is acceptable if you know css well and lisp somewhat. Might be a struggle if not but still more flexible for a beginner than luatex I think.
e. More to the specifics of its use in CSS, it looks like Safari doesn't support the attribute to aggressively follow that rule,[2] as in the bottom right example of the previously linked image.
[1] https://www.thetype.com/wp-content/uploads/2017/11/AI-hangin...
[2] https://developer.mozilla.org/en-US/docs/Web/CSS/hanging-pun...
For me it's a brainier. Neither is better or worse, it's just different. I prefer having hanging-punctuation off by default because the text fits into its container, but if I was making something fancy for some reason I might turn it on.
Awesome" CSS model on top of a regular (quite limiting) box model in action. Now if you want to have a specific padding, you have to calculate how much space that quote took and subtract it from it. CSS is full of bs like that. Feels like it was taken for its first principles. I don't get how people praise it. Maybe they don't work with it often and only build chains of paragraphs with bells and whistles, while frameworks do all the heavy lifting and conceal learning cliffs.
Before receving arguments on Complexity and Layouts and Variety, I'd like to test HN. Please solve this easy puzzle and explain why your solution is logical, intuitive or sane:
You encounter the following html+css code in a mudball of a frontend.
<div class="parent">
<div class="header">Dynamic-height header</div>
<div class="rest">...many divs...</div>
</div>
.parent { width: 20vw; height: 100vh; }
.header { }
.rest { }
Make .rest vertically (i.e. up and down) scrollable without the help of the internet and without checking your solution or comparing to others before posting. Just post what you think should work and (very optionally) your YOE in CSS/Web. Also feel free to ignore it. Upvoted solutions will receive score. Good luck!``` .parent {display: flex; flex-direction: column;} .rest {flex-grow: 1; overflow-y: auto;} ```
But after clicking around you realize that it does not anymore. Waaat? Maybe it's related to sidebar visibility changes? You open the inspector and see that .parent is {display:block}. Seems like some jQuery code assumed that display property is either `block` or `none`. Or something. Aaargh. The "sane" attribute of this solution was violated due to its non-locality to the `.rest`. Who could think that changing the display mode for the parent, which is indeed a private property of the parent, would lead to such an issue. You live and you learn css!
(Also, explanations for "intuitive" and/or "logical" are still missing.)
CSS is a bit of a mess the last few years, with so many caveats... Just look at why position sticky will sometimes not work: "If you are trying to use position: sticky and it is not working, it is because one of the elements wrapping it is using overflow with a value of hidden, auto or scroll."[1]
But it's weird, it should work, or at least this should be documented somewhere. Also why should overflow: hidden break the functionality... If you know all the caveats of css, then you can safely say "I know CSS".
[1] https://robertmarshall.dev/blog/solution-to-why-css-position...
If full justification is helpful in general is another question but it certainly is out of fashion now.
If full justification is possible at all with the currently used browser rendering pipelines is yet another interesting questions. Intuitively I would have assumed so, but I remember past discussions here on HN that convinced me that this is not easy at all.
EDIT: I liked the HN thread I was referring to below. I think good full justification needs Knuth-Plass but don't know enough to be sure.
From commit 3927bbe9a4:
“ This matches the behavior of COMMIT_EDITMSG, which stays around
in case of error.
Two spaces, one quote character, one space, then the quote on that
indentation. This might look a bit off with a proportional font.Linus Torvalds[1] uses a kind of hanging quote for his merged pull requests. But it looks a bit too subtle since the quotation character hugs the first character.
[1] https://github.com/torvalds/linux/commit/5b2b1173a93fa056b45...
On the second picture, with italic:
https://i0.wp.com/chriscoyier.net/wp-content/uploads/2023/11...
the left one, thank you.
https://developer.mozilla.org/en-US/docs/Web/CSS/hanging-pun...
Eh... no it's not?
This just distracts me and makes me forget what I was reading
Doing a google image search for "magazine blockquote" isn't giving me anything with hanging punctuation, just oversized decorative quote marks, mostly at opposite corners of the blockquote box, sometimes even just the opening one. Most of them are also in a different color than the text.
I have this reaction to a lot of established typographical rules actually. Digits with descenders to name just one ("font-variant-numeric: oldstyle-nums" in CSS): I think they're ugly and make reading numbers unnecessarily difficult.
https://www.artlebedev.com/mandership/120/
Not submitting this one since it is light on technical details.
Btw text-indent is not some crazy new css unused thing it's actually very old (like 20yo) essential type setting rule. It's from times where CSS was mostly occupied with text documents, floats and inline elements.
If you look at the recent CSS additions It's all stuff concerned with responsive layouts and effects - very little to do with typography. It makes sense since web became app platform more than document platform.
It could be a nice property; but it isn't ready for primetime yet.
O.45em vs other sizes probably depends a lot on font/rendering/minor details that the website may not be able to control.
Does not work in mobile Safari. It hides the quotation mark
Quote blocks are embedded, nested structure. Sure seems to me like a punctuation model and a layout model which can understand that, is net beneficial.
I always liked the french <<this is a quote>> model. Somehow it felt more like an embedded thing.
Double quotes have the additional burden MICROSOFT WORD I AM LOOKING AT YOU of the random interpolation of what the editor YES MICROSOFT WORD I MEAN YOU thinks it knows you meant to say. Additionally hijacking the text into badly encoded iso-latin1 or utf-8 mis-parsed, as a free gift.
if I mean to say:
“a quote” (left and right double quotation mark)
I will say it. When I say "a quote" (apostrophe, used twice)
please.. leave those quote-marks alone.(double-dash to em-dash.. same problem: free uplift to UTF you didn't ask for)
Those « » characters are called "guillemets" [0]. Fun fact, they're named after an early French typecutter, Guillaume Le Bé!
Guillemets require using space around them («wrong», « correct ») which makes typesetting so hard as you have to hunt for each guillemet that fell to the next line to manually fix it.
And even that's not possible on the web, so you have to get used to dangling punctuation.
Also not in Norwegian and probably others.
Did they though? When I read old books vs new books, I don't notice the difference at all. Especially with justification, spaces are already quite variable per line.
I don't think it aided reading at all. It was just a kind of random convention -- maybe somebody thought there was a logic to it -- that got dropped because it wasn't doing anything. One less rule to worry about.
The difference in reading speed only applies to people who are used to double-spaces, there is no difference in reading speed single-spaced vs. double-spaced for people who are conditioned to read single-spaced.
> Although the type of spacing following punctuation marks did not seem to have an effect on those individuals who type with one space after a period, those who type with two spaces after a period had greater reading speed when paragraphs were presented in the same way in which they type: with two spaces following periods and one space following commas.
I'd argue this data suggests the double-spaces are a waste of space that accomplishes nothing except slightly handicapping people who become accustomed to it and then read text without it.
Or maybe slightly boosting when reading double spaced? (I didn't read the article yet, my plane is just starting).
The habit was adopted for monospace typewriters precisely to try to match book typesetting.
Then the books dropped it, but it persisted in typing habits.
Then once Mac/Windows allowed anyone to use proportional fonts, we were taught to use a single space again.
If you're a designer looking to design to the point of using this styling, you're going to be adding the padding/margin to allow for that space. I would agree that having it set to off is a good default. I like when defaults are sane.