CSSで、引用文に大きなかぎかっこを付ける方法

​​CSS​HTML,Playwright

引用文の左上に大きな開きかっこ(「)、右下に大きな閉じかっこ(」)を付けるには、<blockquote> の ::before と ::after にかっこの字を入れ、position: absolute で角に置きます。HTML には何も足さないので、引用の本文は変わりません。ただ、かっこの字は1文字分の枠の中に余白を持っているので、角に置いたつもりでも内側に寄って見えます。その直し方と、字を使わずに線でかっこを描く方法もあわせて書きます。

補足

検証環境は Ubuntu 24.04、Node.js 22.23.4、Playwright 1.63.0、Chromium 153 です。フォントは Noto Sans CJK JP で、文字の大きさは18pxです。HTML と CSS のページを Playwright で開き、画面を撮ってかっこの色の画素がある範囲を測りました。読み上げについては、Chromium のアクセシビリティツリーに何が入るかを調べています。Firefox と Safari、スマートフォンの実機、実際のスクリーンリーダー、ほかのフォントでは試していません。

blockquote の ::before と ::after にかっこを入れる

CSS は次のとおりです。

css
/* 引用文の左上と右下に、大きなかぎかっこを置く */
.quote {
  position: relative;
  margin: 1.5em 0;
  padding: 1.5em 2em;
  background: #eefafd;
}
.quote::before,
.quote::after {
  position: absolute;
  font-size: 3em;
  line-height: 1;
  color: #00c8e8;
}
.quote::before {
  content: "「";
  top: 0;
  left: 0;
}
.quote::after {
  content: "」";
  right: 0;
  bottom: 0;
}

HTML は、引用の範囲を <blockquote> で囲んで、クラスを付けるだけです。

html
<blockquote class="quote">
  <p>猫の手も借りたいほど忙しいときこそ、作業を小さく分けて、ひとつずつ片付けていくのが近道です。</p>
</blockquote>

::before と ::after は、要素の最初と最後に、CSS だけで中身を足す擬似要素です。中身は content に書きます。親の .quote に position: relative を付けておくと、position: absolute にした擬似要素は、引用の箱を基準に置かれます。top や right は、引用の箱の端からの距離になります。

font-size: 3em で、かっこは本文の3倍の54pxになりました。line-height: 1 にしておくと、擬似要素の箱は54px四方になります。本文が箱の角のかっこと重ならないように、padding で本文を内側に寄せています。

かっこが内側に寄って見えるのは、字の枠の余白のせい

上の CSS で、擬似要素の箱は引用の角にぴったり付きます。ところが、画面を撮って水色の画素がある範囲を測ると、開きかっこの線は、引用の左端から35px、上端から4px離れたところから始まっていました。閉じかっこの線も、右端から35px離れていて、下端には付いていました。かっこの線が横だけ大きく内側に入るので、角に置いたように見えません。

「字をそのまま置いた書き方」という見出しの下に、水色の背景の引用文がある。左上と右下に、擬似要素の箱をピンクの点線で囲んで示している。左上の点線の箱の中で、「の線は箱の右寄りにあり、箱の左側は空いている。右下の点線の箱の中で、」の線は箱の左寄りにあり、箱の右側は空いている
点線が擬似要素の箱。かっこの線は、箱の片側に寄っている

点線で囲んだのが、54px四方の擬似要素の箱です。Noto Sans CJK JP では、開きかっこは1文字分の枠の右上に、閉じかっこは左下に描かれ、残りは余白でした。測った線の大きさは、どちらも幅17px、高さ35pxです。

この余白の分だけ、字の箱を外へずらすと、線が角に近づきます。

css
/* かっこの字の余白の分だけ、外へずらす */
.quote-shifted {
  overflow: hidden;
}
.quote-shifted::before {
  left: -0.5em;
}
.quote-shifted::after {
  right: -0.5em;
  bottom: 0.1em;
}

<blockquote class="quote quote-shifted"> のように、2つのクラスを付けて使います。擬似要素の中の em は、擬似要素自身の文字の大きさ(54px)が基準なので、-0.5em は-27pxです。測ると、開きかっこの線は左端から8px、上端から4px、閉じかっこの線は右端から8px、下端から5pxになりました。

overflow: hidden は、ずらした字の箱が引用の外にはみ出した部分を切り取るためのものです。字の箱の外に出た部分は余白だけなので、overflow: hidden を付けたまま測っても、線は幅17px、高さ35pxで欠けていませんでした。これを付けずに、画面の幅が375pxのページに置くと、閉じかっこの字の箱の右端が386pxまで出て、ページの幅も386pxに広がりました。スマートフォンでは横にスクロールできてしまう幅です。overflow: hidden を付けると、ページの幅は375pxに戻りました。

