blog.鶯梭庵

二〇一七年 皐月 十一日 木曜日

改訂版・たぶん、ほとんどの人は viewport meta タグの指定をまちがえてる・その4 [/links]

その3から続く

以上をまとめると、コンテンツ領域の幅が固定されているウェブページでは width=(コンテンツ領域の幅) と指定する。initial-scale は指定しない。

これは、モバイル向けにデザインされたウェブページでも同じだ。たとえばコンテンツ領域の幅が 320 ピクセルで固定されている場合、width=320 とする。繰り返すが、initial-scale は指定しない。この場合、画面の幅が 320 ピクセルよりも広いデバイスでは、画面に合わせて表示が拡大される。

では、width=320,initial-scale=1 と指定したらどうなるだろうか。画面の幅が 320 ピクセルよりも大きい場合、すでに述べたように width の指定が無視されるから、これは実際のところ initial-scale=1 と指定していることになる。したがって、viewport の幅が画面の幅と同じになり、そこに幅 320 ピクセルのコンテンツをレイアウトするから、デバイスによっては左右に余白ができる。

もっとも、拡大されるより余白ができたほうがよいという考えもあるだろう。それでも width=320,initial-scale=1 はまちがい。拡大を避ける正しい方法は、initial-scale=1 と指定するのが1つ。または width=device-width とする。これは、文字通り、viewport の幅を画面の幅と同じにするという意味だ。

しかし、モバイル向けページでコンテンツ領域の幅を固定するというのは、いまどき流行らない。たとえば、デバイスを横向きに回転させれば幅が広くなるが、そのときに拡大されたり余白ができたりするのは格好悪い。少なくともモバイル向けのウェブページでは、画面の幅に合わせてレイアウトを動的に変化させたほうがよい。

その場合でも、viewport の幅を画面の幅と同じにすることになる。そのための指定は、先ほどと同様、width=device-width または initial-scale=1 だ。ところが、一般には、両者を合わせて


<meta name="viewport" content="width=device-width,initial-scale=1">


と指定することが多い。だが、widthinitial-scale の両方を指定するのは避けるべきではなかったか。どちらか片方だけにするべきではないのか。

width=device-width と指定した場合に、initial-scale を 1(あるいは 1.0)以外の値にするのは、確かに不適切だ。

まず、initial-scale の値が 1 より小さい場合、width の値と initial-scale の値との積は、常に画面の幅より小さくなる。ということは、width=device-width の指定は常に無視される。常に無視される指定をわざわざ書くのは無意味だ。

また、initial-scale の値が 1 より大きい場合、せっかく画面と同じ幅の viewport にレイアウトしたウェブページを拡大して表示することになるから、ページの右側が画面の外に出る。それを見るためには横にスクロールしなければならない。わざわざそんな表示にする理由はないはずだ。

しかし width=device-width,initial-scale=1 なら、同じ意味の指定を2度書いたまでで、とりわけて問題はない。同じことを繰り返すのは、冗長ではあるが、まちがいではない。古いバージョンの Safari では、デバイスを横向きにしたときに viewport が広がるのではなくスケールが大きくなり、拡大されて表示されるという問題があったが、それは3年前の話で、もう考慮しなくてもよいだろう。

なお、Windows Phone 版の IE は initial-scaleサポートしていないそうだ。そのため、強いてどちらか片方だけを指定するなら、width=device-width を指定したほうがよいだろう。

その5に続く。

[この記事だけを読む。] [この記事にコメントを書く。] [最新の記事を読む。]

二〇一七年 皐月 七日 日曜日

改訂版・たぶん、ほとんどの人は viewport meta タグの指定をまちがえてる・その3 [/links]

その2から続く

width をピクセル数で指定したときに initial-scale を指定するべきでない理由がもう1つある。

