<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jacopo Lorenzetti</title>
    <description>The latest articles on DEV Community by Jacopo Lorenzetti (@jlorenzetti).</description>
    <link>https://dev.to/jlorenzetti</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F987734%2Fd676fb77-5937-47ce-b8b4-276b3ca3a130.jpeg</url>
      <title>DEV Community: Jacopo Lorenzetti</title>
      <link>https://dev.to/jlorenzetti</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jlorenzetti"/>
    <language>en</language>
    <item>
      <title>Beyond `text-wrap: pretty` — language-aware line breaks for minor words</title>
      <dc:creator>Jacopo Lorenzetti</dc:creator>
      <pubDate>Wed, 17 Sep 2025 14:35:00 +0000</pubDate>
      <link>https://dev.to/jlorenzetti/beyond-text-wrap-pretty-language-aware-line-breaks-for-minor-words-if6</link>
      <guid>https://dev.to/jlorenzetti/beyond-text-wrap-pretty-language-aware-line-breaks-for-minor-words-if6</guid>
      <description>&lt;p&gt;Ever noticed that tiny &lt;em&gt;“a”&lt;/em&gt; dangling at the end of a headline? 😱&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.chrome.com/blog/css-text-wrap-pretty" rel="noopener noreferrer"&gt;&lt;code&gt;text-wrap: pretty&lt;/code&gt;&lt;/a&gt; already makes paragraphs look smarter — but it isn’t &lt;strong&gt;language-aware&lt;/strong&gt;. In many editorial traditions, you don’t want to break after &lt;em&gt;minor words&lt;/em&gt; (articles, prepositions, conjunctions), or between an honorific and the following name, or between initials and a surname.&lt;/p&gt;

&lt;p&gt;This post proposes a small, language-aware upgrade to line breaking — and ships a tiny polyfill you can try in 30 seconds.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fumvcj8t1l5nqt67xxr90.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fumvcj8t1l5nqt67xxr90.gif" alt="With only text-wrap: pretty, the orphan is gone — but pairs like Fig./2 and J. K./Rowling can still split. The language-aware glue keeps those together while the paragraph stays nicely balanced."&gt;&lt;/a&gt;&lt;br&gt;&lt;small&gt;CodePen: &lt;a href="https://codepen.io/jlorenzetti/pen/zxvXewX" rel="noopener noreferrer"&gt;https://codepen.io/jlorenzetti/pen/zxvXewX&lt;/a&gt;&lt;/small&gt;
  &lt;/p&gt;




&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;text-wrap: pretty&lt;/code&gt; improves line breaks, but it’s &lt;strong&gt;not language-aware&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;This tiny polyfill adds a thin layer of editorial glue: keeps &lt;strong&gt;obvious pairs&lt;/strong&gt; together (e.g. &lt;em&gt;Mr. Smith&lt;/em&gt;, &lt;em&gt;Fig. 2&lt;/em&gt;, &lt;em&gt;20 °C&lt;/em&gt;, &lt;em&gt;1900–2000&lt;/em&gt;, &lt;em&gt;J. K. Rowling&lt;/em&gt;) and optionally keeps &lt;strong&gt;minor words&lt;/strong&gt; attached to the next word &lt;strong&gt;where that’s the editorial norm&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;Zero deps, one DOM pass, no layout measurements.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;center&gt;
&lt;a href="https://jlorenzetti.github.io/text-wrap-minor-words" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;Try the live demo&lt;/a&gt;
&lt;/center&gt;




&lt;h2&gt;
  
  
  What &lt;code&gt;pretty&lt;/code&gt; solves — and what it can’t
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;text-wrap: pretty&lt;/code&gt; focuses on &lt;strong&gt;avoiding short last lines&lt;/strong&gt; and can make smarter break choices near the end of a paragraph (details vary by engine).&lt;br&gt;
But it’s &lt;strong&gt;agnostic&lt;/strong&gt; about editorial semantics — it doesn’t know that &lt;em&gt;Fig.&lt;/em&gt; and &lt;em&gt;2&lt;/em&gt; belong together, or that many editorial traditions avoid breaking after short function words.&lt;/p&gt;

