Cập nhật lần cuối:

Tổ hợp emoji thay đổi ý nghĩa - Sự khác biệt về lượng thông tin giữa 1 ký tự và 2 ký tự trở lên

Khoảng 10 phút đọc

Khi bạn chọn "👨‍👩‍👧‍👦" từ bàn phím emoji trên điện thoại, bạn nghĩ mình đang nhập 1 emoji. Thực tế, emoji gia đình này là sự nối tiếp của 7 điểm mã: "👨 + ZWJ + 👩 + ZWJ + 👧 + ZWJ + 👦". Bề ngoài là 1 ký tự, bên trong là 7. Trong thế giới emoji, tùy cách tổ hợp mà ý nghĩa và số ký tự của 1 biểu tượng có thể thay đổi đáng kể.

Chuỗi ZWJ - Keo dán vô hình hợp nhất emoji

ZWJ (Zero Width Joiner) là "ký tự nối không chiều rộng" được gán cho điểm mã Unicode U+200D. Nó không hiển thị gì trên màn hình nhưng đóng vai trò keo dán gắn kết các emoji trước và sau thành một.

Cơ chế rất đơn giản. Đặt emoji A + ZWJ + emoji B liên tiếp, nếu hệ điều hành hoặc ứng dụng có glyph (hình ảnh hiển thị) cho tổ hợp đó, A và B sẽ hợp nhất hiển thị thành một emoji. Nếu không có glyph phù hợp, A và B đơn giản hiển thị cạnh nhau. Nói cách khác, chuỗi ZWJ là cơ chế linh hoạt: "hợp nhất được thì hợp, không thì giữ nguyên".

Chuỗi ZWJThành phầnSố điểm mãHiển thị
👨‍👩‍👧‍👦👨 + ZWJ + 👩 + ZWJ + 👧 + ZWJ + 👦7Gia đình (bố mẹ con gái con trai)
👩‍💻👩 + ZWJ + 💻3Nữ kỹ thuật viên
🏳️‍🌈🏳️ + ZWJ + 🌈4Cờ cầu vồng
👨‍🍳👨 + ZWJ + 🍳3Đầu bếp nam
🧑‍🚀🧑 + ZWJ + 🚀3Phi hành gia
❤️‍🔥❤️ + ZWJ + 🔥4Trái tim bốc cháy
👩‍❤️‍👨👩 + ZWJ + ❤ + VS16 + ZWJ + 👨6Cặp đôi

Emoji gia đình nằm trong số các chuỗi ZWJ có nhiều điểm mã nhất. Gia đình 4 người "👨‍👩‍👧‍👦" có 7 điểm mã, mã hóa UTF-8 lên đến 25 byte. Chỉ 1 emoji mà tiêu tốn lượng dữ liệu tương đương 25 chữ cái tiếng Anh.

Điều thú vị của chuỗi ZWJ là về lý thuyết có thể thử nối bất kỳ hai emoji nào. Nhập "🐱 + ZWJ + 🐉" (mèo và rồng) - tổ hợp chưa được định nghĩa - sẽ không gây lỗi. Vì không có glyph phù hợp, mèo và rồng đơn giản hiển thị cạnh nhau. Số chuỗi ZWJ mà Unicode chính thức đăng ký là RGI (Recommended for General Interchange) trong danh sách Emoji 17.0 là 1.614. Tuy nhiên con số đó tính mỗi biến thể tông da thành một mục riêng; nếu gộp các biến thể tông da lại thì danh sách còn 249. Khi câu trả lời cho "có bao nhiêu chuỗi?" chênh nhau hơn sáu lần chỉ vì cách đếm, đó chính là hình ảnh thu nhỏ của khó khăn khi đếm emoji. Ngoài danh sách đó, các nhà cung cấp đôi khi tự thêm hỗ trợ.

Emoji cờ quốc gia - 2 ký tự chỉ báo khu vực vẽ 1 lá cờ

🇯🇵 (cờ Nhật Bản) trông như 1 emoji, nhưng thực tế là tổ hợp 2 ký tự: "Ký hiệu chỉ báo khu vực chữ J" (U+1F1EF) và "Ký hiệu chỉ báo khu vực chữ P" (U+1F1F5). Mã quốc gia ISO 3166-1 alpha-2 "JP" được biểu diễn bằng các ký tự Unicode chuyên dụng.

CờMã quốc giaChỉ báo khu vựcĐiểm mã
🇯🇵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

