はじめに
はじめまして。東京理科大学大学院 創域理工学研究科 情報計算科学専攻 修士1年の佐藤太心です。
私は2025年度のサマーインターンシップで、LINEギフトのサービスフロントエンド開発業務に従事しました。このレポートでは、LINEギフトの新たなキャンペーンである「ギフトくじ」のフロントエンド実装における体験談、そして6週間にわたるインターンシップを通して学んだこと・感じたことを書いています。
LINEギフトとは
みな さん、LINEギフトはご存知でしょうか。LINEアプリ上で友だちと簡単にギフトを贈り合えるサービスで、私自身は大学の友人から誕生日にeギフトをもらったのをきっかけに使うようになりました。
技術スタック
LINEギフトのフロントエンドはVue 3 + TypeScriptで構成されており、今回のインターンシップでもその技術スタックで開発しました。
タスクと開発の流れについて
インターンシップ期間の3分の2ほどをかけて取り組んだ「ギフトくじ履歴画面」の実装について紹介します。
※景品等はイメージです。実際のギフトくじ履歴画面の内容とは異なる場合があります。
ギフトくじとは
LINEギフトでは、2025年10月に「ハロウィンギフトくじ」キャンペーンを行いました。期間中に対象商品を友だちに贈ると、ギフトを贈った人ともらった人の両方が抽選に参加できるキャンペーンで、後日抽選で人気ギフトが当たります。
ギフトくじ履歴画面の実装
今回実装した「ギフトくじ履歴画面」では、友だちからもらった/友だちに贈ったギフトくじの番号や、くじの当選結果を確認できます。企画の方が考えてくださった仕様書をもとに機能を実装し、デザイナーの方のFigmaをもとにUIを実装するという流れでした。しかし、実装を進めていくと思わぬ問題点が発覚し、途中で仕様やデザインを修正していただく場面もありました。
LINEギフトのデザインデータは、基本的にはビューポート幅が375pxの場合を基準に作成され、それ以外の横幅の場合は実装者が適宜レイアウトを調整します。しかし、ギフトくじ履歴画面では下図のAs-isのように、横幅320pxの環境では名前のほとんどが省略されてしまうほか、くじ番号やボタンの大きさや配置をエンジニアの裁量だけでは決めかねる状況でした。そこで、要素の大きさやフォントサイズを手元で調整しながら、横幅320px時のデザイン仕様をデザイナーの方と一緒にTo-beのような形に決めました。(ちなみにiPhone SE(第1世代)のように実際の画面横幅が320pxの場合のみならず、より大きい画面サイズのスマートフォンでも拡大表示設定している場合を想定し、横幅320pxでも画面が崩れないように調整しました。)

与えられたタスクを進めるだけでなく、企画やデザイン、そしてサーバーの方とも密に連携を取ることの重要性を感じました。「この仕様は、こういう解釈で実装して問題ないか」、「このデザインは、他のコンポーネントのこの部分に合わ せたほうがいいかもしれない」、そして「この内容を処理するために、他にもこの項目をAPIで返してほしい」など、「こうしたほうがいい」と思ったことを積極的に提案できる環境でした。
試行錯誤と得られた知見
個人開発や大学サークル内での開発ではなかなか気づかないような課題に直面し、とてもよい経験になりました。ここでは、以下の2つをピックアップしてご紹介します。
- 絵文字を含む文字列のトランケーション
- Lottie形式のアニメーションの実装
1. 絵文字を含む文字列のトランケーション
絵文字はUnicodeで標準化されており、OSやフォントの更新によって順次新しいものが追加されています。その中でも、ZWJ(ゼロ幅接合子)を使い、複数の絵文字を組み合わせて1つの絵文字のように表示するようなものも増えています。たとえば、絵文字「ライム🍋🟩」は「レモン🍋 + ZWJ + 緑の大四角🟩」から構成されています。

このように合字表現される絵文字を含む文字列を特定の文字数でトランケート(切り詰め)しようとしたときに、以下の画像のAs-isのようになってしまい、期待通りにならない問題が発生しました。

結論
先に結論から説明すると、文字数でのトランケーションをあきらめ、CSSのみを使い、あふれたコンテンツに省略記号をつける実装が最も妥当だと判断しました。以下の例では、containerの横幅にnameArea全体が収まりきるように、nameBodyをトランケートしています。
<div class='container' id='container'>
<div class='nameArea'>
<span
class='nameBody'
id='name'>🍋🟩🍋🟩🍋🟩🍋🟩🍋🟩🍋🟩🍋🟩🍋🟩🍋🟩🍋🟩🍋🟩🍋🟩🍋🟩🍋🟩🍋🟩🍋🟩🍋🟩🍋🟩🍋🟩🍋🟩</span><span
class='nameSuffix'>さんからもらった
</span>
</div>
</div>
.container {
width: 200px;
border: 1px solid #e0e0e0;
}
.nameArea {
display: flex;
}
.nameBody {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.nameSuffix {
flex: none;
}
原因と試行錯誤
正常にトランケートできない原因は、絵文字を含む文字列の文字数を正しくカウントできないことにありました。まず、単純に絵文字のlengthを取ろうとすると、以下のようになります。
console.log('🍋🟩'.length);
// 5
また、配列に変換した後に長さを取得すると、以下のようになります。
console.log(Array.from('🍋🟩').length);
// 3
console.log(Array.from('