テスターから「登録できない」と報告を受けて発覚した罠の話です。
症状
<form novalidate> を付けているのに、Android版ChromeのWebView(TWA)で minlength 属性がブラウザネイティブバリデーションを発火させてsubmitを止める。
<!-- これが問題 -->
<input type="password" minlength="8">
PCのChromeでは novalidate が正常に機能するが、TWAのWebViewでは無視される。
原因
TWA(Trusted Web Activity)のWebViewはChrome for Androidと微妙に挙動が異なる。novalidate 属性を無視してHTML5バリデーションを適用するケースがある(特にAndroid 12以降)。
解決策
<!-- NG: Android WebViewがsubmitを止める -->
<input type="password" minlength="8" required>
<input type="email" id="email">
<!-- OK: HTML5バリデーション属性を完全に排除 -->
<input type="password" id="password">
<input type="text" id="email"> <!-- type="email"もNG -->
JavaScript側でバリデーションを完全制御:
if (!password) {
showFieldError('password-error', 'パスワードを入力してください');
return;
}
if (password.length < 8) {
showFieldError('password-error', 'パスワードは8文字以上で入力してください');
return;
}
if (!/^[^s@]+@[^s@]+.[^s@]+$/.test(email)) {
showFieldError('email-error', '正しいメールアドレスの形式で入力してください');
return;
}
あわせてやったこと:インラインエラー表示
フォーム上部のエラーバナーをフィールド直下のインライン表示に変更。モバイルでフォームが長いと上部バナーはスクロールアウトして見えない。
<input type="text" id="email" aria-describedby="email-error">
<p id="email-error" class="hidden mt-1 text-xs text-red-600" role="alert"></p>
function showFieldError(errorId, message) {
var el = document.getElementById(errorId);
if (!el) return;
el.textContent = message;
el.classList.remove('hidden');
}
まとめ
- TWAで
novalidateは信頼しない -
minlength/required/type="email"等のHTML5バリデーション属性はすべて削除 - バリデーションはJSで完全制御する
- エラーはフィールド直下にインライン表示(モバイルUXの鉄則)
👉 実際に動くアプリ:https://app.miterun.app
👉 Androidβテスター募集中:https://lp.miterun.app