ウェブページでスペース付きの句読点を直前の単語と分離しないようにするには、通常のスペースを改行なしスペースに置き換えるか、その組み合わせを小さなCSSの折り返し禁止spanで囲みます。MacでローカルのHTMLテストを使い、さまざまな幅で結果を確認します。

このガイドは、MacでページのテキストやHTMLを編集する人を対象としています。たとえば、幅の狭いカードにある Beta : のような簡潔なタイルラベルです。目的は、見た目のスペースを保ちながら、コロンだけが次の行に折り返されないようにすることです。例では意図的にそのスペースを残しています。

どの方法を選べばよいですか?

まず、スペースのルールをテキスト自体に持たせるのか、ページの表示方法に持たせるのかを決めます。Unicodeでは、U+00A0 NO-BREAK SPACE を通常のスペースに対応する改行なしスペース、U+202F NARROW NO-BREAK SPACE をその幅の狭い変種と定義しています。この2つで、見た目の異なるスペースを選べます。Unicode Standard, Chapter 6

編集時の状況 推奨する方法 確認事項
テキストを変更でき、通常幅のスペースを使いたい 通常のスペースを U+00A0 に置き換える 保存したテキストに改行なし文字が含まれている
意図的に幅の狭いスペースを使いたい U+202F を使う ページで実際に使われているフォントで適切に見える
テキスト内の通常のスペースを維持したい ペア全体を含むspanに white-space: nowrap を適用する spanに単語、スペース、句読点がすべて含まれている
ページを閲覧することしかできない 編集可能なソースで修正するか、管理者に依頼する ローカルで試しても元のページは変更されない

HTMLソースでは Beta : と記述します。WHATWGの文字参照表では、  は U+00A0 に対応しています。既存のスペースを置き換え、参照の前に通常のスペースを残さないでください。HTML Standard: Named character references

表示ルールを使う場合は、Beta : をインラインspanに入れ、そのspanに white-space: nowrap を適用します。周囲の段落は通常どおり折り返せる状態にしておきます。MDNによると、white-space は空白の扱いと折り返しの両方を制御します。MDN: white-space

実際に決めるのは、どの範囲のテキストをひとまとまりにするかです。この例では Beta : だけを保護します。Tile Alpha Beta : Next tile 全体を保護すると、ラベル全体の折り返しが不必要に制限されます。意図する関係を表す最小の範囲から始めましょう。

TextEditでローカルテストを作る方法

既存のページを変更する前に、別のテストファイルを作成します。Appleの説明によると、TextEditでプレーンテキストモードを使ってHTMLファイルを作成し、拡張子を .html にして保存できます。確認メッセージが表示されたら Use .html を選びます。Work with HTML documents in TextEdit on Mac

  1. TextEditを開き、File > New を選びます。
  2. Format > Make Plain Text を選びます。
  3. 以下の例全体を貼り付けます。
  4. File > Save を選び、ファイル名を punctuation-test.html にします。
  5. 確認されたら Use .html を選びます。
  6. Safariで File > Open File を使い、保存したファイルを開きます。

これは単体で動作する完全なHTMLドキュメントです。ライブラリの導入やインストール、ネットワーク接続は必要ありません。3つのカードには同じ仮想テキストが使われており、各カードではコロン前のスペースの処理が異なります。

<!doctype html>
<html lang="en">
<meta charset="utf-8">
<title>Punctuation wrap test</title>
<style>
  body {
    font: 20px/1.5 system-ui, sans-serif;
    margin: 2rem;
  }
  .card {
    width: 14ch;
    max-width: 100%;
    border: 1px solid #888;
    padding: 1rem;
    margin-block: 1rem;
  }
  .pair {
    white-space: nowrap;
  }
</style>
<h1>Punctuation wrap test</h1>
<h2>Ordinary space</h2>
<p class="card">Tile Alpha Beta : Next tile</p>
<h2>Nonbreaking space</h2>
<p class="card">Tile Alpha Beta&nbsp;: Next tile</p>
<h2>Local no-wrap rule</h2>
<p class="card">Tile Alpha <span class="pair">Beta :</span> Next tile</p>
</html>

サンプルの文字参照はパーサーで確認し、&nbsp; が U+00A0 に変換されることを確かめました。作成時にはブラウザーでの表示確認は行っていません。Macのブラウザーでレイアウトを確認するには、以下の比較を行ってください。

1枚のスクリーンショットではなく、折り返し位置を比べる

例にある 14ch は開始点であり、特定の折り返し位置を保証する値ではありません。値を 10ch に変更して保存・再読み込みし、その後 18ch も試してください。通常のスペースを使ったカードで、Beta とコロンが分かれる幅を探します。保護した2つのバージョンでは、ほかの単語は折り返されても、Beta とコロンは一緒に残るのが意図した結果です。

最初に3つのカードが同じように見えても、スペースの処理が同等だとは限りません。単にそのペアを表示する余裕があるだけかもしれません。関係する部分が行末に来るまで幅を変え、文字を拡大してもう一度試してください。

