風仙洞

スマホ対応度向上
Webページ・レイアウト

作成:2023/08/23

目次

2020年版レイアウトの問題点

「HTML+CSSでブログ風レイアウト」のページでは、

  • Webページ全体を4つの部分から構成
  • grid レイアウトにより2コラム3段に配置
  • メディア・クエリーにより1コラムに組み替え

を実現した。しかし、画面サイズが8インチのタブレットで閲覧する場合は問題なかったものの、6インチ前後のスマホで閲覧すると、

  • 初期表示ではコンテンツが画面右にはみ出す
  • ピンチ・インするとmain 要素の文字が小さくなって読みにくい

という問題があった。横幅を px 単位ではなく、vw 単位にすれば良いとはわかっていたが、大きめの画像の大きさを具体的にどう調整したらよいかわからなかった。また、メニューをどう作るかという悩みもあった。しかし、2年間密かに悩んだ末に今年(2023年)春、ネット上から情報を得たり、私なりに工夫したりして解決策を見つけた。

トップ・ページ「スマホ用メニュー」、今年3月以降に新規作成した各ページの他、

がその成果である。

なお、このページでは、メディアクエリーを利用したページを試作したことがあるアマチュアWeb制作者を読者に想定している。CSS って何?、というレベルでは理解できないであろう。逆にプロのコーダーにとっては当然すぎる内容であろう。

PC 用2カラム3段レイアウト

私がこのサイトで採用している PC 用のレイアウトは下図のものである。

2カラム3段のレイアウト
  • 全体幅:850px
  • 主要部幅:600px
  • メニュー(サイドバー)部幅:250px

文章主体であるため、横幅を欲張っていない。これを実現する grid レイアウトのコードは次のものである。