&lt;p&gt;This polyfill adds &lt;strong&gt;just enough semantics&lt;/strong&gt; on top of &lt;code&gt;pretty&lt;/code&gt;, without re-implementing layout. Think of it as &lt;em&gt;one layer of “do not break here”&lt;/em&gt; for well-established editorial conventions.&lt;/p&gt;




&lt;h2&gt;
  
  
  The upgrade in one minute
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scope:&lt;/strong&gt; only elements whose computed &lt;code&gt;text-wrap&lt;/code&gt; is &lt;code&gt;pretty&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scan:&lt;/strong&gt; a single pass over &lt;strong&gt;text nodes&lt;/strong&gt; (no layout reads, no reflows).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Decide:&lt;/strong&gt; match language-aware patterns:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Safe rules (always on):&lt;/strong&gt; honorifics + name, initials + surname, label + number, number + unit, § + number, numeric ranges (WORD JOINER around the dash).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Minor words (per locale):&lt;/strong&gt; attach short function words &lt;strong&gt;only&lt;/strong&gt; where this is a common editorial convention.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Glue:&lt;/strong&gt; replace a normal space with &lt;strong&gt;NBSP&lt;/strong&gt; (&lt;code&gt;U+00A0&lt;/code&gt;) or insert &lt;strong&gt;WORD JOINER&lt;/strong&gt; (&lt;code&gt;U+2060&lt;/code&gt;) where appropriate.&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Idempotent &amp;amp; safe:&lt;/strong&gt; skips URLs/emails, doesn’t cross inline elements by default, doesn’t touch &lt;code&gt;pre/code/...&lt;/code&gt;.&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  Quick start
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Plain HTML (no build)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;article&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"typo"&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;See Fig. 2 for details.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
  &lt;span class="nc"&gt;.typo&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;text-wrap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pretty&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;hyphens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c"&gt;/* Older UAs without `text-wrap: pretty`: opt-in to the glue layer */&lt;/span&gt;
  &lt;span class="k"&gt;@supports&lt;/span&gt; &lt;span class="n"&gt;not&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text-wrap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pretty&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;.typo&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;--text-wrap-preferences&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;minor-words&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"module"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;init&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;registerLanguage&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://cdn.jsdelivr.net/npm/text-wrap-minor-words@0.3.1/dist/lite.mjs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;en&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://cdn.jsdelivr.net/npm/text-wrap-minor-words@0.3.1/locales/en.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="nx"&gt;assert&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="nf"&gt;registerLanguage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;en&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ctrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;languages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nx"&gt;ctrl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Swap &lt;code&gt;en&lt;/code&gt; for another locale if needed. To support multiple locales, import/register more JSON files the same way.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  Node / bundler (ESM)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i text-wrap-minor-words
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;init&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;registerLanguage&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text-wrap-minor-words/lite&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;en&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text-wrap-minor-words/locales/en.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;registerLanguage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;en&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ctrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;languages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="na"&gt;observe&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;ctrl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
  &lt;span class="nc"&gt;.typo&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;text-wrap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pretty&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;hyphens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;@supports&lt;/span&gt; &lt;span class="n"&gt;not&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text-wrap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pretty&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;.typo&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;--text-wrap-preferences&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;minor-words&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;You can also load the non-lite global build:&lt;br&gt;
&lt;code&gt;&amp;lt;script src="https://cdn.jsdelivr.net/npm/text-wrap-minor-words@0.3.1/dist/index.global.js"&amp;gt;&amp;lt;/script&amp;gt;&lt;/code&gt; (includes built-in locale data for quick trials; prefer &lt;strong&gt;lite&lt;/strong&gt; in production).&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  English display opt-in (optional)
&lt;/h3&gt;

