Webデザインの教科書
Web制作 中級編
Scroll

実際に作ってみよう!GridとFlexboxで作るフレキシブルサイト

今回は少し本格的なWebページを作ってみましょう。

スマホ対応も含めたレスポンシブデザインのページを作成します。

制作時間はおよそ60分ほどで作成が出来るので、ぜひやってみて下さい。

実際に制作するページ

制作時間 60分
難易度
使用した
HTMLタグ
15種類
使用した
CSSプロパティ
31種類
対応表 パソコン
スマホ

上のような旅館風のトップページを作ってみます。

画像をクリックすると、実際に作るページを確認することが出来ます。

少しだけ難しいかも知れませんが、丁寧に解説するので安心してください。

Webページの基本設定

  1. ファイル名:oshare-homepage.htmlで作成する。
    <!DOCTYPE html>
    <html lang="ja">
    <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" type="text/css" href="css/oshare.css">
    <title>OSHARE HOMEPAGE</title>
    </head>
    <body>

    </body>
    </html>
  2. ファイル名:oshare.cssで作成する。
    @charset "UTF-8";
CSSファイルの作成場所
Web練習フォルダ/
oshare-homepage.html
css/
oshare.css

今回はCSSフォルダを作成して、その中にCSSファイル「oshare.css」を作成します。

ファイルの種類ごとにフォルダーにまとめることで、管理がしやすいというメリットがあります。

今回はCSSファイルは1つだけですが、CSSファイルが増えた時にファイルの整理がしやすくなります。

これで基本的な設定は完了です。

この後はWebページの構造を作っていきましょう。

Webページの構造

<!DOCTYPE html>
<html lang="ja">
<head>
...
</head>
<body>
<header></header>
<nav></nav>
<main></main>
<aside></aside>
<footer></footer>
</body>
</html>
HTML5の新しいタグ
<header></header>
<main></main>
<aside></aside>

前回の「Web制作-基本編」では「div」タグにクラスを付加して「ヘッダー」「メイン」「フッター」を分けて作成しました。

この書き方でも構わないのですが、長くてぱっと見てもわかりにくいです。

そこで、HTML5から新しいタグが登場しました。

<div class="header"></div>
<div class="main"></div>
<div class="footer"></div>
headerタグ

画面の一番上にくる一番最初に表示される部分を構成するタグです。

綺麗な画像やイラスト、インパクトのある見出しを入れるなど、いろんな使い方が出来ます。

<header></header>
navタグ

ページのリンクや目次など、ページに関する案内をする部分を構成するタグです。

他のページに移動するリンクや、目次などのページ内リンクといったリンクをまとめるような使い方が出来ます。

<nav></nav>
mainタグ

Webページのメインになる記事の部分を構成するタグです。

画像や動画などを含めながら記事を書いていくと見やすくてわかりやすい記事になります。

<main></main>
asideタグ

メインの内容の補足説明余談、メインの記事とは関係はないが載せておきたいことなどを構成するタグです。

関連する記事を紹介したり、記事作成者のプロフィールや専門用語の補足説明など使い方は自由です。

<aside></aside>
footerタグ

ページの一番下にくる部分を構成するタグです。

コピーライトロゴなど、著作権や権利を明記するために使われます。

<footer></footer>

これでWebページの構造は完成です。

この作成した構造をベースにして、レイアウトを作っていきましょう。

レイアウトとCSS

@charset "UTF-8";
/* すべての要素に適用 */
* {
box-sizing: border-box;
}
/* ボディの設定 */
body {
position: relative;
margin: 0;
background: black;
display: grid;
grid-template-columns:
[left] 20px [main] 1fr [end] 20px [right];
grid-template-rows:
[header] auto [main] auto [aside] auto [footer] auto [bottom];
}
基本レイアウト
グリッドレイアウト

CSSグリッドを使って、基本のレイアウトを作ります。

「body」タグの中をグリッドで分割します。

グリッドの作成

「body」タグの中にグリッドを作成します。

display」の値を「grid」に指定します。

後に「header」「main」「aside」「footer」をグリッドにはめていきます。

body {
display: grid;
}
横方向の間隔を決める

グリッドの横方向の間隔を指定します。

グリット間隔を左から「20px」「1fr」「20px」の間隔で分割します。

さらに、分割した境目の線にそれぞれ「left」「main」「end」「right」と名前を付けます。

body {
grid-template-columns:
[left] 20px [main] 1fr [end] 20px [right];
}
縦方向の間隔を決める

グリッドの縦方向の間隔を指定します。

グリット間隔をすべて「auto」に要素に合わせて調節されるように分割します。

さらに、分割した境目の線に上から順に「header」「main」「aside」「footer」「bottom」と名前を付けます。

body {
grid-template-rows:
[header] auto [main] auto [aside] auto [footer] auto [bottom];
}
ポジションの設定

bodyタグの中を自由に動けるように「relative」に指定します。

あとで「nav」タグを配置するために指定しています。

body {
position: relative;
}
デザインテクニック
  • margin
  • border
  • padding
  • contents

CSSでデザインする時に便利なプロパティを紹介します。

要素の大きさを指定する時に「box-sizing」というプロパティを使用することで、レイアウトの崩れを防ぐことが出来ます。

box-sizing
  • margin
  • border
  • padding
  • contents

要素には「margin」「border」「padding」「contents」の4つの領域があるのを覚えていますか?

「width」や「height」で要素の大きさを変える時、「contents」の領域の大きさが変わります。

box-sizing」は要素の大きさを変える時に、「border」の領域を基準にすることが出来ます。

box-sizingを使わない時
  • margin
  • border
  • padding
  • contents

例えば、「width」「padding」「border」を指定した時の要素の大きさを確認してみます。

下記のように「width」の値を「100px」に指定した場合、「contents」の領域が広がります。

その時の要素全体の大きさは「122px」になります。