たとえば width=250,initial-scale=1 と指定してみよう。これまで述べてきた方式を適用すれば、幅 250 ピクセルの viewport に合わせてウェブページがレイアウトされて、それが等倍で表示されるから、デバイスの左 250 ピクセル分だけにウェブページが表示され、右端は空白になることになる。あるいは width=500,initial-scale=0.5 と指定した場合、幅 500 ピクセルの viewport に合わせてウェブページがレイアウトされて、それが 50% 縮小されて表示されるから、やはりデバイスの左 250 ピクセル分だけにウェブページが表示され、右端は空白になる、のだろうか。

実際には、そうならない。ただでさえ狭いモバイルデバイスの画面で、右端を空白にするというのはもったいない話だ。こういう場合、すなわち width の値と initial-scale の値との積が画面の幅より小さい場合、width の指定が無視される。無視されるかどうかは、画面の幅に依存するから、ユーザーが使っているデバイスに依存する。そのため、widthinitial-scale の両方を指定した場合、デバイスによって、意図した表示になるかもしれないし、ならないかもしれない。width=1000,initial-scale=1 という指定でも、タブレットを横向きに使っていれば、width が無視されるかもしれない。

一方、initial-scale を指定しなければ、ほとんどの場合に width の指定が有効になる。「ほとんどの場合に」と書いたのは、スケールにはデフォルトで最大値と最小値が設定されており、そのため指定できる width の値にもデバイスに依存した最大値と最小値ができるからだ。最大値より大きければ最大値を指定した場合と同じになるし、最小値より小さければ最小値を指定した場合と同じになる。ただし、よほど極端な指定をしなければ、範囲を外れることはない。width=100 とか width=2000 とか指定することはないだろう。

では、width の指定が無視された場合、あるいはそもそも width を指定せず initial-scale のみを指定した場合、viewport の幅はどうなるのだろうか。

このような場合、viewport の幅は画面の幅を initial-scale の値で割った値になる。たとえば initial-scale=1 なら、viewport の幅は画面の幅と同じになる。initial-scale=0.5 なら viewport の幅は画面の幅の2倍、initial-scale=2 なら viewport の幅は画面の幅の半分になる。いずれの場合でも、viewport を initial-scale の値で拡大縮小すれば、画面の幅にぴったり合う。

したがって、width=250,initial-scale=1 という指定は initial-scale=1 という指定と同等であり、viewport の幅はデバイスの画面の幅と同じ(iPhone 7 であれば 375 ピクセル)になる。同様に、width=500,initial-scale=0.5 という指定は initial-scale=0.5 という指定と同等であり、viewport の幅はデバイスの画面の幅の2倍(iPhone 7 であれば 750 ピクセル)になる。

その4に続く

[この記事だけを読む。] [この記事にコメントを書く。] [最新の記事を読む。]

二〇一七年 皐月 四日 木曜日

改訂版・たぶん、ほとんどの人は viewport meta タグの指定をまちがえてる・その2 [/links]

その1から続く

では、viewport のデフォルト値を変えたいときはどうするのか。ここで meta タグの出番だ。HTML で <meta name="viewport" content="..."> と記述することで、viewport のさまざまな属性を設定できる。

前述のとおり、パソコン向けにデザインされたウェブページは、デフォルトで、つまり meta タグがなくても、モバイルデバイスでそれなりに表示される。しかし、コンテンツを表示する領域の幅を 800 ピクセルとか 1024 ピクセルとか特定の値にしている場合、モバイルデバイスでの表示が残念なことになる。

コンテンツ領域の幅が 1024 ピクセルに設定されているウェブページがあるとする。これを iPhone 上の Safari で表示すると、まず 980 ピクセル幅の viewport に合わせてレイアウトされるので、ページの右端 44 ピクセル分が viewport の外にはみ出てしまう。その状態で縮小されて画面に表示されるから、右端のコンテンツが画面の外にはみ出る。そのコンテンツを見るには、横にスクロールしなければならない。この場合、width=1024 として viewport の幅を 1024 ピクセルに広げてやれば、スケールは小さくなる(縮小率が大きくなる)が、横スクロールの必要がなくなる。