&lt;p&gt;By default, &lt;em&gt;minor words&lt;/em&gt; are &lt;strong&gt;off&lt;/strong&gt; for English body text. This snippet enables them &lt;strong&gt;only in display contexts&lt;/strong&gt; (headings).&lt;/p&gt;

&lt;h4&gt;
  
  
  Plain HTML (no build)
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;article&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"typo"&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;From a book to the browser: a practical guide to typography on the web&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
  &lt;span class="nc"&gt;.typo&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;text-wrap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pretty&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;hyphens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c"&gt;/* Enable the minor-words glue only for English headings (display) */&lt;/span&gt;
  &lt;span class="nc"&gt;.typo&lt;/span&gt; &lt;span class="nd"&gt;:is&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;h4&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;h5&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;h6&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nd"&gt;:lang&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;en&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="py"&gt;--text-wrap-preferences&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;minor-words&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* gate on */&lt;/span&gt;
    &lt;span class="py"&gt;--text-wrap-minor-threshold&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* glue after 1-char tokens */&lt;/span&gt;
    &lt;span class="py"&gt;--text-wrap-minor-stoplist&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;"of to in on at for by a I"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* adjust to your style guide */&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;@supports&lt;/span&gt; &lt;span class="n"&gt;not&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text-wrap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pretty&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;.typo&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;--text-wrap-preferences&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;minor-words&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"module"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;init&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;registerLanguage&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://cdn.jsdelivr.net/npm/text-wrap-minor-words@0.3.1/dist/lite.mjs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;en&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://cdn.jsdelivr.net/npm/text-wrap-minor-words@0.3.1/locales/en.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="nx"&gt;assert&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="nf"&gt;registerLanguage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;en&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ctrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;languages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;display&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt; &lt;span class="c1"&gt;// limit processing to display contexts&lt;/span&gt;
  &lt;span class="nx"&gt;ctrl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Bundler / ESM
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i text-wrap-minor-words
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;init&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;registerLanguage&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text-wrap-minor-words/lite&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;en&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text-wrap-minor-words/locales/en.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;registerLanguage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;en&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ctrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;languages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;display&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;ctrl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.typo&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;text-wrap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pretty&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;hyphens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.typo&lt;/span&gt; &lt;span class="nd"&gt;:is&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;h4&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;h5&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;h6&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nd"&gt;:lang&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;en&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--text-wrap-preferences&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;minor-words&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--text-wrap-minor-threshold&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--text-wrap-minor-stoplist&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;"of to in on at for by a I"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;@supports&lt;/span&gt; &lt;span class="n"&gt;not&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text-wrap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pretty&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nc"&gt;.typo&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;--text-wrap-preferences&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;minor-words&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Tip: prefer &lt;code&gt;:lang(en)&lt;/code&gt; over &lt;code&gt;[lang="en"]&lt;/code&gt; so headings match the language &lt;strong&gt;inherited&lt;/strong&gt; from the container.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Defaults &amp;amp; language notes (compact)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Safe rules&lt;/strong&gt; (on in every language): &lt;strong&gt;honorifics + name&lt;/strong&gt; (&lt;em&gt;Mr. Smith&lt;/em&gt;, &lt;em&gt;Dr. Müller&lt;/em&gt;), &lt;strong&gt;initials + surname&lt;/strong&gt; (&lt;em&gt;J. K. Rowling&lt;/em&gt;), &lt;strong&gt;label + number&lt;/strong&gt; (&lt;em&gt;Fig. 2&lt;/em&gt;, &lt;em&gt;S. 12&lt;/em&gt;), &lt;strong&gt;number + unit&lt;/strong&gt; (&lt;em&gt;20 °C&lt;/em&gt;, &lt;em&gt;10 km&lt;/em&gt;), &lt;strong&gt;§ + number&lt;/strong&gt;, &lt;strong&gt;numeric ranges&lt;/strong&gt; (&lt;em&gt;1900–2000&lt;/em&gt; with &lt;code&gt;U+2060&lt;/code&gt; around the dash).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Minor words&lt;/strong&gt;: &lt;strong&gt;on by default&lt;/strong&gt; in Romance/Slavic/Greek; &lt;strong&gt;off by default&lt;/strong&gt; in English/German/Dutch (you can opt-in for display).&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Locale&lt;/th&gt;
&lt;th&gt;1-letter glue&lt;/th&gt;
&lt;th&gt;Examples from the default stop-list*&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;fr&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;de, du, le, la, les, un, une…&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;it&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;di, da, in, su, con, per…&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;pl&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;w, z, do, na, po…&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ru&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;в, к, с, на, по…&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;el&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;σε, το, τη, οι…&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;en&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;&lt;em&gt;(safe rules by default; opt-in for display)&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;* Full lists and configuration in the &lt;a href="https://github.com/jlorenzetti/text-wrap-minor-words/tree/main/src/data/languages" rel="noopener noreferrer"&gt;language dataset&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Performance &amp;amp; accessibility
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;O(n)&lt;/strong&gt; over text nodes. Regex pre-compiled per locale. No layout measurements.&lt;/li&gt;
&lt;li&gt;Early exit for &lt;strong&gt;neutral locales&lt;/strong&gt; (e.g. en/de/nl when minor words are off).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Screen readers:&lt;/strong&gt; NBSP/WORD JOINER are invisible to AT; URL/email detection prevents accidental glue.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Caveats
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Inline crossing:&lt;/strong&gt; currently we don’t cross inline elements (e.g. &lt;code&gt;a &amp;lt;em&amp;gt;word&amp;lt;/em&amp;gt;&lt;/code&gt;). We may evaluate a future opt-in.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CJK/RTL:&lt;/strong&gt; not targeted for now (different line-breaking traditions).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Not a grammar rule:&lt;/strong&gt; this encodes &lt;strong&gt;editorial conventions&lt;/strong&gt;, not linguistic rules. Defaults are conservative; override when your style guide differs.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Spec angle (why this might belong in CSS)
&lt;/h2&gt;