● CSS
  • body {line-height: 160%;}
  • div#contents {max-width: 850px; margin: auto; display: grid; grid-template-columns: 1fr 250px; grid-template-rows: auto auto 70px; position: relative;}
  • header {grid-column: 1 / 3; grid-row: 1; background-color: #111; background-image: url('画像 URL'); min-height: 55px; margin-bottom: 5px;}
  • main {grid-column: 1; grid-row: 2; border: silver solid 1px; min-height: 500px; width: 598px;}
  • div#sidebar {grid-column: 2; grid-row: 2; background-color: lavender; min-height: 500px;}
  • footer {grid-column: 1 / 3; grid-row: 3; background-color: beige;}
  • address {margin: 10px;}
  • h1 {width: 200px; margin: 0; padding: 0;}
● HTML(body 要素前後は省略)
  • <div id="contents">
  • <header>
  • <h1>
    <img src="(画像 URL)" alt="風仙洞" width="200" height="50">
  • </h1>
  • <div id="last-update"></div>
  • <nav class="go2menu">
  • <a href="../menu.html">
  • <svg width="40" height="35" viewBox="0 0 24 24" fill="none" stroke="silver" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
    • <line x1="2" y1="7" x2="21" y2="7"></line>
    • <line x1="2" y1="14" x2="21" y2="14"></line>
    • <line x1="2" y1="21" x2="21" y2="21"></line>
  • </svg><br>
  • <span id="guide">MENU</span>
  • </a>
  • </nav>
  • </header>
  • <main>
    (省略)
  • </main>
  • <div id="sidebar">
    (省略)
  • </div>
  • <footer>
    (省略)
  • </footer>
  • </div>
  • 2カラム・レイアウトの構造に関係するタグをピンクで表示。
このページの PC 向け表示

スマホ&タブレット用メディアクエリー

次はスマホ&8インチ・タブレット用のメディアクエリーである。

● CSS
  • /* 8 inch tablet 用 Grid Layout start */
  • @media screen and (max-width: 630px) {
    • DIV#contents {display: grid; grid-template-columns: calc(100vw - 16px); grid-template-rows: repeat(4,auto); margin: auto; font-size: 100%;}
    • HEADER, FOOTER, #sidebar {width: calc(100vw - 16px);}
    • HEADER {grid-column: 1; grid-row: 1; margin: 0 auto; position: relative;}
    • MAIN {grid-column: 1; grid-row: 2; width: calc(100vw - 18px);}
    • FOOTER {grid-column: 1; grid-row: 4;}
    • DIV#sidebar {grid-column: 1; grid-row: 3;}
    }
  • /* 8 inch tablet 用 Grid Layout end */
  • /* 8 inch → SP 差分 Grid Layout start */
  • @media screen and (max-width: 520px) {
    • DIV#contents {font-size: 93%; width: calc(100vw - 16px);}
    • MAIN {line-height: 140%; width: calc(100vw - 18px);}
    • DIV#last-update {color: #ddd; font-size: 90%; margin-top: 0; width: fit-content; position: absolute; top: 5px; right: 50px; text-align: center;}
    }
  • /* 8 inch → SP 差分 Grid Layout end */
  • セレクタの要素名はわかりやすくするために大文字で記述。

ポイントは、

  • ブレイクポイントを8インチ・タブレット向けは 630px、スマホ向けは 520px に設定した。
  • 各構造要素の横幅を calc(100vw - 16px) に設定した。
    main 要素の幅が calc(100vw - 18px) であるのは、border 分を考慮したため。
  • スマホ&タブレット用は div id="contents" の幅を指定すれば、header、main 等の横幅指定を省略できるのではないかと考えたが、指定しないと横スクロールが必要になってしまったので、省略するのを止めた。
  • 8インチ・タブレット向け基本文字サイズはブラウザのデフォルトのまま。スマホ向けの基本文字サイズは、何も指定しないと大きすぎるような気がするので、93% に設定した。
    これで私のスマホ AQUOS Sense 3 の縦長画面の場合、1行が全角約20文字となるが、この辺は各自の好みであろう。
スマホ向け縦長表示
スマホ向け縦長表示

ハンバーガー・メニュー?

このページを含め、2023年型レイアウトのページの右上の三本線、いわゆるハンバーガー・メニューをクリックしてみて、「?」と思われた方もあるだろう。ハンバーガー・メニューは、JavaScript で作成するか、label/input 要素と CSS を駆使して作成し、クリックすると下に伸びるものなのに、私のサイトでは、単純にメニュー/サイトマップのページへのジャンプになっているからである。

私もそう考え、label/input 要素と CSS を利用してハンバーガー・メニューを作成してみたのだが、約60ページとページ数が中途半端に多いので、クリックすると下に伸びる型では都合が悪かった。

  • details/summary 要素を利用したカテゴリーに分類して個々のページ名を最初は隠すのでは、3回クリックしないと目的のページに行けない。
  • 個々のページ名を最初から表示するのでは、下に長く伸びすぎる。
  • PC 向け画面のサイドバーにあるメニューと役割が重複してしまう。そこでメニュー/サイトマップのページには文字だけ、サイドバーには上昇率ベスト3、人気ページのランキングの下に各ページのバナー画像を配置することにした。
  • ページを追加したときに編集箇所が増えるので面倒。メニュー/サイトマップのページにジャンプすることにすれば、各ページのハンバーガー・メニューはいじらなくて済む。

label/input 要素と CSS でハンバーガー

ちなみに上で検討した label/input 要素と CSS を利用してのハンバーガー・メニューは、header 要素の内容の nav と CSS を次のように変更すると作れる。下の例では、うまくサイドバーの幅に合わせて下に伸びるようにした。

label/input 要素と CSS を利用しての
ハンバーガー・メニュー

label/input 要素と CSS を利用するやり方は、私がサイトを2020年にリニューアルした時に HTML5/CSS Lv.3 の教材として使い、今でもいろいろ参考にしている「HTML & CSS 逆引き事典」(大藤幹 著、技術評論社 刊、ISBN 978-4-297-11251-6)で紹介されている。私自身はこんなことを思いつかない。カスタマイズするだけで精一杯である。

● HTML(nav 要素を差し替え)
  • <nav id="hmb-menu">
  • <label for="h-btns">
  • <svg width="40" height="35" viewBox="0 0 24 24" fill="none" stroke="silver" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
    • <line x1="2" y1="7" x2="21" y2="7"></line>
    • <line x1="2" y1="14" x2="21" y2="14"></line>
    • <line x1="2" y1="21" x2="21" y2="21"></line>
  • </svg>
  • <span id="guide">MENU</span>
  • </label>
  • <input type="checkbox" id="h-btns">
  • <ul class="menu-list">
    • <li><a href="index.html">home</a>
    • </li>
    • <li>
    • <details class="close-open">
    • <summary>Category 1</summary>
    • <ul class="inner-list">
    • <li><a href="contact.html">連絡先</a></li>
    • <li><a href="profile.html">自己紹介</a></li>
    • <li><a href="hobbies.html">趣味</a></li>
    • </ul>
    • </details>
    • </li>
    • <li>
    • <details class="close-open">
    • <summary>Category 2</summary>
    • <ul class="inner-list">
    • <li><a href="contact.html">テキストテキスト</a></li>
    • <li><a href="profile.html">長いテキストテキストテキストテキスト</a></li>
    • <li><a href="hobbies.html">長い長いテキストテキストテキストテキストテキストテキスト</a></li>
    • </ul>
    • </details>
    • </li>
    • <li class="attention">メニューを閉じるには下のどれか
    • <ul class="inf">
    • <li>行きたいページをクリック</li>
    • <li>三本線を再度クリック</li>
    • <li>ブラウザを更新</li>
    • </ul>
    • </li>
  • </ul>
  • </nav>
  • メニューの内容はダミー。
● CSS
  • HEADER {position: relative;}
  • NAV#hmb-menu {position: absolute; top: 0; right: 0; text-align: center; width: 250px; height: 60px; margin-right: 5px; opacity: 1; display: flex; flex-wrap: wrap; justify-content: flex-end;}
  • LABEL {display: block; cursor: pointer; position: relative; text-align: center;}
  • SPAN#guide {font-size: 80%; position: absolute; top: 32px; left: 3px; color: khaki;}
  • INPUT[type="checkbox"] {display: none; width: 50px;}
  • UL.menu-list {list-style-type: none; width: 100%; background-color: #111; margin: 10px 0 0 10px; padding: 0; height: 0; opacity: 1; z-index: 100; overflow: hidden; transition: 0.6s; line-height: 140%;}
  • INPUT#h-btns:checked + ul {height: auto;}
  • UL.menu-list LI {margin: 5px auto 10px; line-height: 120%; text-align: left; width: 220px;}
  • .menu-list > LI:first-child {text-align: center; padding: 5px; border: slateblue solid 2px; border-radius: 10px;}
  • .menu-list A {text-decoration: none; color: lavender;}
  • .menu-list LI.attention {font-size: 90%; color: lavender; padding: 5px; border-top: silver solid 1px;}
  • UL.inf LI {line-height: 100%; padding-left: 0; margin-left: -10px; margin-top: 10px;}
  • UL.page-list {display: flex; flex-wrap: wrap; justify-content: space-around; padding: 5px; margin: auto; line-height: 120%; margin-top: 0;}
  • .page-list li {list-style-type: none; width: 50px; margin: 5px 3px 3px; padding: 3px; text-align: center; border: 1px solid lavender; border-radius: 5px; background-color: #222;}
  • .page-list LI A {color: lavender;}
  • .page-list LI A:hover {color: red;}
  • DETAILS.close-open summary {color: lightsteelblue;}
  • .close-open summary:hover {color: lightpink}
  • UL.inner-list {padding: 5px 10px 2px 0; font-size: 95%; margin-left: 0;}

画像サイズの問題

スマホ対応のWebページを作成するにあたって、留意するべき点は次のようになる。

スマホを縦長にしたときの画面横幅は狭いので、画像をその横幅よりも広く表示しないようにする必要がある。例えば私のスマホ AQUOS Sense 3 は数年前の発売当時でも普及クラスであったが、ブラウザの「デベロッパーツール」でデバイスとして設定してみると 362 × 653 px となっていて、思ったよりも狭い。

デベロッパーツールでの表示
(このページ上端)

画像本来のサイズで工夫無く表示するには大きすぎる場合、いくつか方法がある。

  • CSS で width を % で指定する。親要素に対する割合で表示することになる。例: width: 80%。サイズを縦横の片方しか指定しない場合、もう片方の表示サイズはブラウザが自動計算する。
  • CSS で width を vw で指定し、画面横幅に対する割合で表示する。例: width: 90vw。ただしこの場合 PC 用画面では大きすぎるかも知れないので、メディアクエリーを利用することになるであろう。
  • 親要素に overflow: auto を指定し、スクロールすることにより初期画面で表示しきれなかった部分を見ることが出来るようにする。
  • 画像自体に object-fit プロパティを適用する。値には fill、cover、none、scale-down がある。それぞれの意味は、説明していると長くなるのでネット検索してください。
  • サムネイルとして小さな画像を表示し、ハイパーリンクなどでクリック(タップ)すると大きく表示されるようにする。