最終更新:

絵文字の組み合わせで意味が変わる - 1 文字と 2 文字以上で伝わる情報量の違い

約 8 分で読めます

スマホの絵文字キーボードで「👨‍👩‍👧‍👦」を選んだとき、あなたは 1 つの絵文字を入力したつもりでしょう。ところが、この家族絵文字の正体は「👨 + ZWJ + 👩 + ZWJ + 👧 + ZWJ + 👦」という 7 つのコードポイントの連結です。見た目は 1 文字、中身は 7 つ。絵文字の世界では、組み合わせ次第で 1 文字の意味も文字数も劇的に変わります。

ZWJ シーケンス - 見えない接着剤で絵文字を合体させる

ZWJ (Zero Width Joiner) は、Unicode のコードポイント U+200D に割り当てられた「幅ゼロの接合子」です。画面上には何も表示されませんが、前後の絵文字を 1 つに結合する接着剤の役割を果たします。

仕組みはシンプルです。絵文字 A + ZWJ + 絵文字 B と並べると、OS やアプリがこの組み合わせに対応するグリフ (描画イメージ) を持っていれば、A と B が合体した 1 つの絵文字として表示されます。対応するグリフがなければ、A と B がそのまま並んで表示されるだけです。つまり ZWJ シーケンスは「合体できたらする、できなければそのまま」という柔軟な仕組みなのです。

ZWJ シーケンス構成要素コードポイント数表示
👨‍👩‍👧‍👦👨 + ZWJ + 👩 + ZWJ + 👧 + ZWJ + 👦7家族 (父母娘息子)
👩‍💻👩 + ZWJ + 💻3女性テクノロジスト
🏳️‍🌈🏳️ + ZWJ + 🌈4レインボーフラッグ
👨‍🍳👨 + ZWJ + 🍳3男性料理人
🧑‍🚀🧑 + ZWJ + 🚀3宇宙飛行士
❤️‍🔥❤️ + ZWJ + 🔥4燃える心
👩‍❤️‍👨👩 + ZWJ + ❤️ + ZWJ + 👨5カップル

家族絵文字は ZWJ シーケンスの中でも最もコードポイント数が多い部類です。4 人家族の「👨‍👩‍👧‍👦」は 7 コードポイント、UTF-8 でエンコードすると 25 バイトにもなります。たった 1 文字の絵文字が、英語のアルファベットなら 25 文字分のデータ量を消費しているわけです。

ZWJ シーケンスの面白いところは、理論上はどんな絵文字同士でも結合を試みられる点です。「🐱 + ZWJ + 🐉」(猫とドラゴン) のような未定義の組み合わせを入力しても、エラーにはなりません。対応グリフがないので猫とドラゴンが並んで表示されるだけです。Unicode Consortium が公式に定義した ZWJ シーケンスは約 600 種類ですが、ベンダーが独自に対応を追加することもあります。

国旗絵文字 - 2 文字の地域インジケータで 1 つの旗を描く

🇯🇵 (日本の国旗) は 1 つの絵文字に見えますが、実は「地域インジケータ記号文字 J」(U+1F1EF) と「地域インジケータ記号文字 P」(U+1F1F5) の 2 文字の組み合わせです。ISO 3166-1 alpha-2 の国コード「JP」を、専用の Unicode 文字で表現しているのです。

国旗国コード地域インジケータコードポイント
🇯🇵JP🇯 + 🇵U+1F1EF U+1F1F5
🇺🇸US🇺 + 🇸U+1F1FA U+1F1F8
🇬🇧GB🇬 + 🇧U+1F1EC U+1F1E7
🇫🇷FR🇫 + 🇷U+1F1EB U+1F1F7
🇧🇷BR🇧 + 🇷U+1F1E7 U+1F1F7
🇰🇷KR🇰 + 🇷U+1F1F0 U+1F1F7

地域インジケータ記号は A から Z まで 26 文字あり、理論上は 26 × 26 = 676 通りの組み合わせが可能です。しかし、実際に国旗として表示されるのは ISO 3166-1 に登録された約 250 の国・地域コードだけです。未登録の組み合わせ (例えば「🇽🇽」) は、プラットフォームによって「XX」のテキストや空白として表示されます。

この設計には政治的な配慮が込められています。Unicode Consortium は「どの地域を国として認めるか」という政治的判断を避けるため、国旗の絵文字を直接定義せず、ISO 3166-1 という既存の国際規格に委ねました。新しい国が独立して ISO 3166-1 に登録されれば、Unicode の仕様を変更しなくても自動的に国旗絵文字が使えるようになります。