&lt;p&gt;This polyfill explores a small, &lt;strong&gt;language-aware extension&lt;/strong&gt; to &lt;code&gt;text-wrap&lt;/code&gt;. If real-world use proves it broadly useful and low-risk, one possible shape could be a dedicated option (e.g. a &lt;em&gt;“minor-words”&lt;/em&gt; sub-mode) that lets UAs apply these &lt;strong&gt;low-controversy “do not break here” hints&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The repo includes an &lt;a href="https://github.com/jlorenzetti/text-wrap-minor-words/blob/main/explainer.md" rel="noopener noreferrer"&gt;explainer&lt;/a&gt; with &lt;strong&gt;non-goals&lt;/strong&gt;, &lt;strong&gt;locale data&lt;/strong&gt;, and &lt;strong&gt;tests&lt;/strong&gt;. If you have production samples or edge cases, please share them — they’re exactly what a future proposal needs.&lt;/p&gt;




&lt;h2&gt;
  
  
  Try it &amp;amp; tell me what breaks
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Live demo: &lt;a href="https://jlorenzetti.github.io/text-wrap-minor-words/" rel="noopener noreferrer"&gt;https://jlorenzetti.github.io/text-wrap-minor-words/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Repo: &lt;a href="https://github.com/jlorenzetti/text-wrap-minor-words" rel="noopener noreferrer"&gt;https://github.com/jlorenzetti/text-wrap-minor-words&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;CodePen: &lt;a href="https://codepen.io/jlorenzetti/pen/zxvXewX" rel="noopener noreferrer"&gt;https://codepen.io/jlorenzetti/pen/zxvXewX&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Got an edge case (especially in English display, or a new locale)? &lt;strong&gt;Open an issue&lt;/strong&gt; or drop a comment — examples and screenshots are gold.&lt;/p&gt;

</description>
      <category>css</category>
      <category>typography</category>
      <category>webdev</category>
      <category>i18n</category>
    </item>
  </channel>
</rss>