もし、要素全体の大きさを「100px」のつもりで指定した場合は、「22px」の誤差が出てしまいます。

.box {
width: 100px;
padding: 0 10px
border: solid 1px black;
}
box-sizingを使う時
  • margin
  • border
  • padding
  • contents

box-sizing」の値を「border-box」を設定した時の要素の大きさを確認してみます。

「width」の値を「100px」に指定した場合、「contents」「padding」「border」を含めた大きさが指定されます。

「contents」の領域は「78px」に自動調整され、要素全体の大きさは「100px」になります。

.box {
width: 100px;
padding: 0 10px
border: solid 1px black;
box-sizing: border-box;
}
すべての要素に適用する

「box-sizing」を設定するには、すべての要素に適用しないと効果は発揮しません。

すべての要素を適用するには、CSSのセレクタにアスタリスク「*」を指定します。

つまり、「div」「h1」「h2」「p」「ul」「li」などのすべての要素に「box-sizing」を適用することが可能です。

* {
box-sizing: border-box;
}
こんな時に便利
要素を最大まで広げた時にはみ出る
最大の横幅 + 44px

「width」の値を「100%」にして最大まで広げた時に効果を発揮します。

最大まで広げた時に「padding」と「border」を指定してしまうと、画面の外にはみ出てしまいます。

下記の場合、「padding 」と「border」の大きさ「44px」が画面の外にはみ出ます。

width: 100%;
padding: 0 20px;
border: solid 2px black;
要素がはみ出ないようにする
最大の横幅(100%)

「box-sizing」を設定している場合は、画面にぴったり収まるようになります。

まず先に「padding」と「border」の大きさを計算して、残りが「contents」の大きさになります。

「contents」「padding」「border」の合計の大きさが「100%」になるように計算されます。

width: 100px;
padding: 0 10px
border: solid 1px black;
box-sizing: border-box;

これで基本のレイアウトは完了です。

この後、作成したレイアウトに要素を当てはめてページを作っていきます。

まずはヘッダーを作成してましょう。

ヘッダーの作成

<!DOCTYPE html>
<html lang="ja">
<head>
...
</head>
<body>
<header>
<img src="image/oshare-bgimage.jpg" alt="トップイメージ">
<div class="top-title">
OSHARE<br>
DESIGN<br>
HOMEPAGE
</div>
</header>
<nav></nav>
<main></main>
<aside></aside>
<footer></footer>
</body>
</html>
@charset "UTF-8";
/* ここから追記 */
/* ヘッダー */
header {
position: relative;
grid-column-start: left;
grid-column-end: right;
grid-row-start: header;
grid-row-end: main;
margin-bottom: 100px;
}
header img {
display: block;
width: 100%;
max-height: 100vh;
}
.top-title {
display: flex;
justify-content: center;
align-items: center;
position: absolute;
bottom: 0;
left: 50%;
transform: translate(-50%,50px);
width: 500px;
height: 500px;
background: rgba(255,255,255,.5);
font-size: 50px;
}
/* メディアクエリ */
@media (max-width: 1024px) {
.top-title {
width: 400px;
height: 400px;
font-size: 40px;
transform: translate(-50%,40px);
}
}
@media (max-width: 840px) {
.top-title {
width: 300px;
height: 300px;
font-size: 35px;
transform: translate(-50%,30px);
}
}
@media (max-width: 580px) {
header {
margin-bottom: 60px;
}
.top-title {
width: 250px;
height: 250px;
transform: translate(-50%,25px);
}
}
@media (max-width: 450px) {
.top-title {
width: 200px;
height: 200px;
font-size: 30px;
transform: translate(-50%,20px);
}
}
@media (max-width: 370px) {
.top-title {
width: 150px;
height: 150px;
font-size: 25px;
transform: translate(-50%,15px);
}
}
ヘッダーのデザイン
グリッドの配置

グリッドレイアウトの中にヘッダーを配置します。

グリッドの名前のついた境界線をそれぞれ指定して配置します。

横方向は「left」と「right」を指定して、両端に配置します。

縦方向は「header」と「main」を指定して、一番右上のグリッドに配置します。

header {
grid-column-start: left;
grid-column-end: right;
grid-row-start: header;
grid-row-end: main;
}
ヘッダーの画像

パソコンやスマホなどの端末でも綺麗に画像が表示されるように、レスポンシブ対応します。

画像を横幅最大まで広げる

「width」の値を「100%」にして、横幅の最大まで広げます。

header img {
width: 100%;
}
imgタグを「block」要素に上書きする

「img」タグで画像を表示する時に、画像の下に謎の空白が出来ることがあります。

その謎の空白を消去するために、「block」要素に上書きして修正しています。

header img {
display: block;
}
画像の最大の高さを決める

画像の最大の高さを、画面(ブラウザ)の高さを超えないように調整します。

CSSプロパティの「max-height」とその値に「100vh」を指定をします。

header img {
max-height: 100vh;
}
新しい単位 vh
vh

vh」という単位は「viewport height」の略で画面(ブラウザ)の縦の大きさを基準にした単位です。

100vh」の時は、パソコンやスマホなどの画面の高さと同じ大きさを意味します。

50vh」の時は、画面の半分の高さが指定されます。

今回は、画像が画面下にはみ出ないように「max-height」の値を「100vh」にして、画面に収まるように調整しています。

ヘッダーのタイトル
タイトルの中央寄せ
OSHARE
DESIGN
HOMEPAGE
OSHARE
DESIGN
HOMEPAGE

タイトルの文字を要素の中央に配置します。

文字の中央寄せはフレックスボックスを使います。