URL の文字数制限でも触れた通り、国コードはインターネットのさまざまな場面で使われています。ccTLD (国別トップレベルドメイン) の「.jp」も同じ ISO 3166-1 の国コードに基づいています。

肌の色修飾子 - 1 つの絵文字が 5 色に変わる仕組み

2015 年の Unicode 8.0 で導入された肌の色修飾子 (Emoji Modifier) は、人物絵文字の肌の色を変更するための仕組みです。フィッツパトリック・スケール (皮膚科で使われる肌色分類) に基づく 5 段階の修飾子が用意されています。

修飾子コードポイントフィッツパトリック分類例 (👋 + 修飾子)
🏻U+1F3FBType I-II (明るい肌色)👋🏻
🏼U+1F3FCType III (やや明るい肌色)👋🏼
🏽U+1F3FDType IV (中間の肌色)👋🏽
🏾U+1F3FEType V (やや暗い肌色)👋🏾
🏿U+1F3FFType VI (暗い肌色)👋🏿

肌の色修飾子を付けると、1 つの絵文字が 2 コードポイントになります。「👋」(U+1F44B) は 1 コードポイントですが、「👋🏽」は「U+1F44B U+1F3FD」の 2 コードポイントです。UTF-8 では 4 バイト + 4 バイト = 8 バイト。肌の色を指定するだけでデータ量が倍になるのです。

さらに、ZWJ シーケンスと肌の色修飾子を組み合わせると、コードポイント数は爆発的に増えます。例えば、肌の色が異なるカップルの絵文字「👩🏻‍❤️‍👨🏿」は、👩 + 🏻 + ZWJ + ❤️ + VS16 + ZWJ + 👨 + 🏿 で 8 コードポイントにもなります。見た目は 1 つの絵文字なのに、内部的には英語の「Hi there!」(9 文字) とほぼ同じデータ量です。

絵文字スラング - 組み合わせで生まれる隠語の世界

絵文字は公式の意味だけでなく、ユーザーコミュニティの中で独自のスラングとしても使われています。単体では無害な絵文字が、組み合わせることで全く別の意味を持つようになるのです。

最も有名なのは 🍑🍆 の組み合わせでしょう。桃とナスという食べ物の絵文字ですが、SNS 上では性的な暗喩として広く認知されています。Instagram は 2019 年にこの組み合わせを含む投稿の検索結果を制限する措置を取りました。

絵文字の組み合わせ文字数公式の意味スラングとしての意味
🍑🍆2 文字桃とナス性的な暗喩
🧢1 文字野球帽嘘 (cap = 嘘をつく)
💀1 文字頭蓋骨笑いすぎて死んだ
🐐1 文字ヤギGOAT (Greatest Of All Time)
👁️👄👁️3 文字目と口驚き・困惑の顔
🫠1 文字溶ける顔恥ずかしい・照れる
🤡1 文字ピエロ愚かな行動をした人

「👁️👄👁️」は 3 つの絵文字を並べて顔を作る、いわゆる「絵文字アート」の一種です。目 + 口 + 目で「何とも言えない表情」を表現しています。この 3 文字の組み合わせは 2020 年頃から TikTok を中心に流行し、驚きや困惑、あるいは「見てしまった」というニュアンスで使われます。

絵文字スラングは世代や地域によって解釈が異なります。日本では 🙏 は「お願い」や「ありがとう」の意味で使われますが、欧米では「ハイタッチ」と解釈されることもあります。絵文字の Unicode と文字数カウントで解説した通り、絵文字の技術的な文字数と、人間が感じる「意味の量」は全く別の次元の話なのです。

SNS ごとの絵文字カウント方法の違い

絵文字の文字数カウントは、プラットフォームによって大きく異なります。同じ絵文字を投稿しても、Twitter (X) と Instagram では消費する文字数が違うのです。

プラットフォーム絵文字のカウント方法👨‍👩‍👧‍👦 のカウント🇯🇵 のカウント
Twitter (X)NFC 正規化後の文字数1 文字 (= 2 文字分消費)1 文字 (= 2 文字分消費)
InstagramUTF-16 コードユニット数11 文字分4 文字分
LINE独自カウント1 文字1 文字
SMSUCS-2 (16 ビット)7 文字分2 文字分
JavaScriptUTF-16 コードユニット.length = 11.length = 4

Twitter (X) は比較的寛大で、ZWJ シーケンスの家族絵文字も国旗絵文字も、見た目通り 1 つの絵文字として扱います (ただし内部的には 2 文字分の重みを持ちます)。Twitter の文字数制限で詳しく解説していますが、280 文字の制限内で絵文字は 1 つあたり 2 文字分としてカウントされます。