逆に、コンテンツ領域の幅が 800 ピクセルで固定されているウェブページでは、viewport に合わせてレイアウトされた時点で左右に合計 180 ピクセルの余白ができる。それを縮小するから、画面でもやはり余白がある。この場合、width=800 として viewport の幅を狭くすれば、余白がなくなると同時にスケールを大きくできる。

つまり、コンテンツ領域の幅が固定されているウェブページでは、以下のようにして viewport の幅を指定する。


<meta name="viewport" content="width=(コンテンツ領域の幅)">


注意点が2点ある。まず、幅の単位はピクセルだが、単位は書かない。width=1000px はまちがい。

次に、width をピクセル数で指定する場合、initial-scale は指定しない。width=1000,initial-scale=1 はまちがい。いや、まちがいではないけれど、意図した表示にはならないはずだ。

そもそも initial-scale とは何か。すでに述べたように、モバイルブラウザーは viewport 上にレイアウトしたウェブページを拡大縮小して画面に表示する。そのときのスケールの初期値、つまりスケールが設定されていないときに使用される値が initial-scale の値だ。

width をピクセル数で指定する場合、たいていはコンテンツ領域の幅を画面の幅に合わせたいと思っているだろう。viewport の幅をコンテンツ領域の幅と等しく設定していれば、必要なスケールの値は、画面の幅を viewport の幅で割ることで求められる。たとえばコンテンツ領域の幅が 1000 ピクセルで width=1000 と指定した場合、iPhone 7 なら画面の幅が 375 ピクセルだから、スケールが 0.375 のとき画面の幅に過不足なく表示される。ところが、iPhone 7 Plus なら、画面の幅が 414 ピクセルだから適切なスケールは 0.414 だ。指定するべき initial-scale の値は、デバイスごとに異なる。したがって、HTML で指定してはいけない。width だけ指定すれば、その値と画面の幅から、適切なスケールの値をブラウザーが計算してくれる。

では、width=1000,initial-scale=1 と指定したら、どう表示されるだろうか。ウェブページが幅 1000 ピクセルの viewport 上にレイアウトされて、等倍で画面に表示される。ということは、iPhone 7 であればページの左 375 ピクセルだけが見えていて、それより右のコンテンツを見るには横にスクロールしなければならない。これは意図した表示ではないだろう。

その3に続く。

[この記事だけを読む。] [この記事にコメントを書く。] [最新の記事を読む。]

二〇一七年 卯月 卅日 日曜日

改訂版・たぶん、ほとんどの人は viewport meta タグの指定をまちがえてる・その1 [/links]

もう3年近く前になるが、「たぶん、ほとんどの人は viewport meta タグの指定をまちがえてる」という記事を書いた。その内容に大きな間違いはないのだけれど、3年前と今とでは状況が変わっているし、あらためて読み返してみると我ながらわかりにくい記事だと思った。

一方、Google で「meta viewport」と検索して上位に出てくるページを見る限り、3年たってもまだ理解していない人が多いようだ。たとえば「もう逃げない。HTMLのviewportをちゃんと理解する」は、残念ながら理解が中途半端だ。そんなわけで、改訂版を書くことにした。

しかし、わかりやすく説明しようとすると、どうしても長くなる。長くなるので分割する。技術的なことはいいから結論だけ知りたいという人は、まとめだけ読んでもかまわない。

そもそもウェブページというのは、印刷物と違って、ユーザーの環境によって見た目が変わる。特に、ブラウザーのウィンドウの幅に大きく依存する。パソコンのブラウザーで、ウィンドウの幅が 1000 ピクセルなら、ウェブページの横幅が 1000 ピクセルになるようにブラウザーがレイアウトをする。

モバイルデバイスでは、たいていの場合、ブラウザーのウィンドウの幅はデバイスの画面の幅に等しい。それなら、モバイルデバイスのブラウザーは画面の幅に合わせてウェブページをレイアウトするかというと、そうではない。モバイルブラウザーは、viewport の幅に合わせてレイアウトする。では、viewport とは何か。