.top-title {
display: flex;
justify-content: center;
align-items: center;
}
タイトルを配置する
headerエリア
OSHARE
DESIGN
HOMEPAGE
  1. タイトルの要素を配置する準備

    ヘッダーの中を自由に動けるように「relative」を指定します。

    「OSHARE DESIGN HOMEPAGE」のタイトル部分を配置するために設定しています。

    さらに、ヘッダーの下に「100px」の余白を作成します。

    header {
    position: relative;
    margin-bottom: 100px;
    }
  2. タイトルの要素を中央に配置

    CSSプロパティ「position」「left」「bottom」を使ってタイトルを配置します。

    タイトルの要素の左下が、ヘッダーの画像の中央に来るように配置します。

    .top-title {
    position: absolute;
    bottom: 0;
    left: 50%;
    }
  3. タイトルの要素に大きさに合わせて位置を調整する
    translate(X,Y)
    OSHARE
    DESIGN
    HOMEPAGE

    要素の大きさを基準に横(X軸)縦(Y軸)に移動します。

    今回は、横幅の大きさの半分(50%)を左に移動して、さらに下に「50px」移動します。

    .top-title {
    position: absolute;
    bottom: 0;
    left: 50%;
    transform: translate(-50%,50px);
    }
レスポンシブ対応

画面サイズが小さくなると、タイトルが大きすぎたり見栄えが悪くなってしまします。

メディアクエリを使って、画面サイズに合わせて微調整します。

画面サイズの横幅が1024px以下

ヘッダータイトルの要素の大きさを「400px」文字サイズを「40px」に変更して、さらに要素を「40px」下に調整します。

@media (max-width: 1024px) {
.top-title {
width: 400px;
height: 400px;
font-size: 40px;
transform: translate(-50%,40px);
}
}
画面サイズの横幅が840px以下

ヘッダータイトルの要素の大きさを「300px」文字サイズを「35px」に変更して、さらに要素を「30px」下に調整します。

@media (max-width: 840px) {
.top-title {
width: 300px;
height: 300px;
font-size: 35px;
transform: translate(-50%,30px);
}
}
画面サイズの横幅が580px以下

ヘッダーの下の余白を「60px」に変更します。

さらにヘッダータイトルの要素の大きさを「250px」に変更して、要素を「25px」下に調整します。

@media (max-width: 580px) {
header {
margin-bottom: 60px;
}
.top-title {
width: 250px;
height: 250px;
transform: translate(-50%,25px);
}
}
画面サイズの横幅が450px以下

ヘッダータイトルの要素の大きさを「200px」文字サイズを「30px」に変更して、さらに要素を「20px」下に調整します。

@media (max-width: 450px) {
.top-title {
width: 200px;
height: 200px;
font-size: 30px;
transform: translate(-50%,20px);
}
}
画面サイズの横幅が370px以下

ヘッダータイトルの要素の大きさを「150px」文字サイズを「25px」に変更して、さらに要素を「15px」下に調整します。

@media (max-width: 370px) {
.top-title {
width: 150px;
height: 150px;
font-size: 25px;
transform: translate(-50%,15px);
}
}

これでヘッダーが完成しました。

メディアクエリで細かく設定をして、レイアウトが崩れないようにします。

続いてはメニューを作成します。

メニューの作成

<!DOCTYPE html>
<html lang="ja">
<head>
...
</head>
<body>
<header>...</header>
<nav>
<ul>
<li>About</li>
<li>Room</li>
<li>Plan</li>
<li>Access</li>
<li>Gallery</li>
</ul>
</nav>
<main></main>
<aside></aside>
<footer></footer>
</body>
</html>
@charset "UTF-8";
/* ここから追記 */
/* ナビゲーション */
nav {
position: absolute;
top: 0;
left: 0;
right: 0;
}
nav ul {
display: flex;
background: rgba(255,255,255,.7);
margin: 0;
list-style: none;
padding: 0;
font-size: 1.2rem;
}
nav li {
text-align: center;
padding: 10px 0;
width: 80px;
cursor: pointer;
transition: all 1s;
}
nav li:hover {
background: white;
}
メニューのデザイン
メニューの配置

ナビゲーションを画面上部に配置します。

CSSプロパティの「position」「top」「left」「right」を使って、画面上に左右の端まで広げたナビゲーションを配置します。

nav {
position: absolute;
top: 0;
left: 0;
right: 0;
}
こんな書き方でもOK!!

left: 0」と「right: 0」を指定した時は、左右が最大まで広がります。

実は左右を広げる時に「width: 100%」でも同じように広がります。

下記のような書き方でも大丈夫です。

nav {
position: absolute;
top: 0;
left: 0;
width: 100%;
}
メニューのデザイン

フレックスボックスを使って、メニューのリストを横並びにします。

さらに、メニューの文字サイズや中央寄せなどデザインを作っていきます。

  1. リストを横並びにする

    フレックスボックスで、メニューを横並びにします。

    nav ul {
    display: flex;
    }
  2. 文字サイズを大きくする

    メニューの文字サイズを少し大きくします。

    文字サイズを「1.2rem」に指定します。

    HTMLの初期の文字サイズ「16px」の1.2倍の大きさの「19.2px」が指定されます。

    nav ul {
    font-size: 1.2rem;
    }
  3. 文字を中央寄せする

    メニューの文字を中央寄せします。

    さらに、上下に「10px」の余白を作成して整えます。

    nav li {
    text-align: center;
    padding: 10px 0;
    }
アニメーション

メニューに色を変えるアニメーションを追加して、オシャレなデザインにします。

アニメーションをすることで、クリックが出来ることを知らせる効果もあります。

アニメーション設定
Touch Me!!
Touch Me!!

メニューにマウスカーソルを乗せた時のアニメーションを設定します。

文字の色と背景の色を1秒かけてアニメーションするように設定します。

上の「Touch Me!!」は、アニメーションを追加前と追加後の違いを比較することが出来ます。

nav li {
transition: all 1s;
}
アニメーションの動作

メニューにマウスカーソルを乗せた時に、どのように変化するか設定します。

CSSで「:hover」を使って、文字の色と背景の色が変わるように設定します。

nav li:hover {
transition: all 1s;
}
マウスの形を変える
pointer

