LINEミニアプリの下端ボタンが押せなくなっていませんか。Edge-to-edge 適用と、CSS 1行の正体
まず、お手元の LIFF アプリを Android 端末で開いてみてください。画面の一番下に置いたボタンが、システムのナビゲーションバーと重なっていませんか。
2026 年 3 月 9 日、Android 版 LINE に Edge-to-edge が適用されました。これから起きることではなく、すでに適用済みです。気づかないまま、下端のボタンが押しにくい状態で公開されている可能性があります。
対処は CSS 1 行です。ただしその 1 行が、なぜ 2 つの変数の入れ子という奇妙な形をしているのか。そこを理解しておかないと、環境によって効いたり効かなかったりする現象に振り回されます。
何が起きているのか
Edge-to-edge とは、アプリの描画領域を画面の端まで広げる表示方式です。ステータスバーやナビゲーションバーの裏側にもコンテンツが描かれます。
LINE の告知はこうなっています。
2026 年 3 月 9 日(UTC+9)以降、Android 版 LINE のバージョン 26.3.0 以降で Edge-to-edge が適用されます。すべての LIFF アプリおよび LINE ミニアプリが対象です。LIFF ブラウザの画面サイズは、Full、Tall、Compactのすべてが対象となります。
対象がすべての画面サイズである点に注意してください。Full だけの話ではありません。Tall や Compact で作ったアプリも同じように影響を受けます。
具体的な症状はこうです。
- 画面下端に固定した送信ボタン・購入ボタンが、ナビゲーションバーと重なる
- ジェスチャーナビゲーションの「バー」の下にボタンが潜り、タップが吸われる
- フッターのテキストが見切れる
「押せなくはないが、押しにくい」という中途半端な壊れ方をするため、動作確認で見落とされやすいのが厄介なところです。
なぜ避けられないのか
これは LINE 側の裁量による変更ではありません。 Android のプラットフォーム側で Edge-to-edge が強制されるようになったことへの追随です。
経緯を追うと、逃げ道が段階的に塞がれてきたことが分かります。
Android 15 enforced edge-to-edge for apps targeting Android 15 (API level 35), but your app could opt-out by settingR.attr#windowOptOutEdgeToEdgeEnforcementtotrue.
For apps targeting Android 16 (API level 36),R.attr#windowOptOutEdgeToEdgeEnforcementis deprecated and disabled, and your app can't opt-out of going edge-to-edge.
出典: Behavior changes: Apps targeting Android 16 or higher | Android Developers
Android 15(API 35)では opt-out できましたが、Android 16(API 36)を対象にすると opt-out 自体が無効化されます。つまり、待っていても元には戻りません。LINE に限らず、Android で WebView を使うサービスは同じ対応を迫られています。
LIFF まわりでは、この 1 年ほどプラットフォーム側の変更が続いています。LIFF アプリの LINE ミニアプリへの統合については LIFFアプリ廃止に向けた移行ガイド にまとめました。あわせて確認しておくと、どこまでが自社都合で、どこからが追随必須なのかを切り分けやすくなります。
対処は1行。ただし意味を理解する
公式が案内している対処はこれだけです。
margin-bottom: var(--android-safe-area-inset-bottom, env(safe-area-inset-bottom));var() の第 2 引数はフォールバック値です。つまりこの 1 行は、次の意味になります。
--android-safe-area-inset-bottomが定義されていればそれを使う。定義されていなければ、標準のenv(safe-area-inset-bottom)を使う。
ここで疑問が浮かぶはずです。なぜ標準の env() だけではだめなのか。
iOS でノッチ対応をしたことがある方なら、env(safe-area-inset-bottom) は馴染みのある書き方でしょう。Web 標準として定義されており、本来ならこれ 1 つで済むはずです。
答えは、Android の WebView 側にあります。
WebView の対応差が、独自変数を必要にする
Android の公式ドキュメントに、safe-area-inset-* のサポート状況が書かれています。
M136 —displayCutout()andsystemBars()support through CSS safe-area-insets. Fullscreen WebViews only.
M144 —displayCutout()andsystemBars()support. All WebViews (regardless of fullscreen state).
出典: Understand window insets in WebView | Android Developers
整理するとこうなります。
| WebView バージョン | env(safe-area-inset-*) が効く範囲 |
|---|---|
| M136 | 全画面の WebView のみ |
| M144 以降 | すべての WebView(全画面かどうかを問わない) |
ここが核心です。 LIFF ブラウザは Tall や Compact という「全画面ではない」サイズを持ちます。
M144 より前の WebView では、標準の env() が全画面の WebView でしか効きません。つまり Tall や Compact で作ったアプリは、標準の書き方だけでは safe-area の値を取得できない、という穴が空きます。
その穴を埋めるために、LINE が独自の CSS 変数 --android-safe-area-inset-bottom を注入している、というのが 2 つの変数を入れ子にする理由です。LINE の告知にも対応関係が明記されています。
WebView バージョン 144 以降の環境ではsafe-area-inset-bottomを使用し、WebView バージョン 144 未満の環境ではフォールバックとして--android-safe-area-inset-bottomを使用します。
なお、Android の公式ドキュメントは M144 未満での回避策を示していません。プラットフォーム側が手当てしていない領域を、LINE が独自に埋めている構図になります。
⚠️ ひとつ補足しておくと、LINE の告知は「WebView バージョン 144」、Android の公式ドキュメントは「M144」という表記で、両者が同一のものを指すという明示的な記述は確認できていません。ただしサポート範囲の説明が一致しているため、同じものと解釈しています。
書き方の注意
margin-bottom に直接書くより、変数に一度受けたほうが扱いやすくなります。
:root {
/* 独自変数を優先し、無ければ標準の env() にフォールバック */
--safe-bottom: var(--android-safe-area-inset-bottom, env(safe-area-inset-bottom));
}
.fixed-footer {
position: fixed;
bottom: 0;
/* 元の余白に safe-area 分を足す。上書きではなく加算にするのがポイント */
padding-bottom: calc(12px + var(--safe-bottom));
}padding-bottom を単純に var(--safe-bottom) で上書きすると、safe-area が 0 の環境(ノッチのない端末や 3 ボタンナビゲーション)で元の余白まで消えてしまいます。calc() で加算するのが実務的です。
⛔ viewport-fit=cover を忘れないでください。
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">これが無いと、safe-area-inset-* が 0 のままになります。「CSS を書いたのに効かない」という場合、まずここを疑ってください。
2種類のナビゲーションで試して確認する
Edge-to-edge の確認で見落としやすいのが、ジェスチャーナビゲーションと 3 ボタンナビゲーションで挙動が異なる点です。
| ナビゲーション | 挙動 |
|---|---|
| ジェスチャー | 細いバーのみ。safe-area は比較的小さい |
| 3 ボタン | 戻る・ホーム・履歴のボタン領域。 safe-area が大きく、重なりが顕著 |
片方だけで確認すると、もう片方で破綻します。Android の設定 →「システム」→「ジェスチャー」から切り替えられるので、両方で確認してください。
実際の値を確認する
数値を目で見るのが確実です。検証用のページにこんなコードを仕込んでおくと、その場で判断できます。
// env() が実際に効いているかを測る
const probe = document.createElement('div');
probe.style.cssText =
'position:fixed;bottom:0;height:env(safe-area-inset-bottom);visibility:hidden';
document.body.appendChild(probe);
const envPx = probe.getBoundingClientRect().height;
probe.remove();
// LINE が注入する独自変数も読む
const androidVar = getComputedStyle(document.documentElement)
.getPropertyValue('--android-safe-area-inset-bottom').trim();
console.log('env =', envPx, '/ android-var =', androidVar || '(未定義)');env が 0 で android-var に値が入っていれば、まさにフォールバックが必要な環境です。両方 0 なら viewport-fit=cover の書き忘れを疑ってください。
同じ型の罠は他にもある
セーフエリアまわりには、「同じ CSS が環境によって効いたり効かなかったりする」という共通の厄介さがあります。
私たちも別のところで同じ型の問題を踏みました。社内ツールを iOS のホーム画面に PWA として追加したところ、画面の下端に不自然な空白が出るという症状です。
原因は 100dvh でした。apple-mobile-web-app-status-bar-style を black-translucent にしていると、100dvh が「画面高 − safe-area-inset-top」に解決されることがあり、その分だけ下に余白が生まれます。厄介なのは、同じ端末・同じ画面でも出るときと出ないときがあることでした。実測すると、ずれ量は 59pt。ちょうど safe-area-inset-top と一致していました。
結局、dvh に頼るのをやめ、window.innerHeight の実測値を CSS 変数に流し込む方式に変えて解決しました。
/* dvh を信用せず、実測値を使う。未対応環境では従来値に退避 */
height: var(--app-h, 100dvh);教訓は共通しています。セーフエリアは「仕様どおりに動く」という前提を置かず、実機で値を測る。 仕様書を読んで書いたコードが、実機で違う振る舞いをする領域だと理解しておくことです。
まとめ
- Edge-to-edge の適用は 2026 年 3 月 9 日で完了済み 。これから起きることではなく、すでに起きている
- 対象は すべての LIFF アプリ・ミニアプリ、画面サイズ
Full/Tall/Compactのすべて - 対処は
var(--android-safe-area-inset-bottom, env(safe-area-inset-bottom))の 1 行 - 独自変数が要る理由は、WebView M144 未満で標準の
env()が全画面以外に効かないから viewport-fit=coverが無いとsafe-area-inset-*は 0 のまま- 確認はジェスチャーナビと 3 ボタンナビの両方で行う
プラットフォーム側の変更に追随する作業は、派手さはありませんが放置すると確実に効いてきます。
出典
- LINE Developers「ニュース(2026年)」Edge-to-edge 適用のお知らせ
- Android Developers「Understand window insets in WebView」 M136 / M144 の対応範囲
- Android Developers「Behavior changes: Apps targeting Android 16 or higher」opt-out の廃止
- Chrome for Developers「Chrome on Android edge-to-edge migration guide」
※ 情報は 2026 年 8 月時点のものです。
この検証を行ったのは 株式会社Amanity です。 自社で手を動かして技術を確かめたうえで、モバイルアプリ・LINEアプリ・Webアプリの受託開発を行っています。
開発について相談する