最終更新:
絵文字の組み合わせで意味が変わる - 1 文字と 2 文字以上で伝わる情報量の違い
スマホの絵文字キーボードで「👨👩👧👦」を選んだとき、あなたは 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 + ❤ + VS16 + ZWJ + 👨 | 6 | カップル |
家族絵文字は ZWJ シーケンスの中でも最もコードポイント数が多い部類です。4 人家族の「👨👩👧👦」は 7 コードポイント、UTF-8 でエンコードすると 25 バイトにもなります。たった 1 文字の絵文字が、英語のアルファベットなら 25 文字分のデータ量を消費しているわけです。
ZWJ シーケンスの面白いところは、理論上はどんな絵文字同士でも結合を試みられる点です。「🐱 + ZWJ + 🐉」(猫とドラゴン) のような未定義の組み合わせを入力しても、エラーにはなりません。対応グリフがないので猫とドラゴンが並んで表示されるだけです。Unicode が RGI (Recommended for General Interchange = 汎用交換向け推奨) として公式に登録している ZWJ シーケンスは、Emoji 17.0 の一覧では 1,614 件です。ただしこれは肌の色の違いを別件として数えた値で、肌の色の変種をまとめると 249 件に整理されます。「何種類あるか」の答えが数え方で 6 倍以上ぶれるのは、絵文字の数え方の難しさをそのまま映しています。この一覧の外側でも、ベンダーが独自に対応を追加することがあります。
国旗絵文字 - 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+1F3FB | Type I-II (明るい肌色) | 👋🏻 |
| 🏼 | U+1F3FC | Type III (やや明るい肌色) | 👋🏼 |
| 🏽 | U+1F3FD | Type IV (中間の肌色) | 👋🏽 |
| 🏾 | U+1F3FE | Type V (やや暗い肌色) | 👋🏾 |
| 🏿 | U+1F3FF | Type VI (暗い肌色) | 👋🏿 |
肌の色修飾子を付けると、1 つの絵文字が 2 コードポイントになります。「👋」(U+1F44B) は 1 コードポイントですが、「👋🏽」は「U+1F44B U+1F3FD」の 2 コードポイントです。UTF-8 では 4 バイト + 4 バイト = 8 バイト。肌の色を指定するだけでデータ量が倍になるのです。
さらに、ZWJ シーケンスと肌の色修飾子を組み合わせると、コードポイント数は爆発的に増えます。例えば、肌の色が異なるカップルの絵文字「👩🏻❤️👨🏿」は、👩 + 🏻 + ZWJ + ❤ + VS16 + ZWJ + 👨 + 🏿 で 8 コードポイントにもなります。UTF-8 でのバイト数は 28 バイト。英語の「Hi there!」が 9 バイトですから、見た目は 1 つの絵文字でも 3 倍以上のデータ量を運んでいることになります。
絵文字スラング - 組み合わせで生まれる隠語の世界
絵文字は公式の意味だけでなく、ユーザーコミュニティの中で独自のスラングとしても使われています。単体では無害な絵文字が、組み合わせることで全く別の意味を持つようになるのです。
最も有名なのは 🍑🍆 の組み合わせでしょう。桃とナスという食べ物の絵文字ですが、SNS 上では性的な暗喩として広く認知されています。厄介なのは、絵文字そのものは公式には食べ物のままだという点です。送った側は果物と野菜を並べただけでも、受け取った側はスラングとして読む。この「公式の意味」と「実際の読まれ方」のずれが、絵文字コミュニケーション特有のすれ違いを生みます。
| 絵文字の組み合わせ | 文字数 | 公式の意味 | スラングとしての意味 |
|---|---|---|---|
| 🍑🍆 | 2 文字 | 桃とナス | 性的な暗喩 |
| 🧢 | 1 文字 | 野球帽 | 嘘 (cap = 嘘をつく) |
| 💀 | 1 文字 | 頭蓋骨 | 笑いすぎて死んだ |
| 🐐 | 1 文字 | ヤギ | GOAT (Greatest Of All Time) |
| 👁️👄👁️ | 3 文字 | 目と口 | 驚き・困惑の顔 |
| 🫠 | 1 文字 | 溶ける顔 | 恥ずかしい・照れる |
| 🤡 | 1 文字 | ピエロ | 愚かな行動をした人 |
「👁️👄👁️」は 3 つの絵文字を並べて顔を作る、いわゆる「絵文字アート」の一種です。目 + 口 + 目で「何とも言えない表情」を表現しています。この 3 文字の組み合わせは SNS 上で広まり、驚きや困惑、あるいは「見てしまった」というニュアンスで使われます。ZWJ シーケンスと違って結合の仕組みは一切使っておらず、並べただけで顔になるという発想だけで成立している点が面白いところです。
絵文字スラングは世代や地域によって解釈が異なります。日本では 🙏 は「お願い」や「ありがとう」の意味で使われますが、欧米では「ハイタッチ」と解釈されることもあります。絵文字の Unicode と文字数カウントで解説した通り、絵文字の技術的な文字数と、人間が感じる「意味の量」は全く別の次元の話なのです。
数え方の単位で絵文字の文字数は変わる
絵文字の文字数が場所によって食い違う原因は、プラットフォームの気分ではなく「何を 1 単位として数えているか」の違いです。同じ「👨👩👧👦」でも、単位を変えるだけで 1 から 25 まで答えが動きます。
| 数える単位 | 👨👩👧👦 | 🇯🇵 | この単位を使う場所 |
|---|---|---|---|
| 書記素クラスタ (見た目の 1 文字) | 1 | 1 | Swift の count・Intl.Segmenter |
| コードポイント | 7 | 2 | Python 3 の len()・[...str].length |
| UTF-16 コードユニット (16 ビット単位) | 11 | 4 | JavaScript の .length・SMS の UCS-2 モード |
| UTF-8 バイト | 25 | 8 | Rust の len()・Go の len()・DB のバイト長 |
投稿画面の残り文字数がどの単位で減るかは、サービス側が公開していない限り外からは断定できません。上限ぎりぎりの投稿を絵文字で飾るなら、実際に貼り付けてカウンターの動きを見るのが確実です。ただし X (旧 Twitter) だけは仕様が公開されています。
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 の文字数制限まとめも参考にしてみてください。プラットフォームごとのカウント方法の違いを知っておくと、絵文字を多用する投稿で「文字数オーバー」に悩まされることが減ります。
絵文字しりとりと映画タイトル当て - 遊びの中の文字数
絵文字を使った遊びも、文字数の観点から見ると面白い発見があります。
「絵文字しりとり」は、絵文字の名前でしりとりをするゲームです。🍎 (りんご) → 🦍 (ゴリラ) → 🍜 (ラーメン)... のように続けます。ルールは簡単ですが、揉めるのは必ず「名前」です。上の例の 🍜 も、Unicode 上の文字名は「STEAMING BOWL」(湯気の立つ丼) で、ラーメンと決まっているわけではありません。🍛 は「CURRY AND RICE」なので、「カレー」と読むか「カレーライス」と読むかで次に出せる絵文字が変わります。🫥 のように見慣れない絵文字も厄介で、文字名は「DOTTED LINE FACE」ですが、日本語での呼び方は人によってばらつきます。絵文字の各言語での名前は Unicode の CLDR (Common Locale Data Repository) が定義しているので、遊ぶ前に「CLDR の日本語名を正とする」と決めておくと最後まで成立します。
「絵文字で映画タイトルを当てる」ゲームも人気です。例えば「🦁👑」は絵文字 2 つで「ライオンキング」(7 文字)、「👻👻👻🔫」は絵文字 4 つで「ゴーストバスターズ」(9 文字)、「🧙♂️💍🌋」は絵文字 3 つで「ロード・オブ・ザ・リング」(中黒を除いて 9 文字) を表します。絵文字の組み合わせは、文字数を大幅に圧縮しながら意味を伝える、一種の「超圧縮言語」と言えるかもしれません。ただし圧縮できているのは見た目の文字数だけで、「🧙♂️」は内部では 4 コードポイントの ZWJ シーケンスです。データ量で見れば、絵文字はむしろ膨らむ側にいます。
プログラミングで絵文字の「本当の文字数」を取得する
開発者にとって、絵文字の文字数カウントは頭痛の種です。言語やランタイムによって返る値がバラバラだからです。
| 言語 / 環境 | メソッド | 「👨👩👧👦」の結果 | カウント単位 |
|---|---|---|---|
| JavaScript | "👨👩👧👦".length | 11 | UTF-16 コードユニット |
| JavaScript | [..."👨👩👧👦"].length | 7 | コードポイント |
| Python 3 | len("👨👩👧👦") | 7 | コードポイント |
| Swift | "👨👩👧👦".count | 1 | 書記素クラスタ |
| Rust | "👨👩👧👦".len() | 25 | バイト (UTF-8) |
| Go | len("👨👩👧👦") | 25 | バイト (UTF-8) |
Swift だけが「1」を返すのは、Swift が書記素クラスタ (grapheme cluster) を文字の単位として採用しているからです。人間の直感に最も近い結果ですが、内部的な処理コストは高くなります。JavaScript で同じ結果を得るには Intl.Segmenter を使います。
Unicode の基礎知識で解説した通り、「文字数」の定義はコンテキストによって異なります。絵文字の組み合わせは、この問題を最も鮮明に浮き彫りにする存在です。全角と半角の文字数カウントの違いと同様に、絵文字のカウント方法もプラットフォームや言語によって異なることを覚えておきましょう。
絵文字の未来 - 組み合わせの可能性は無限大
2026 年 8 月時点で最新の Emoji 17.0 の集計表では、絵文字の総数は 3,953 件です。ただしこの数え方は肌の色の変種を 1 件ずつ数えたもので、一覧に並ぶ 3,944 件の完全修飾シーケンスのうち 2,030 件、つまり半数以上が肌の色の変種です。「絵文字は何個あるのか」に一つの答えが無いのは、ここまで見てきた「何を 1 単位として数えるか」の問題が、総数の集計にもそのまま現れているからです。
比較的新しい仕組みとしては、Emoji 15.1 で加わった「方向」のシーケンスがあります。🏃 (走る人) に右向き矢印を ZWJ で繋ぐと 🏃➡️ (右向きに走る人) になります。中身は 🏃 + ZWJ + ➡ + VS16 の 4 コードポイント、UTF-8 で 13 バイト。向きを変えるだけで、元の 🏃 (4 バイト) の 3 倍以上のデータ量になります。
絵文字の組み合わせは、テキストコミュニケーションの表現力を飛躍的に高めました。1 文字の絵文字が内部的に何コードポイントで構成されているかは、普段のチャットでは気にする必要はありません。しかし、文字数制限のある SNS への投稿や、データベースの文字数設計、プログラミングでの文字列処理では、この「見た目の文字数」と「内部的な文字数」のギャップが思わぬ落とし穴になります。
LINE メッセージの文字数の記事でも触れていますが、絵文字を多用するメッセージは、テキストだけのメッセージよりもデータ量が大きくなります。次に絵文字を選ぶとき、その 1 文字の裏側にどれだけのコードポイントが隠れているか、ちょっと想像してみると面白いかもしれません。