メニューにマウスカーソルを乗せた時に、マウスの形を変えます。

マウスの形を変えて、クリックが出来ることを知らせます。

ポインタ

マウスを乗せた時に、「」から「」に形を変えます。

nav li {
cursor: pointer;
}

これでメニューの作成が完成しました。

ですが、スマホやタブレットではデザインが崩れてしまいます。

今度は、作成したメニューをモバイル対応してみましょう。

モバイル版メニュー

@charset "UTF-8";
/* ここから追記 */
/* メニューの表示 */
nav.open {
display: block;
}
/* メディアクエリ */
@media (max-width:840px) {
nav {
position: fixed;
display: none;
}
nav ul {
flex-direction: column;
height: 100vh;
padding-top: 40px;
background: rgba(255,255,255,.9);
}
nav li {
width: 100%;
padding: 20px;
}
}
メニューのモバイル対応
メニューのモバイル対応

スマホやタブレットでもメニューが見やすいようにCSSでモバイル対応をします。

メディアクエリを使って上部にあったメニューのデザインを変更します。

リストを縦並びに戻す

フレックスボックスを使って横並びにしていたものを縦並びに戻します。

画面サイズが840px以下の時は、メニューを縦並びのデザインにします。

nav ul {
display: flex;
}
/* 840px以下の時 */
@media (max-width:840px) {
nav ul {
flex-direction: column;
}
}
画面いっぱいまで広げる

メニューを画面全体を覆うように広げたデザインに変更します。

メニューの高さを「100vh」にして画面の大きさと同じ高さに設定します。

nav ul {
display: flex;
}
/* 840px以下の時 */
@media (max-width:840px) {
nav ul {
flex-direction: column;
height: 100vh;
}
}
画面に付いてくるようにする

スクロールしてもナビゲーションが付いてくるようにします。

positionを「absolute」から「fixed」に上書きして、画面についてくるようにします。

nav {
position: absolute;
top: 0;
left: 0;
right: 0;
}
/* 840px以下の時 */
@media (max-width:840px) {
nav {
position: fixed;
}
}
メニューを非表示にする

モバイル版のメニューの時は、画面全体に被せるように変更しました。

なので、メニューを利用しない時は非表示にします。

/* 840px以下の時 */
@media (max-width:840px) {
nav {
display: none;
}
}
/* メニュー表示 */
nav.open {
display: block;
}
並べる向きを変える
1
2
3
4
2
3
4

フレックスボックスを使って、要素を横並び縦並びに変更する時はこのようにCSSを書きます。

要素の並ぶ方向を変更する時は、「flex-direction」プロパティを使用します。

要素の縦並び

フレックスボックスで横並びにしていたものを、縦並びに戻す時は「flex-direction」の値を「column」に指定します。

nav ul {
flex-direction: column;
}
要素の横並び

フレックスボックスで横並びにする時は、「flex-direction」の値を「row」に指定します。

ですが、フレックスボックスは初期値で「row」に設定されています。

例えば「column」で縦並びにしていたものを、横並びに戻す時に設定します。

nav ul {
flex-direction: row;
}

これでモバイル版のメニューは完了です。

モバイル版は使わない時は邪魔なので、非表示にしています。

次はメニューを表示するボタンを作成します。

メニューボタンの作成

<!DOCTYPE html>
<html lang="ja">
<head>
...
</head>
<body>
<header>...</header>
<nav>...</nav>
<!--メニューボタン-->
<div class="menubutton" onclick="menu()">
<i></i>
<i></i>
<i></i>
</div>
<main></main>
<aside></aside>
<footer></footer>
</body>
</html>
@charset "UTF-8";
/* ここから追記 */
/* メニューボタン */
.menubutton {
position: fixed;
top: 0;
left: 0;
cursor: pointer;
z-index: 100;
width: 40px;
height: 40px;
padding: 5px;
background: black;
display: none;
}
.menubutton i {
display: block;
width: 30px;
height: 5px;
background: white;
margin-bottom: 7.5px;
}
.menubutton i:last-child {
margin-bottom: 0;
}
/* メディアクエリ */
@media (max-width:840px) {
.menubutton {
display: block;
}
}
メニューボタンの作成
メニューボタンのアイコン作成
  1. 黒の正方形を作る

    「40px」の黒の正方形を作ります。

    .menubutton {
    width: 40px;
    height: 40px;
    background: black;
    }
  2. 正方形の中にスペースを作る

    正方形の内側に5pxのスペースを作ります。

    .menubutton {
    padding: 5px;
    }
  3. 3本の白い長方形を作る

    「iタグ」を使って白い3本のバーを作ります。

    横幅「30px」高さ「5px」の白い長方形を作成します。

    <i></i>
    <i></i>
    <i></i>
    .menubutton i {
    display: block;
    width: 30px;
    height: 5px;
    background: white;
    }
  4. 3本の長方形の下に間隔を作る

    作成した3本の白いバーの間隔を空けます。

    「iタグ」の下にスペースを「7.5px」の空白を作ります。

    .menubutton i {
    margin-bottom: 7.5px;
    }
「iタグ」について
  1. 本来は斜め文字に装飾するタグ

    iタグの本来の使い方は「Name Text」のように斜め文字にしたい時に使用するタグですが、今回のようにアイコン用のためにiタグを使用します。

    斜め文字はCSSでも出来るのでiタグは使われなくなりました。そのため、よくアイコン用に使われるようになりました。

  2. displayプロパティの上書き

    iタグのdisplayプロパティの初期値は「inline」という値で、大きさを変えられません。なので、大きさを変えられるように「block」に上書きします。

    デザインの都合上必要な上書きという認識で大丈夫です。

    display: block;
  3. 最後のiタグだけスペースなし

    最後(3つ目)の「iタグ」の下のスペースは必要ないので、最後の「iタグ」のみ、CSSを上書きしてスペースをなくします。

    .menubutton i:last-child {
    margin-bottom: 0;
    }
