Androidでは、設定にある「表示サイズとテキスト」を変更した場合、webサイトの文字サイズが可変します。
iOSにおけるDynamic Typeの有効化のための特殊な指定や、font-sizeをremにするといった対応は不要です。
OSの設定のほかに、ブラウザにも文字サイズの変更設定があり、OS全体ではなくブラウザのみ変更することも可能です。
しかし、一部環境ではこの文字サイズの可変が正しく動作しない場合があります。
可変しないケース1:文字数が少ない
AndroidのChromeで次のHTMLを表示したとき、文字サイズはOS/ブラウザの設定値に応じて可変になります。
※ 以降のサンプルで word-break: break-all;
を指定していますが、これはサンプルテキストが画面幅を突き抜けるのを防ぐための指定で、文字サイズ可変の挙動とは無関係
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title></title>
<style>
body{word-break: break-all;}
</style>
</head>
<body>
123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
</body>
</html>
表示するテキストを減らした場合、OS/ブラウザの設定値を無視し、CSSの設定のまま表示されます。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title></title>
<style>
body{word-break: break-all;}
</style>
</head>
<body>
123456789012345678901234567890
</body>
</html>
コンテンツのテキスト量が少ない場合、文字サイズ可変が無効化されるようです。
可変しないケース2:font-sizeが小さい
テキスト量が同じでもfont-size
の指定値によって可変が有効/無効になる場合があります。
次のサンプルのテキスト量ではfont-size
が未設定の場合、可変が無効になります。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title></title>
<style>
body{word-break: break-all;}
</style>
</head>
<body>
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
</body>
</html>
しかし、デフォルトの16pxよりも大きいfont-sizeを指定すると、テキスト量が同じでも可変が有効になります。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title></title>
<style>
body{word-break: break-all;}
body{
font-size:17px;
}
</style>
</head>
<body>
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
</body>
</html>
可変しないケース3:画面幅が広い
テキスト量、font-size
が同じでも、画面幅によって可変が有効/無効になる場合があります。
以下のサンプルは、ポートレートモードで表示している場合、可変が有効になります。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title></title>
<style>
body{word-break: break-all;}
</style>
</head>
<body>
123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
</body>
</html>
しかしランドスケープモードでは可変が無効になります
可変しないケース4:特定のスタイルが指定されている
要素に特定のスタイルがあたっていると、文字サイズ可変が無効になる場合があります。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title></title>
<style>
body{word-break: break-all;}
p{height:100%;}
</style>
</head>
<body>
<p>123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890</p>
</body>
</html>
何が起きているか
可変になる文字数を確認すると、
-
font-size:10px
のときは165文字 -
font-size:20px
のときは83文字
font-size
が倍のとき文字数は半減しています。
ざっくりとしたイメージとして、テキストの文字数*font-size
で求められる、「テキストが専有している領域」のようなものがしきい値として利用されていると考えられます。
また、ランドスケープ時の場合を確認すると
-
font-size:10px
のときは317文字 -
font-size:20px
のときは159文字
このときの画面幅の比率は、
792 / 412.190 = 1.92144399427
(ポートレートが412.190px
、ランドスケープが792px
)
それぞれの文字数の比率は
317 / 165 = 1.92121212121
159 / 83 = 1.9156626506
ということで、近似した結果が得られました。
可変になる条件としての「テキストが専有している領域」の大きさは、画面幅応じて変化するようです。
文字数ではどうしても細かい数値でブレが出るため、100文字と1000文字で可変になるfont-size
をそれぞれ確認してみました。
(font-size
は小数点以下のかなり細かい数字まで判定しているため、小数点以下12桁程度を目処に確認しています)
- ポートレートで100文字のときは
16.479998588562...px
- ポートレートで1000文字のときは
1.64799994230...px
- ランドスケープで100文字のときは
31.679999351502...px
- ランドスケープで1000文字のときは
3.168px
「テキストが専有している領域」に換算すると
- ポートレートが
1647.999...
- ランドスケープが
3167.999...
-3168
それぞれの画面幅で割ってみると
- ポートレートは
1648 / 412.19 = 3.99815619011
- ランドスケープは
3168 / 792 = 4
となり、「テキストが専有している領域」が 画面幅 * 4
を上回ったとき、テキストの可変が有効になることがわかりました。
除外される要素
可変しないケース4のように、特定のスタイルが指定されている場合その要素の中のテキストは文字サイズの可変から除外されます。無効になるスタイルは以下を確認しています。(他にも存在する可能性があります)
-
height
(値の単位は何でも) position: absolute;
position: fixed;
white-space: nowrap;
white-space: pre
このうち、height
、position
については、body
より下の要素に設定した場合のみ無効になります。
つまり、
html,body{
height:100%;
}
このようなhtml
,body
に対するheight
指定では、文字サイズ可変は有効なままですが、
html,body{
height:100%;
}
body > div{
height:100%;
}
このようにbody
直下にdiv
を置き、それにheight:100%;
を指定すると、そのdiv
は子孫要素を含めて文字サイズ可変が無効になります。
除外される要素の挙動
除外されるスタイルが指定された要素のなかのテキストについては、以下の挙動をしています。
- 文字サイズ可変が有効の場合でも、文字サイズは可変しない
- 文字サイズ可変が有効になるテキスト量のカウントから除外される
文字サイズ可変が有効の場合でも、文字サイズは可変しない
次のサンプルでは
-
div
はスタイル指定なし -
p
はheight:100%;
という指定のため、div
の子孫にあるテキストのみ可変になります。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title></title>
<style>
body{word-break: break-all;}
p{height:100%;}
</style>
</head>
<body>
<div>123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890</div>
<p>123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890</p>
</body>
</html>
可変が有効になるテキスト量のカウントから除外される
除外されるスタイルが指定された要素の中にあるテキストは、可変が有効になるためのテキスト量のカウントに含まれないようです。
次のサンプルでは
-
div
のテキスト量が少ない -
p
のテキスト量は可変になるテキスト量として十分だが、height
が指定されている
という条件のため、div
の子孫にあるテキストは可変になりません。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title></title>
<style>
body{word-break: break-all;}
p{height:100%;}
</style>
</head>
<body>
<div>1234567890</div>
<p>123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890</p>
</body>
</html>
対応したコード
「テキストが専有している領域」が 画面幅 * 4
を上回ったとき、テキストの可変が有効になることがわかりました。
これは逆に言うと、font-size:400vw
なテキストが1文字でもコンテンツに存在すれば、テキストの可変が有効になることになります。
また、以下のテキストが「テキストが専有している領域」の対象になることも確認しました。
- HTMLではなくCSSの
content
プロパティによって生成された文字 - 半角スペース
よって、次のようにcontent
プロパティによって400vw
の半角スペースを追加しておくことで、コンテンツの文字量、サイズ、画面幅に関係なく、テキストの可変を有効にすることができます。
html::after{
content: "\00a0";
display: block;
width:1px;
font-size:400vw;
margin-top:-5rem;
line-height:1;
pointer-events: none;
overflow: hidden;
}