Có 26 ký hiệu chỉ báo khu vực (A đến Z), lý thuyết có 26 × 26 = 676 tổ hợp. Tuy nhiên chỉ khoảng 250 mã quốc gia và vùng lãnh thổ đăng ký trong ISO 3166-1 mới hiển thị thành cờ. Tổ hợp chưa đăng ký (ví dụ "🇽🇽") có thể hiển thị thành văn bản "XX" hoặc khoảng trắng tùy nền tảng.

Thiết kế này chứa đựng cân nhắc chính trị. Unicode Consortium tránh phán xét chính trị "khu vực nào được coi là quốc gia" bằng cách không định nghĩa trực tiếp emoji cờ, mà ủy thác cho tiêu chuẩn quốc tế hiện có ISO 3166-1. Nếu quốc gia mới độc lập và đăng ký trong ISO 3166-1, emoji cờ tự động khả dụng mà không cần thay đổi đặc tả Unicode.

Như đã thảo luận trong giới hạn ký tự URL, mã quốc gia xuất hiện ở nhiều nơi trên internet. ccTLD (tên miền cấp cao nhất mã quốc gia) ".jp" cũng dựa trên cùng mã quốc gia ISO 3166-1.

Bộ điều chỉnh tông da - 1 emoji biến thành 5 màu

Bộ điều chỉnh tông da (Emoji Modifier) được giới thiệu trong Unicode 8.0 năm 2015, dùng để thay đổi màu da của emoji người. 5 cấp độ bộ điều chỉnh dựa trên thang Fitzpatrick dùng trong da liễu.

Bộ điều chỉnhĐiểm mãPhân loại FitzpatrickVí dụ (👋 + bộ điều chỉnh)
🏻U+1F3FBType I-II (da sáng)👋🏻
🏼U+1F3FCType III (da hơi sáng)👋🏼
🏽U+1F3FDType IV (da trung bình)👋🏽
🏾U+1F3FEType V (da hơi tối)👋🏾
🏿U+1F3FFType VI (da tối)👋🏿

Thêm bộ điều chỉnh tông da biến 1 emoji thành 2 điểm mã. "👋" (U+1F44B) là 1 điểm mã, nhưng "👋🏽" là "U+1F44B U+1F3FD" - 2 điểm mã. UTF-8 là 4 byte + 4 byte = 8 byte. Chỉ định tông da đã nhân đôi kích thước dữ liệu.

Khi kết hợp chuỗi ZWJ và bộ điều chỉnh tông da, số điểm mã tăng vọt. Ví dụ emoji cặp đôi có tông da khác nhau "👩🏻‍❤️‍👨🏿" gồm 👩 + 🏻 + ZWJ + ❤ + VS16 + ZWJ + 👨 + 🏿 - 8 điểm mã. Mã hóa UTF-8 thành 28 byte. Cụm từ tiếng Anh "Hi there!" chỉ có 9 byte, nghĩa là một emoji duy nhất đang mang lượng dữ liệu hơn ba lần một lời chào ngắn.

Tiếng lóng emoji - Thế giới ẩn ngữ sinh ra từ tổ hợp

Emoji không chỉ được dùng với nghĩa chính thức mà còn được sử dụng như tiếng lóng độc đáo trong cộng đồng người dùng. Những emoji vô hại khi đứng riêng có thể mang ý nghĩa hoàn toàn khác khi kết hợp.

Ví dụ nổi tiếng nhất có lẽ là tổ hợp 🍑🍆. Đào và cà tím - emoji thực phẩm - nhưng trên mạng xã hội được công nhận rộng rãi là ẩn dụ tình dục. Điều rắc rối là về mặt chính thức, hai emoji này vẫn chỉ là thực phẩm. Người gửi có thể chỉ xếp cạnh nhau một loại quả và một loại rau, còn người nhận lại đọc ra tiếng lóng. Chính khoảng cách giữa nghĩa chính thức và cách một tin nhắn thực sự được đọc đã khiến việc hiểu sai emoji trở nên đặc thù như vậy.

Tổ hợp emojiSố ký tựNghĩa chính thứcNghĩa lóng
🍑🍆2 ký tựĐào và cà tímẨn dụ tình dục
🧢1 ký tựMũ bóng chàyNói dối (cap = nói dối)
💀1 ký tựHộp sọCười chết đi được
🐐1 ký tựDêGOAT (Greatest Of All Time)
👁️👄👁️3 ký tựMắt và miệngBiểu cảm sốc / bối rối
🫠1 ký tựMặt tan chảyXấu hổ / ngượng ngùng
🤡1 ký tựChú hềNgười làm điều ngốc nghếch