メニューボタンを配置する
メニューボタンの配置
  1. メニューボタンを画面左上に配置する

    CSSプロパティの「position」「top」「left」を使って、メニューボタンを画面左上に配置します。

    CSSの値「position: fixed」は、画面をスクロールした場合も画面に残り続け、常に表示された状態になります。

    .menubutton {
    position: fixed;
    top: 0;
    left: 0;
    }
  2. マウスポインタの設定

    マウスを載せたの時にマウスカーソルの形をポインターに変えます。

    .menubutton {
    position: fixed;
    top: 0;
    left: 0;
    cursor: pointer;
    }
  3. 要素の重なる順番の調整

    「position」で要素同士が重なるデザインの時に、要素が重なる順番を設定します。

    z-index」プロパティの値を「100」に指定して、一番上に重なるようにします。

    .menubutton {
    position: fixed;
    top: 0;
    left: 0;
    cursor: pointer;
    z-index: 100;
    }
メニューボタンの表示・非表示

画面の大きさでメニューボタンの表示・非表示を切り替えます。

画面の大きさが840px以下の時に、モバイル版のメニューに切り替わります。

メニューボタンも840px以下の時は表示して、それ以外の時は非表示にします。

.menubutton {
display: none;
}
/* 840px以下の時 */
@media (max-width:840px) {
.menubutton {
display: block;
}
}
z-indexの値
100
50
20

「z-index」の値は、数値が大きいほど画面の手前に表示されます。

反対に背景画像など奥に表示させたい時は「-1」のようにマイナス値を指定することも出来ます。

「z-index」が指定されていない要素は、初期値の「0」が基準になります。

メニューボタンの作成が完了しました。

ですが、まだメニューボタンとしての機能はありません。

これから表示の機能を追加します。

メニューボタンの機能