TextEditでファイルを開き直すときは、File > Open を選んでファイルを指定し、Show Options を選びます。必要に応じて Ignore rich text commands を選択してください。Appleは Display HTML files as HTML code instead of formatted text という設定も説明しています。これらのオプションを使うと、ソースを直接編集できます。Apple’s TextEdit HTML instructions

改行なしスペースを使っても失敗するのはなぜですか?

改行なし文字は、ブラウザーのテキストフローのルールの範囲で機能します。目に見えない文字を追加する前に、問題の原因がコンテンツ、優先されるCSSルール、またはレイアウトの境界のどれなのかを確認してください。

ページに参照文字列がそのまま表示される

ページに &nbsp; という文字が表示される場合、HTML文字参照として解析されず、テキストとして扱われています。HTMLソース欄では Beta&nbsp;: を使います。通常のテキスト欄では、実際の改行なし文字を挿入します。

JavaScriptでも同じ違いがあります。textContent を使って文字列を設定すると、テキストが作成されます。HTML参照は解析されません。JavaScript文字列には "Beta\u00A0:" としてその文字を含められます。また、1つのスペースを直すために書式付き段落全体へ textContent を設定するのは避けてください。既存の子要素が置き換えられます。MDN: Node.textContent

CSSルールによって通常より強い折り返しが許可されている

line-break: anywhere が指定されていないか確認します。MDNによると、この値は、グルークラスやワードジョイナークラスに関連する禁止事項を無視し、タイポグラフィ上の文字単位の境界で折り返しを許可します。そのため、改行なし文字を追加しても、この設定を無条件に上書きできるわけではありません。MDN: line-break

overflow-wrap も確認してください。その値が anywhere の場合、オーバーフローを避ける必要があれば、通常は分割できない文字列でも途中で分割されます。この緊急時の動作は、スペースで通常どおり折り返す場合とは異なります。MDN: overflow-wrap

表示上、短いペア全体を一緒に保つ必要がある場合は、ローカルな折り返し禁止spanを使います。特にページのスタイルシートに、より具体的なセレクターがある場合は、そのspanに実際に適用されているルールを確認してください。修正の適用範囲を絞り、関係のない長文はこれまでどおり折り返せるようにします。

句読点が別のレイアウトボックスに入っている

コロンが通常のインラインテキストなのか、inline-block などのアトミックなインライン要素に入っているのかを確認します。W3Cは、アトミックなインライン要素の前後に特別な改行可能位置があることを定めており、隣接する改行なしスペースに関する例外もあります。そのようなボックスの隣に挿入したスペースは、連続したテキスト内のスペースと同じではありません。CSS Text Module Level 3: Line Breaking Details

この単純なラベルでは、単語、スペース、句読点を1つの通常のインラインspan内に置きます。自動折り返しを意図している場合は、その間にある明示的な <br> を削除してください。nowrap は強制改行をなくすものではなく、ソフトラップを抑制します。CSS Text Module Level 3: White Space and Wrapping

ブラウザーのシェーピングを保ち、幅の狭いレイアウトに対応するには?

単語を1文字ずつ折り返すのではなく、単語全体を維持します。W3Cは、インライン要素の境界をまたいでシェーピングを継続する条件と、パディング、ボーダー、配置などの変更によって中断が必要になる条件を定義しています。単純なインラインspanなら、不要な書式境界を追加せずに済みます。CSS Text Module Level 3: Shaping Across Element Boundaries

ただし、物理的な制約は残ります。保護したペアを表示するには、十分な横幅が必要です。コンテナが Beta : より狭くなると、ペアを一緒に保つことでオーバーフローが起きることがあります。この状態も意図的にテストしてください。そのうえで、影響を受けるテキストを隠すのではなく、カードの幅を広げる、ラベルを短くするなどのレイアウト上の対応を選びます。折り返し禁止の動作については、W3Cのwhite-spaceの定義を参照してください。

行分割ライブラリは必要ですか?

通常のブラウザページでは、この作業にライブラリは必要ありません。linebreak というライブラリはUnicodeの改行可能位置を計算しますが、利用可能な幅と表示テキストのサイズを把握しているソフトウェアが、実際の行分割を決めるとドキュメントに明記されています。READMEには、現在Unicodeバージョン13をサポートすると記載されています。foliojs/linebreak documentation

この境界は、別のツールがすでにそのライブラリを使っている場合に重要です。改行候補の一覧だけでは、シェーピングされたテキストがブラウザーでどこで折り返されるかはわかりません。このページ編集作業では、フォントのシェーピングと最終的な行レイアウトはブラウザーに任せ、文字または局所的なCSSで意図した制約を表します。

修正を適用する前に、スペースが見えていること、行末に近い位置でも単語と句読点が一緒に保たれること、周囲のテキストは引き続き折り返せることの3点を確認します。関係をテキストに持たせる場合は改行なしスペースを、表示方法に持たせる場合は適用範囲を絞った折り返し禁止spanを使います。実際のページを、実用上最も狭い幅でもう一度確認してください。

出典