"👁️👄👁️" là dạng "nghệ thuật emoji" sắp xếp 3 emoji thành khuôn mặt: mắt + miệng + mắt, biểu đạt "biểu cảm khó tả". Tổ hợp 3 ký tự này lan truyền trên mạng xã hội, dùng để thể hiện sốc, bối rối hoặc cảm giác "vừa nhìn thấy điều gì đó". Điều thú vị là khác với chuỗi ZWJ, nó không dùng bất kỳ cơ chế nối nào: nó hoạt động thuần túy dựa trên việc ba emoji đặt cạnh nhau được đọc thành một khuôn mặt.

Tiếng lóng emoji khác nhau theo thế hệ và khu vực. Ở Nhật Bản, 🙏 dùng để nói "xin hãy" hoặc "cảm ơn", trong khi ở phương Tây đôi khi được hiểu là "đập tay". Như đã giải thích trong Unicode emoji và cách đếm ký tự, số ký tự kỹ thuật của emoji và "lượng ý nghĩa" con người cảm nhận hoàn toàn ở hai chiều khác nhau.

Đơn vị bạn dùng để đếm sẽ thay đổi số ký tự

Khi số ký tự của emoji không khớp nhau giữa nơi này và nơi khác, nguyên nhân không phải là mỗi nền tảng tùy hứng mà là sự khác biệt về việc coi cái gì là một đơn vị. Với cùng một "👨‍👩‍👧‍👦", chỉ cần đổi đơn vị là câu trả lời đã dịch chuyển từ 1 đến 25.

Đơn vị đếm👨‍👩‍👧‍👦🇯🇵Nơi dùng đơn vị này
Cụm tự vị (1 ký tự nhìn thấy)11count của Swift, Intl.Segmenter
Điểm mã72len() của Python 3, [...str].length
Đơn vị mã UTF-16 (đơn vị 16-bit)114.length của JavaScript, SMS ở chế độ UCS-2
Byte UTF-8258len() của Rust, len() của Go, độ dài byte trong cơ sở dữ liệu

Bộ đếm ký tự còn lại trên màn hình đăng bài đang trừ dần theo đơn vị nào thì không thể biết từ bên ngoài, trừ khi dịch vụ công bố. Nếu bạn định trang trí emoji cho một bài đăng đã sát giới hạn, cách chắc chắn là dán emoji vào rồi quan sát bộ đếm phản ứng thế nào. X (trước đây là Twitter) là trường hợp duy nhất có công bố quy tắc.

Twitter (X) khá rộng rãi, coi emoji gia đình chuỗi ZWJ và emoji cờ như 1 emoji theo giao diện (nhưng nội bộ mỗi cái tính 2 ký tự). Như chi tiết trong giới hạn ký tự Twitter, trong giới hạn 280 ký tự mỗi emoji tính 2 ký tự.

Thuộc tính .length của JavaScript trả về số đơn vị mã UTF-16, nên emoji chứa cặp thay thế trả về giá trị lớn hơn số ký tự nhìn thấy. Emoji gia đình "👨‍👩‍👧‍👦" có .length là 11. Để có số đếm chính xác, dùng Array.from(str).length hoặc [...str].length, nhưng chúng cũng phân tách chuỗi ZWJ và trả về 7. Để đếm theo cụm tự vị (grapheme cluster), dùng API Intl.Segmenter.

Bạn cũng có thể tham khảo tổng hợp giới hạn ký tự SNS. Biết cách đếm của từng nền tảng giúp tránh rắc rối "vượt giới hạn ký tự" khi đăng nội dung nhiều emoji.

Nối đuôi emoji và đoán tên phim - Số ký tự trong trò chơi

Các trò chơi dùng emoji cũng có phát hiện thú vị từ góc độ số ký tự.

"Nối đuôi emoji" là trò chơi nối từ tiếng Nhật bằng tên emoji. 🍎 (ringo / táo) → 🦍 (gorira / khỉ đột) → 🍜 (ramen)... và tiếp tục. Luật đơn giản, nhưng điều người chơi luôn tranh cãi lại là cái tên. Lấy ngay 🍜: tên ký tự Unicode của nó là "STEAMING BOWL", nên không có gì khẳng định đó là ramen. 🍛 là "CURRY AND RICE", nghĩa là đọc thành "cà ri" hay "cơm cà ri" sẽ thay đổi emoji nào được phép đi tiếp. Những emoji lạ mắt còn khó hơn nữa: tên ký tự của 🫥 là "DOTTED LINE FACE", nhưng cách người ta gọi nó trong lời nói hằng ngày thì mỗi người một kiểu. Tên emoji theo từng ngôn ngữ được định nghĩa trong CLDR (Common Locale Data Repository) của Unicode, và các tên bản địa hóa này là một sổ đăng ký tách biệt với tên ký tự Unicode, nên thống nhất trước rằng lấy tên CLDR làm chuẩn chính là điều giữ cho cuộc chơi không đổ vỡ giữa đường.