先ほど「ウィンドウの幅が 1000 ピクセル」と書いたが、この「ピクセル」は物理的な画素の数ではない。最近は高精細のモニターが増えたが、CSS で 1000px と指定してあるものを 1000 個の画素で表示するなら、従来のモニターでは大きく、高精細のモニターでは小さく表示されることになる。それでは困るので、高精細のモニターでは、1000px の長さを、たとえば 2000 個の画素を使って表示する。その場合、1px が 2 画素にあたることになる。

CSS で指定する「ピクセル」(px)は、センチメートルやインチと同じような長さの単位だと考えるとよい。このような「ピクセル」を「CSS ピクセル」と言ったりする。で、ウェブデザインの文脈では、モバイルデバイスの幅も CSS ピクセルで測らなければならない。

最近のモバイルデバイスは画素数が非常に大きくなっているが、CSS ピクセルで測った幅はそれほど大きくない。たとえば iPhone 7 で 375 ピクセル、iPhone 7 Plus だと 414 ピクセルだ。パソコン向けにデザインされたウェブページを幅 375 ピクセルでレイアウトするなら、見づらくなるに決まっている。そこで viewport が登場する。

viewport というのは、ユーザーには見えない仮想的なウィンドウであって、その横幅は、デフォルトではパソコンのブラウザーの一般的なウィンドウの幅と同じ程度(iPhone 版 Safari では 980 ピクセル)に設定されている。そのため、パソコン向けにデザインされたウェブページを viewport に合わせてレイアウトすると、十分適切なレイアウトになる。

この段階では、ウェブページは viewport の上にレイアウトされている。しかし、viewport はユーザーには見えないから、レイアウトしたウェブページを画面に表示しなければならない。そのとき、ブラウザーは、viewport 上のウェブページを拡大したり縮小したりして画面に表示する。その拡大縮小の比率を、この記事では「スケール」と呼ぶことにする。

スケールのデフォルト値は、viewport 上でレイアウトされたウェブページを縮小して画面の幅にぴったり収めるような値だ。iPhone 7 なら、幅 980 ピクセルのウェブページを縮小して幅 375 ピクセルの画面で表示することになるから、デフォルトのスケールは約 0.38 だ。その結果、全体的なレイアウトはパソコンのブラウザーで見た場合と同等になるが、文字や画像は、パソコンで見る場合と比べておよそ3分の1の大きさで表示される。

これでは文字が読めないと思ったユーザーは、ピンチアウトしたり要素をダブルタップしたりして表示を拡大できる。このとき、レイアウトは変わらない。なぜなら、viewport の幅が変わらないからだ。画面の表示を拡大しようと縮小しようと、viewport 上のウェブページは変わらない。ユーザーが操作しているのは、スケールの値だ。ユーザーが表示を拡大したとき、スケールが大きくなっている。viewport 上のウェブページの大きさが変わらなくても、スケールが大きくなると、画面上では大きく表示される。

その2に続く

[この記事だけを読む。] [この記事にコメントを書く。] [最新の記事を読む。]

二〇一七年 弥生 卅一日 金曜日

Flexbox でウィンドウに中央配置する2つの方法の比較 [/links]

ここ2年ほど、ブログを細々と更新するだけで、私のウェブサイトをほったらかしにしていたら、新しい仕様がどんどん使えるようになっていて、すっかり浦島太郎になってしまった。自分のウェブサイトをいつまでも古いまま置いておくわけにもゆかないので、勉強を始めた。

新しい仕様の中でも使い勝手がよいものに、CSS の Flexible box(Flexbox)がある。要素を横に並べて高さを揃えたり上下左右の位置を揃えたりが簡単にできる。

Flexbox は、コンテンツ全体をブラウザウィンドウの中央に表示するのにも使える。従来はいろいろ面倒なことをしなければならなかったが、Flexbox を使うと簡単にできる。

次のような HTML があるとする。


<body>

<div id="container">