<!DOCTYPE html>
<html lang="ja">
<head>
...
</head>
<body>
<header>...</header>
<nav>...</nav>
<!--メニューボタン-->
<div class="menubutton" onclick="menu()">
...
</div>
<main></main>
<aside></aside>
<footer></footer>
<!--ボタンをクリック-->
<script>
function menu() {
document.querySelector('nav').classList.toggle('open');
{
</script>
</body>
</html>
メニューボタンの機能を追加する
<navclass="open">
...
</nav>
<!--メニューボタン-->
<div class="menubutton" onclick="menu()" >
...
</div>
<!--ボタンをクリック-->
<script>
function menu() {
document.querySelector('nav').classList.toggle('open');
}
</script>
@media (max-width:840px) {
nav {
display:none;
}
}
nav.open {
display:block;
}
メニュー開閉の仕組み

メニューボタンが押されると、メニューの「表示」「非表示」が切り替わるようにします。

こちらはJavaScriptを使って、HTML内に新しい目印を追加します。

その後、追加された目印に反応するように、CSSがメニューの「表示」「非表示」を切り替える仕組みを作っていきます。

「open」クラスの追加・削除

まずは、メニューの開閉の仕組みの重要な部分を、JavaScriptを使って作成します。

メニューの「表示」「非表示」を判断するための目印(クラス)を操作する機能を作っていきます。

ここからは、JavaScriptのプログラムは、HTMLの中に記述していきます。

  1. クラスを付加・削除する機能を作る

    HTMLのnavタグに、メニューの表示・非表示を判別する目印を付けたり削除する機能を作ります。

    HTMLのnavタグに、目印として「open」クラスを付加もしくは削除する機能をJavaScriptで作ります。

    function menu()
    関数の名前を「menu」に設定します。
    document.querySelector('nav')
    HTMLの中にある「nav」タグを対象に操作します。
    classList
    対象のHTMLタグにクラスの操作します。
    toggle('open')
    対象のHTMLタグに「open」クラスがない時はクラスを付加して、反対に「open」クラスがある時はクラスを消去します。
    <script>
    function menu() {
    document.querySelector('nav').classList.toggle('open');
    }
    </script>
    <script>
    関数名:menu {
    'nav'タグに'open'クラスを付加または消去する;
    }
    </script>
  2. クリックを検知する

    HTMLのタグに「onclick="menu()"」を追加します。

    先ほど作成した関数名「menu」を、クリックを検知した際に関数を呼び出すようにします。

    クリックで呼び出された関数名「menu」が実行されると、HTMLのnavタグに「open」クラスが付加・削除されるようになります。

    <div class="menubutton" onclick="menu()">
    ・・・
    </div>
  3. メニューの表示・非表示の切り替え

    ボタンがクリックされて、HTMLのnavタグに「open」クラスが付加された際に、CSSでメニューを表示するようにします。

    CSSのセレクタで、navタグに「open」クラスがある時は、CSSプロパティ「display: block」で表示するようにします。

    それ以外は、CSSプロパテ「display: none」で非表示にしておきます。

    /* 非表示 */
    nav {
    display: none;
    }
    /* 表示 */
    nav.open {
    display: block;
    }

これでメニューのモバイル対応は完了です。

ここまでが長い道のりでした...。

今度はメインの記事を作成していきます。

メイン記事の作成

<!DOCTYPE html>
<html lang="ja">
<head>
...
</head>
<body>
<header>...</header>
<main>
<h1>オシャレな旅館のホームページ</h1>
<div class="plan">
<img src="image/oshare-bar.jpg" alt="バーの写真">
<div class="comments">
<h2>木で統一された雰囲気のあるBAR</h2>
<p>
宿泊される方が集まるBAR。海外から訪れる方が多く国際交流ができる場になっています。150種類以上のお酒がお楽しみいただけます。
</p>
<div>※20歳以上の方のみご利用出来ます。</div>
</div>
</div>
<div class="plan">
<img src="image/oshare-room.jpg" alt="部屋の写真">
<div class="comments">
<h2>日本らしい古風のお部屋</h2>
<p>
昔ながらの日本の雰囲気でゆっくりくつろげる空間。お部屋ごとに露天風呂をご用意しております。いつでもご利用下さいませ。
</p>
</div>
</div>
</main>
<aside></aside>
<footer></footer> </body>
</html>
@charset "UTF-8";
/* ここから追記 */
/* メイン */
main {
grid-column-start: main;
grid-column-end: end;
grid-row-start: main;
grid-row-end: aside;
margin-bottom: 100px;
}
h1,h2 {
color: white;
text-align: center;
}
.plan {
display: flex;
width: 100%;
max-width: 800px;
margin: 2em auto;
}
.plan img {
display: block;
height: 200px;
}
.plan h2 {
font-size: 20px;
color: black;
}
.plan .comments {
width: 100%;
padding: 0 20px;
background: #cccccc;
}
@media (max-width: 700px) {
.plan {
flex-direction: column;
}
.plan img {
width: 100%;
height: auto;
}
.plan .comments {
padding: 20px;
}
}
メインのデザイン
グリッドの配置

グリッドレイアウトの中にメインを配置します。

横方向は「main」と「end」を指定して、中央に配置します。

縦方向は「main」と「aside」を指定して、上から2番目のグリッドに配置します。

main {
grid-column-start: main;
grid-column-end: end;
grid-row-start: main;
grid-row-end: aside;
}
見出しのデザイン

「h1」と「h2」の見出しのデザインをします。

「h1」と「h2」のデザインは共通なので、一緒にデザインします。

文字の色

見出しの文字の色を白に変更します。

背景が黒なので、文字の色を白にしてはっきり見えるようにします。

文字の中央寄せ

見出しがページの中央に来るように寄せます。

h1 , h2 {
color: white;
text-align: center;
}
旅館の紹介

旅館のサービスや部屋に関する項目をデザインします。

全体レイアウト

画像と詳細を横並びに配置します。

さらに、横に広がる大きさを最大800pxに制限します。

もし「800px」以下になる時は、親要素に合わせて縮んでいきます。

.plan {
display: flex;
width: 100%;
max-width: 800px;
}
画像

画像の高さを「200px」に固定します

さらに、画像を「block」要素に変更します。

画像の下に出来る謎の空白を消去するために、「block」要素に上書きして修正します。

.plan img {
display: block;
height: 200px;
}
見出し

「h2」タグの見出しのデザインを変更します。

文字サイズを「20px」変更して、さらに文字の色を黒に変更します。

.plan h2 {
font-size; 20px;
color: black;
}
レスポンシブ対応

旅館のサービスや部屋に関する項目を、レスポンシブ対応します。

メディアクエリで画面の大きさが「700px」以下の時は、要素を縦並びにします。

レイアウトの変更

旅館の紹介のレイアウトを横並びから縦並びに変更します。

@media (max-width: 700px) {
.plan {
flex-direction: column;
}
}
画像の大きさを調節

要素を縦並びにしている時は、画像の横幅を最大まで広げるように変更します。

さらに、画像の高さを「200px」から「auto」に上書きします。

高さを「auto」にすることで、画像の高さを自動で調節するようにします。

@media (max-width: 700px) {
.plan img {
width: 100%;
height: auto;
}
}
詳細部分の余白を調整

旅館の紹介のレイアウトを縦並びにすると、画像と詳細の文章との間が近くなってしまいます。

文章が読みやすくなるように、上下左右に余白を作って整えます。

@media (max-width: 700px) {
.plan .comments {
padding: 20px;
}
}

これでメインの記事は完了です。

完成まであともう少しですよ!!

次は、最新情報をお知らせするサイド記事を作成します。

サイド記事の作成

<!DOCTYPE html>
<html lang="ja">
<head>
...
</head>
<body>
<header>...</header>
<main>...</main>
<aside>
<h2>News</h2>
<div class="news">
<div class="topic">
<div class="time">2019/10/01</div>
<div>消費税の増税に伴う料金の変更のお知らせ 増税後ver</div>
</div>
<div class="topic">
<div class="time">2019/09/23</div>
<div>台風に関する営業時間の変更のお知らせ</div>
</div>
<div class="topic">
<div class="time">2019/08/10</div>
<div>消費税の増税に伴う料金のお知らせ</div>
</div>
<div class="topic">
<div class="time">2019/07/04</div>
<div>公式instagramがオープン</div>
</div>
<div class="topic">
<div class="time">2019/07/03</div>
<div>公式Twitterがオープン</div>
</div>
<div class="topic">
<div class="time">2019/06/20</div>
<div>お部屋をリニューアルしました</div>
</div>
</div>
</aside>
<footer></footer>
</body>
</html>
/* ここから追記 */
/* サイド */
aside {
grid-column-start: main;
grid-column-end: end;
grid-row-start: aside;
grid-row-end: footer;
}
.news {
max-width: 1000px;
border-top: dashed 1px #cccccc;
border-bottom: dashed 1px #cccccc;
margin: 2em auto;
padding: 1em 20px;
color: white;
}
.news .topic {
display: flex;
align-items: center;
padding: 10px;
margin: 1em 0;
border-left: solid 10px #cccccc;
}
.news .time {
margin-right: 1em;
}
@media (max-width: 450px) {
.news .topic {
flex-direction: column;
align-items: flex-start;
}
}
サイドのデザイン
グリッドの配置

グリッドレイアウトの中にお知らせ一覧の項目を配置します。

横方向は「main」と「end」を指定して、中央に配置します。

縦方向は「aside」と「footer」を指定して、上から3番目のグリッドに配置します。

aside {
grid-column-start: main;
grid-column-end: end;
grid-row-start: aside;
grid-row-end: footer;
}
最新情報の全体デザイン
2019/10/01
最新情報
2019/09/23
最新情報

最新情報をまとめる項目をデザインします。

横幅の制限

横幅の広がる大きさを最大1000pxに制限します。

もし「1000px」以下になる時は、親要素に合わせて縮んでいきます。

.news {
max-width: 1000px;
}
要素の中央寄せ

横幅を「1000px」に制限したので、画面が大きい時は要素が左に寄ってしまいます。

要素を中央寄せして、さらに上下に「2em」の余白を作ります。

「2em」はHTMLの初期値の文字サイズ「16px」の2倍大きさ「32px」になります。

.news {
margin: 2em auto;
}
上下に破線を追加

最新情報をまとめる項目の上下にグレーの破線を作成します。

上の線「border-top」と下の線「border-bottom」で、破線(dashed)を作成します。

.news {
border-top: dashed 1px #cccccc;
border-bottom: dashed 1px #cccccc;
}
情報一覧のデザイン
2019/10/01
最新情報のお知らせ

一つ一つの情報のレイアウトとデザインを設定します。

レイアウト
Time
New Info

更新日と詳細を横並びにします。

その時「align-items」の値を「center」にして、上下方向の中央寄せをします。

さらに更新日と詳細の間隔を空けるために、「time」クラスの右側に「1em」の余白を作ります。

.news .topic {
display: flex;
align-items: center;
}
.news .time {
margin-right: 1em;
}
デザイン

一つ一つの情報が見えやすいように、左側に縦の太い線を引きます。

border-left」の値を「10px」に指定して、左側に太い線を作成します。

.news .topic {
border-left: 10px;
}
レスポンシブ対応
Time
New Info

お知らせ一覧の項目を、レスポンシブ対応します。

メディアクエリで画面の大きさが「450px」以下の時は、要素を縦並びにします。

レイアウトの変更

情報一覧のレイアウトを横並びから縦並びに変更します。

@media (max-width: 450px) {
.plan .topic {
flex-direction: column;
}
}
要素の左寄せ

縦並びにした時に「align-items」の値が「center」のままだと中央寄せされます。

「align-items」の値が「flex-start」に変更して、左寄せします。

@media (max-width: 450px) {
.plan .topic {
align-items: flex-start;
}
}
縦並びにした時の注意

フレックスボックスを使って横並び縦並びを切り替える時に注意しなければいけないことがあります。

フレックスボックスの「justify-content」と「align-items」で子要素を揃えていましたが、横並び縦並びでは機能が反対になります。

横並びの時
1
2
3
justify-content
align-items

子要素を横並びにしている時は「justify-content」は左右の間隔を揃えます。

それに対して「align-items」は上下の間隔を揃えます。

.plan .topic {
display: flex;
justify-content: center;
align-items: center;
}
縦並びの時
1
2
3
align-items
justify-content

子要素を縦並びにしている時は「align-items」が左右の間隔を揃えます。

それに対して「justify-content」は上下の間隔を揃えます。

flex-direction」で縦並びの「column」を指定している時は、反対の効果になります。

.plan .topic {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}

サイド記事の作成が完了しました。

残すところはフッターのみです。

がんばっていきましょう。

フッターの作成

<!DOCTYPE html>
<html lang="ja">
<head>
...
</head>
<body>
<header>...</header>
<main>...</main>
<aside>...</aside>
<footer>
&copy; 2019 OSHARE HOMEPAGE
</footer>
</body>
</html>
/* ここから追記 */
/* フッター */
footer {
grid-column-start: left;
grid-column-end: right;
grid-row-start: footer;
grid-row-end: bottom;
text-align: center;
background: white;
padding: 10px 0;
}
フッターのデザイン
グリッドの配置

グリッドレイアウトの中にヘッダーを配置します。

横方向は「left」と「right」を指定して、両端に配置します。

縦方向は「footer」と「bottom」を指定して、一番下のグリッドに配置します。

footer {
grid-column-start: left;
grid-column-end: right;
grid-row-start: footer;
grid-row-end: bottom;
}
コピーライト

フッターの中に、コピーライトを作成します。

コピーライトとは?

コピーライトとは、一番下の「© 2019 OSHARE HOMEPAGE」の部分です。

これはこのサイトで作成された記事や画像、動画などすべてのコンテンツに著作権がありますとわかりやすく明記するためによく書かれます。

書き方
  1. コピーライトマーク
  2. 発行年

    ここには公開した年を書きます。本サイトは2019年に公開したので「2019」と書きます。

  3. 会社名・名前

    ここはなんでもいいのですが、会社でサイトを公開するのなら「会社名」、個人で公開するなら「ご自身の名前」など著作権を持つ会社・名前を書くといいと思います。

&copy; 2019 OSHARE HOMEPAGE
コピーライトは必要?

実際は、コピーライトを記述しなくても自動的に著作権は発生します。

正直あっても無くても変わりません。

昔からの習慣・風習のような理由で明記してるサイトがほとんどなので、そんな細かく考えることはしなくて大丈夫です。

参考サイト : LIG

以上でWeb制作中級編は終了です。

お疲れ様でした。

このように「grid」と「flexbox」でレイアウトを作っていきます。

さらに、メディアクエリでスマホ対応することで本格的なページの完成です。

Webページの完成

すべてのHTMLとCSSのコードが下にあります。

このように作成出来ていれば正解です。

確認程度によかったら確認してみて下さい。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" href="css/oshare.css">
<title>OSHARE HOMEPAGE</title>
</head>
<body>
<header>
<img src="image/oshare-bgimage.jpg" alt="トップイメージ">
<div class="top-title">
OSHARE<br>
DESIGN<br>
HOMEPAGE
</div>
</header>
<main>
<h1>オシャレな旅館のホームページ</h1>
<div class="plan">
<img src="image/oshare-bar.jpg" alt="バーの写真">
<div class="comments">
<h2>木で統一された雰囲気のあるBAR</h2>
<p>
宿泊される方が集まるBAR。海外から訪れる方が多く国際交流ができる場になっています。150種類以上のお酒がお楽しみいただけます。
</p>
<div>※20歳以上の方のみご利用出来ます。</div>
</div>
</div>
<div class="plan">
<img src="image/oshare-room.jpg" alt="部屋の写真">
<div class="comments">
<h2>日本らしい古風のお部屋</h2>
<p>
昔ながらの日本の雰囲気でゆっくりくつろげる空間。お部屋ごとに露天風呂をご用意しております。いつでもご利用下さいませ。
</p>
</div>
</div>
</main>
<aside>
<h2>News</h2>
<div class="news">
<div class="topic">
<div class="time">2019/10/01</div>
<div>消費税の増税に伴う料金の変更のお知らせ 増税後ver</div>
</div>
<div class="topic">
<div class="time">2019/09/23</div>
<div>台風に関する営業時間の変更のお知らせ</div>
</div>
<div class="topic">
<div class="time">2019/08/10</div>
<div>消費税の増税に伴う料金のお知らせ</div>
</div>
<div class="topic">
<div class="time">2019/07/04</div>
<div>公式instagramがオープン</div>
</div>
<div class="topic">
<div class="time">2019/07/03</div>
<div>公式Twitterがオープン</div>
</div>
<div class="topic">
<div class="time">2019/06/20</div>
<div>お部屋をリニューアルしました</div>
</div>
</div>
</aside>
</body>
</html>
@charset "UTF-8";
/* すべての要素に適用 */
* {
box-sizing: border-box;
}
/* ボディの設定 */
body {
position: relative;
margin: 0;
background: black;
display: grid;
grid-template-columns:
[left] 20px [main] 1fr [end] 20px [right];
grid-template-rows:
[header] auto [main] auto [aside] auto [footer] auto [bottom];
}
/* ヘッダー */
header {
position: relative;
grid-column-start: left;
grid-column-end: right;
grid-row-start: header;
grid-row-end: main;
margin-bottom: 100px;
}
header img {
display: block;
width: 100%;
max-height: 100vh;
}
.top-title {
display: flex;
justify-content: center;
align-items: center;
position: absolute;
bottom: 0;
left: 50%;
transform: translate(-50%,50px);
width: 500px;
height: 500px;
background: rgba(255,255,255,.5);
font-size: 50px;
}
/* メディアクエリ */
@media (max-width: 1024px) {
.top-title {
width: 400px;
height: 400px;
font-size: 40px;
transform: translate(-50%,40px);
}
}
@media (max-width: 840px) {
.top-title {
width: 300px;
height: 300px;
font-size: 35px;
transform: translate(-50%,30px);
}
}
@media (max-width: 580px) {
header {
margin-bottom: 60px;
}
.top-title {
width: 250px;
height: 250px;
transform: translate(-50%,25px);
}
}
@media (max-width: 450px) {
.top-title {
width: 200px;
height: 200px;
font-size: 30px;
transform: translate(-50%,20px);
}
}
@media (max-width: 370px) {
.top-title {
width: 150px;
height: 150px;
font-size: 25px;
transform: translate(-50%,15px);
}
}
/* ナビゲーション */
nav {
position: absolute;
top: 0;
left: 0;
right: 0;
}
nav ul {
display: flex;
background: rgba(255,255,255,.7);
margin: 0;
list-style: none;
padding: 0;
font-size: 1.2rem;
}
nav li {
text-align: center;
padding: 10px 0;
width: 80px;
cursor: pointer;
transition: all 1s;
}
nav li:hover {
background: white;
}
/* ナビゲーションモバイル版 */
nav.open {
display: block;
}
/* メディアクエリ */
@media (max-width:840px) {
nav {
position: fixed;
display: none;
}
nav ul {
flex-direction: column;
height: 100vh;
padding-top: 40px;
background: rgba(255,255,255,.9);
}
nav li {
width: 100%;
padding: 20px;
}
}
/* メニューボタン */
.menubutton {
position: fixed;
top: 0;
left: 0;
cursor: pointer;
z-index: 100;
width: 40px;
height: 40px;
padding: 5px;
background: black;
display: none;
}
.menubutton i {
display: block;
width: 30px;
height: 5px;
background: white;
margin-bottom: 7.5px;
}
.menubutton i:last-child {
margin-bottom: 0;
}
/* メディアクエリ */
@media (max-width:840px) {
.menubutton {
display: block;
}
}
/* メイン */
main {
grid-column-start: main;
grid-column-end: end;
grid-row-start: main;
grid-row-end: aside;
margin-bottom: 100px;
}
h1,h2 {
color: white;
text-align: center;
}
.plan {
display: flex;
width: 100%;
max-width: 800px;
margin: 2em auto;
}
.plan img {
display: block;
height: 200px;
}
.plan h2 {
font-size: 20px;
color: black;
}
.plan .comments {
width: 100%;
padding: 0 20px;
background: #cccccc;
}
@media (max-width: 700px) {
.plan {
flex-direction: column;
}
.plan img {
width: 100%;
height: auto;
}
.plan .comments {
padding: 20px;
}
}
/* サイド */
aside {
grid-column-start: main;
grid-column-end: end;
grid-row-start: aside;
grid-row-end: footer;
}
.news {
max-width: 1000px;
border-top: dashed 1px #cccccc;
border-bottom: dashed 1px #cccccc;
margin: 2em auto;
padding: 1em 20px;
color: white;
}
.news .topic {
display: flex;
align-items: center;
padding: 10px;
margin: 1em 0;
border-left: solid 10px #cccccc;
}
.news .time {
margin-right: 1em;
}
@media (max-width: 450px) {
.news .topic {
flex-direction: column;
align-items: flex-start;
}
}
/* フッター */
footer {
grid-column-start: left;
grid-column-end: right;
grid-row-start: footer;
grid-row-end: bottom;
text-align: center;
background: white;
padding: 10px 0;
}

ヒツジのサイトを使ってくれてありがとうございます。

よかったらTwitterでシェアしてくれると嬉しいです!!