一方、JavaScript の .length プロパティは UTF-16 コードユニット数を返すため、サロゲートペアを含む絵文字は見た目の文字数より大きな値になります。家族絵文字「👨‍👩‍👧‍👦」の .length は 11 です。正確な文字数を得るには Array.from(str).length[...str].length を使う必要がありますが、これでも ZWJ シーケンスは分解されて 7 と返ります。書記素クラスタ (grapheme cluster) 単位でカウントするには Intl.Segmenter API を使います。

SNS の文字数制限まとめも参考にしてみてください。プラットフォームごとのカウント方法の違いを知っておくと、絵文字を多用する投稿で「文字数オーバー」に悩まされることが減ります。

絵文字しりとりと映画タイトル当て - 遊びの中の文字数

絵文字を使った遊びも、文字数の観点から見ると面白い発見があります。

「絵文字しりとり」は、絵文字の名前でしりとりをするゲームです。🍎 (りんご) → 🦍 (ゴリラ) → 🍛 (ラーメン)... のように続けます。ルールは簡単ですが、絵文字の正式名称を知らないと意外と難しい。例えば 🫥 の正式名称は「Dotted Line Face」(点線の顔) です。日本語名は「点線で描かれた顔」。しりとりでは「か」で始まる絵文字を探す必要がありますが、絵文字の日本語名は Unicode の CLDR (Common Locale Data Repository) で定義されており、約 3,600 個の絵文字すべてに日本語名が付いています。

「絵文字で映画タイトルを当てる」ゲームも人気です。例えば「🦁👑」は「ライオンキング」(2 文字で 5 文字のタイトルを表現)、「👻👻👻🔫」は「ゴーストバスターズ」(4 文字で 9 文字のタイトルを表現)、「🧙‍♂️💍🌋」は「ロード・オブ・ザ・リング」(3 文字で 10 文字のタイトルを表現) です。絵文字の組み合わせは、文字数を大幅に圧縮しながら意味を伝える、一種の「超圧縮言語」と言えるかもしれません。

プログラミングで絵文字の「本当の文字数」を取得する

開発者にとって、絵文字の文字数カウントは頭痛の種です。言語やランタイムによって返る値がバラバラだからです。

言語 / 環境メソッド「👨‍👩‍👧‍👦」の結果カウント単位
JavaScript"👨‍👩‍👧‍👦".length11UTF-16 コードユニット
JavaScript[..."👨‍👩‍👧‍👦"].length7コードポイント
Python 3len("👨‍👩‍👧‍👦")7コードポイント
Swift"👨‍👩‍👧‍👦".count1書記素クラスタ
Rust"👨‍👩‍👧‍👦".len()25バイト (UTF-8)
Golen("👨‍👩‍👧‍👦")25バイト (UTF-8)

Swift だけが「1」を返すのは、Swift が書記素クラスタ (grapheme cluster) を文字の単位として採用しているからです。人間の直感に最も近い結果ですが、内部的な処理コストは高くなります。JavaScript で同じ結果を得るには Intl.Segmenter を使います。

Unicode の基礎知識で解説した通り、「文字数」の定義はコンテキストによって異なります。絵文字の組み合わせは、この問題を最も鮮明に浮き彫りにする存在です。全角と半角の文字数カウントの違いと同様に、絵文字のカウント方法もプラットフォームや言語によって異なることを覚えておきましょう。

絵文字の未来 - 組み合わせの可能性は無限大

Unicode 16.0 (2024 年) の時点で、絵文字の総数は約 3,790 個です。しかし、ZWJ シーケンスや肌の色修飾子の組み合わせを含めると、表現可能なバリエーションは数万通りに達します。

2024 年には「方向修飾子」が導入され、人物絵文字の向きを左右に変えられるようになりました。🏃 (走る人) に方向修飾子を付けると 🏃‍➡️ (右向きに走る人) になります。これもコードポイント数を増やす要因です。

絵文字の組み合わせは、テキストコミュニケーションの表現力を飛躍的に高めました。1 文字の絵文字が内部的に何コードポイントで構成されているかは、普段のチャットでは気にする必要はありません。しかし、文字数制限のある SNS への投稿や、データベースの文字数設計、プログラミングでの文字列処理では、この「見た目の文字数」と「内部的な文字数」のギャップが思わぬ落とし穴になります。

LINE メッセージの文字数の記事でも触れていますが、絵文字を多用するメッセージは、テキストだけのメッセージよりもデータ量が大きくなります。次に絵文字を選ぶとき、その 1 文字の裏側にどれだけのコードポイントが隠れているか、ちょっと想像してみると面白いかもしれません。

絵文字や Unicode の仕組みに興味が湧いたら、関連書籍を Amazon で探してみてください

この記事を共有