... コンテンツ

</div>

</body>


ここで、コンテンツをウィンドウの中央に表示するには、まず body 要素の高さをウィンドウいっぱいにする(幅は自動的にウィンドウの幅になる)。そのためには、html 要素と body 要素の両方に height:100%; と指定する。次に、body 要素を Flexbox の親要素にする。


html {

height: 100%;

}

body {

height: 100%;

display: flex;

}


この後は2つの方法がある。1つは、body 要素に justify-content:center;align-items:center; を指定する。つまり、こうなる。


html {

height: 100%;

}

body {

height: 100%;

display: flex;

justify-content: center;

align-items: center;

}


Flexbox を解説しているウェブページを見ると、この方法を紹介しているところが多い。たいていの場合はこれでうまくいくのだけれど、実はうまくない場合がある。子要素(この場合 #container)の幅または高さが親要素よりも大きい場合だ。

上記の指定では、親要素と子要素の中心がそろえられる。子要素の方が大きいと、収まらない部分は上下または左右に均等にはみ出る。下や右にはみ出た部分はスクロールすれば見えるが、上や左にはみ出た部分はどうしても表示されない。これでは困る。MDN のページに詳しい説明がある。

もう1つの方法は、子要素に margin:auto; を指定する。つまり、こうする。


html {

height: 100%;

}

body {

height: 100%;

display: flex;

}

#container {

margin: auto;

}


子要素の幅または高さが親要素より大きい場合は、左右または上下のマージンの値は 0 になる。一方、子要素の幅または高さが親要素より小さければ、左右または上下のマージンが等しくなり、中央に配置される。これなら、子要素が小さくても大きくても問題なく表示される。

ところが、例によって IE にバグがある。子要素の高さを明示的に指定しない場合、上下のマージンが常に 0 になり、上下方向に中央配置されない。子要素で height を指定してやればよい話だが、要素の幅や高さを指定しなくてもよいのが Flexbox の肝だ。

というわけで、どちらの方法にも問題がある。しかし、第1の方法の問題はユーザーがコンテンツを見れないことであるのに対し、第2の方法の問題は、いまや少数派となった IE で見た目がよろしくないということだから、前者の方が深刻だ。私は、自分のウェブサイトで IE をサポートする気がさらさらないので、第2の方法を使おうと思う。

[この記事だけを読む。] [この記事にコメントを書く。] [最新の記事を読む。]

[もっと古い 5 件の記事を読む] [もっと新しい 5 件の記事を読む]

RSS feed

カテゴリ

[/language] (98)
[/links] (254)
[/mac] (114)
[/music] (36)
[/origami] (406)
[/this_blog/ajax] (7)
[/this_blog/blosxom] (4)
[/this_blog/history] (12)
[/this_blog/perl] (9)

最新記事

パスワードについてのあなたの常識はもはや非常識かもしれない・その1 [/links]
ニューラルネットワークとディープラーニングで翻訳はどうなる・その5 [/language]
ニューラルネットワークとディープラーニングで翻訳はどうなる・その4 [/language]
HTTPS 対応 [/links]
ひらがな・カタカナ学習ウェブアプリ [/links]
日本語の「た」と英語の過去形 [/language]
ORI-REVO で回転楕円体を折る・その2 [/origami]
ORI-REVO で回転楕円体を折る・その1 [/origami]
折り紙建築 [/origami]
折鶴に松図小柄 [/origami]
改訂版・たぶん、ほとんどの人は viewport meta タグの指定をまちがえてる・その6 [/links]
改訂版・たぶん、ほとんどの人は viewport meta タグの指定をまちがえてる・その5 [/links]
改訂版・たぶん、ほとんどの人は viewport meta タグの指定をまちがえてる・その4 [/links]
改訂版・たぶん、ほとんどの人は viewport meta タグの指定をまちがえてる・その3 [/links]
改訂版・たぶん、ほとんどの人は viewport meta タグの指定をまちがえてる・その2 [/links]

羽鳥 公士郎