"Đoán tên phim từ emoji" cũng rất phổ biến. Ví dụ "🦁👑" là 2 emoji cho "Vua Sư Tử" (9 ký tự, tính cả dấu cách), "👻👻👻🔫" là 4 emoji cho "Ghostbusters" (12 ký tự), "🧙‍♂️💍🌋" là 3 emoji cho "Chúa Tể Những Chiếc Nhẫn" (24 ký tự). Tổ hợp emoji có thể coi là một dạng "ngôn ngữ siêu nén" truyền đạt ý nghĩa trong khi giảm mạnh số ký tự. Tuy nhiên thứ được nén lại chỉ là số ký tự nhìn thấy: bên trong, "🧙‍♂️" là một chuỗi ZWJ gồm 4 điểm mã. Đo bằng lượng dữ liệu thì emoji nằm hẳn về phía phình ra.

Lấy "số ký tự thực" của emoji trong lập trình

Đối với lập trình viên, đếm ký tự emoji là vấn đề đau đầu vì các ngôn ngữ và runtime trả về giá trị khác nhau.

Ngôn ngữ / Môi trườngPhương thứcKết quả cho "👨‍👩‍👧‍👦"Đơn vị đếm
JavaScript"👨‍👩‍👧‍👦".length11Đơn vị mã UTF-16
JavaScript[..."👨‍👩‍👧‍👦"].length7Điểm mã
Python 3len("👨‍👩‍👧‍👦")7Điểm mã
Swift"👨‍👩‍👧‍👦".count1Cụm tự vị
Rust"👨‍👩‍👧‍👦".len()25Byte (UTF-8)
Golen("👨‍👩‍👧‍👦")25Byte (UTF-8)

Chỉ Swift trả về "1" vì Swift sử dụng cụm tự vị (grapheme cluster) làm đơn vị ký tự. Đây là kết quả gần nhất với trực giác con người, nhưng chi phí xử lý nội bộ cao hơn. Để có kết quả tương tự trong JavaScript, dùng Intl.Segmenter.

Như đã giải thích trong kiến thức cơ bản về Unicode, định nghĩa "số ký tự" khác nhau tùy ngữ cảnh. Tổ hợp emoji làm nổi bật vấn đề này rõ ràng nhất. Giống như sự khác biệt trong cách đếm ký tự toàn chiều rộng và nửa chiều rộng, hãy nhớ rằng cách đếm emoji cũng khác nhau theo nền tảng và ngôn ngữ.

Tương lai của emoji - Khả năng tổ hợp vô hạn

Trong bảng thống kê của Emoji 17.0, phiên bản mới nhất tính đến tháng 8 năm 2026, tổng số emoji là 3.953. Tuy nhiên con số đó coi mỗi biến thể tông da là một mục riêng: trong 3.944 chuỗi đủ điều kiện đầy đủ của danh sách, 2.030 mục - hơn một nửa - là biến thể tông da. Lý do câu hỏi "có bao nhiêu emoji?" không có một đáp án duy nhất là vì vấn đề "cái gì được tính là một đơn vị", sợi chỉ xuyên suốt toàn bộ bài viết này, cũng xuất hiện ngay trong con số tổng.

Một cơ chế khá mới là chuỗi "hướng" được thêm vào ở Emoji 15.1. Nối 🏃 (người chạy) với mũi tên phải bằng ZWJ sẽ thành 🏃‍➡️ (người chạy sang phải). Bên trong, đó là 🏃 + ZWJ + ➡ + VS16, gồm 4 điểm mã và 13 byte khi mã hóa UTF-8. Chỉ đổi hướng thôi mà lượng dữ liệu đã hơn ba lần so với 🏃 ban đầu (4 byte).

Tổ hợp emoji đã nâng cao đáng kể sức biểu đạt của giao tiếp văn bản. Trong chat hàng ngày không cần quan tâm 1 emoji gồm bao nhiêu điểm mã. Nhưng khi đăng lên mạng xã hội có giới hạn ký tự, thiết kế trường ký tự cơ sở dữ liệu, hay xử lý chuỗi trong lập trình, khoảng cách giữa "số ký tự nhìn thấy" và "số ký tự nội bộ" có thể trở thành cạm bẫy bất ngờ.

Như cũng đề cập trong bài viết về số ký tự tin nhắn LINE, tin nhắn dùng nhiều emoji có dung lượng dữ liệu lớn hơn tin nhắn chỉ có văn bản. Lần tới khi chọn emoji, thử tưởng tượng xem bao nhiêu điểm mã đang ẩn sau 1 ký tự đó.

Chia sẻ bài viết này