ずらす量の-0.5emは、Noto Sans CJK JP で確かめた値です。ほかのフォントを使うときは、画面で線の位置を見て、ずらす量を決めてください。

字を使わずに、線でかっこを描く

フォントに左右されずに位置を決めたいときは、かっこの形を枠線で描きます。中身が空の擬似要素に、上と左(閉じかっこは下と右)だけの枠線を付けます。

css
/* かぎかっこの形を、線で描く */
.quote-border {
  position: relative;
  margin: 1.5em 0;
  padding: 1.5em 2em;
  background: #eefafd;
}
.quote-border::before,
.quote-border::after {
  content: "";
  position: absolute;
  width: 1em;
  height: 1em;
  border: 0 solid #00c8e8;
}
.quote-border::before {
  top: 0.5em;
  left: 0.5em;
  border-top-width: 4px;
  border-left-width: 4px;
}
.quote-border::after {
  right: 0.5em;
  bottom: 0.5em;
  border-right-width: 4px;
  border-bottom-width: 4px;
}
上下2段の比較。上の「字を外へずらした書き方」では、水色の背景の引用文の左上と右下に、細長いかぎかっこが角の近くに付いている。下の「線で描いた書き方」では、左上と右下に、縦と横の長さが同じ鉤形の線が、角から少し離れたところに付いている
字を外へずらした書き方(上)と、線で描いた書き方(下)

こちらは top などに書いた値のとおりの位置に線が出ました。0.5em(9px)と指定した左上のかっこは、引用の左端からも上端からも9pxのところから始まり、大きさは22px四方でした。width と height の18pxに、4pxの枠線が足された大きさです。

字のかっこは縦長でしたが、線で描いたかっこは、width と height を同じにしたので縦と横が同じ長さです。

読み上げとコピーでは、かっこはどう扱われるか

MDN の content の説明では、CSS で生成した中身は DOM に入らず、アクセシビリティツリーにも出ないので、支援技術とブラウザの組み合わせによっては読み上げられないとされています。ところが、Chromium 153 のアクセシビリティツリーを Playwright の ariaSnapshot() で見ると、字で入れたかっこは、本文の段落の前と後ろに、それぞれ 「 と 」 という文字として入っていました。

読み上げさせたくないときは、content の値の後ろに / と空の文字列を書きます。/ の後ろは代替テキストで、MDN の説明では、スクリーンリーダーの読み上げにはこちらが使われます。

css
/* かっこを読み上げさせない(「/」の後ろが読み上げ用の文字) */
.quote-silent::before {
  content: "「";
  content: "「" / "";
}
.quote-silent::after {
  content: "」";
  content: "」" / "";
}

この CSS を足すと、アクセシビリティツリーには段落だけが残り、かっこは消えました。擬似要素の箱の位置と大きさ(上と左が0px、54px四方)は足す前と同じで、画素で測った線の位置と大きさの差も1px以内でした。線で描いた書き方は、content が空なので、初めから段落だけでした。

content を2行書いているのは、/ の書き方に対応していないブラウザのためです。MDN にある、CSS のエラー処理の説明によると、ブラウザは値が分からない宣言を無視します。対応していないブラウザでは2行目が無視され、1行目のかっこが使われます。MDN の互換性データ(@mdn/browser-compat-data 8.1.8)によると、/ の書き方には Chrome 77、Firefox 128、Safari 17.4 から対応しています。

コピーでは、どちらの書き方でもかっこは入りませんでした。引用の中を選んで Control+C でコピーし、クリップボードの文字を読むと、本文の「猫の手も……近道です。」だけでした。

文の中の短い引用は q 要素で

段落の中の短い引用には、<q> 要素を使えます。<q> には、ブラウザがかっこを自動で付けます。何を付けるかは quotes で決まり、初期値の auto では、要素の言語(lang 属性)に合うかっこになります。

html
<p>本には<q>まず<q>小さく</q>分ける</q>と書いてあります。</p>

<html lang="ja"> のページでは、この文は「本には「まず『小さく』分ける」と書いてあります。」になりました。入れ子の内側は『』です。同じ文を lang="en" の段落に置くと、かっこは “ ” と ‘ ’ に変わりました。ページの lang を日本語にしていないときは、quotes で指定します。

css
/* 文の中の q 要素に付くかっこを、ページの言語に関係なく決める(外側、内側の順) */
.q-ja q {
  quotes: "「" "」" "『" "』";
}

lang="en" の段落に q-ja クラスを付けると、かっこは「」と『』に戻りました。

​Posted by 86