初学者さん向けの記事です。
レスポンシブに欠かせないflexBoxを使って、画面サイズにあったコンテンツ作りを練習して行きたいと思います。
かくいう自分も最初の頃は、これから紹介するやり方でなんとなくレスポンシブを理解したところから始めました。今回はそれを紹介ししながら、一緒に手を動かしながらコーディングできれば思います。
レジュメ
1.ブロックを作る。
→まずは文字なしでブロックのみを使って、flexboxを体感的に学びます。
2.レスポンシブ対応
→各サイズの画面でも自然な形になるようにコードを追加していきます。
3.モバイルファーストなコードに書き換えます。
→分かりやすいように最初はPCファーストな書き方で書きます。ですが基本的にはモバイルファーストで書くのが主流なのでこれに書き換えます。
4.より実践的な形にする。
→世の中に出回っているサイトを見本に本物WEBページの一部っぽくしていきます。
1.ブロックを作る。
ではベースとなるhtml,cssを書いていきます。最初は分かりやすくするためブロックだけ作りましょう。
※headにこの記載がない場合は追記しましょう。
<!-- レスポンシブ対応用にmetaのviewportを記載 -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<div class="wrapper">
<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>
<div class="box">4</div>
<div class="box">5</div>
<div class="box">6</div>
</div>
@charset "UTF-8";
/* reset */
*{
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Noto Sans JP', sans-serif;
line-height: 1;
}
ul{
list-style: none;
}
a{
text-decoration: none;
}
/* main contents */
body{
background-color: rgb(230, 230, 230);
}
.wrapper{
background-color: white;
width: 960px;
margin: 0 auto;
}
/* .boxの共通CSS */
.box{
/* box本体のCSS */
width: 300px;
height: 200px;
background-color: pink;
/* 文字色、配置位置設定 */
line-height: 200px;
color: white;
font-size: 3rem;
text-align: center;
/* boxどうしの間隔を開ける */
margin: 10px;
}
ここまでは難しい事はありませんね。一応コメントを追加してるのでどうグループ分しているか見て理解しましょう。
ではブラウザを確認します。
このように縦に6つブロックが並んでいればOKです!
ではもう少し手を加えます。ブロックの色が交互になるように、「奇数番目の.boxのみ背景色を変える」をやってみます。
/* 奇数番目の.boxのみ背景色を変える */
.box:nth-child(odd){
background-color: aquamarine;
}
nth-childは疑似クラスです。兄弟要素の位置を()内で指定出来ます。
兄弟要素とは同列のアウトラインにいる要素の事を指しています。今回の場合.boxクラスが同列に6つ並んでいるので6兄弟となり、1番目なら「:nth-child(first-child)」、2番目なら「:nth-child(2)」みたいに番号や名称で指定可能です。ちなみに今回は奇数番目の兄弟にのみCSSを適用したいので(odd)を使用します。(偶数の場合は(2n)または(even))
ブラウザを確認しましょう。
見事奇数番目の.boxの色が変わりました。
続いて.boxを横並びにします。
.wrapper{
background-color: white;
width: 960px;
margin: 0 auto;
/* 子要素を横並びにする */
display: flex;
}
ブラウザを確認します。
横並びになりましたが、何やら.boxの形がおかしいです。
flexboxの特徴として横並びをして子要素の幅が親要素の幅を超えた場合は、子要素を均等にして並べる特性があります。
ではこれを回避するためにどうしたら良いでしょうか?目的を確認します。
.wrapperのwidthは960pxです。一方.boxのwidthは300pxに加えmarginが両端に10pxづつ付いています。なので1つの.boxで320pxを要します。つまり.boxが3つ並ぶと960pxになります。
なので目的としては3つ.boxが並んだら、自動的に折り返し設定をします。
ではCSSを1つ追加しましょう。
.wrapper{
background-color: white;
width: 960px;
margin: 0 auto;
/* 子要素を横並びにする */
display: flex;
/* .boxが幅の端まで来たら折り返し */
flex-wrap: wrap;
}
ブラウザを確認しましょう。
出来ましたね!一応これでベースは完成しました。
だだ画面を小さくしたりすると表示がおかしくなってしまいます。なので次の章で各画面に合わせた対応をしていきたいと思います。
2.レスポンシブ対応
さて次に各画面サイズでページがみやすくなるようにコードを追加していきます。
レスポンシブで必要な知識やワードを箇条書きにします。
・デベロッパーツール
→開発者専用のWEBページ検証ツールです。Chromeブラウザ上、Ctrl+Shift+iで起動します。画面をスライドする事でいろんなサイズの画面を検証する事が出来ます。(以下参照)
・ブレイクポイント
→画面の表示が切り替わるポイント(画面サイズ)のこと。
よく使われるブレイクポイントは480,576,768,960,992,1024,1200,1400pxです。
例えば480pxをブレイクポイントと置いた場合以下のような書き方になります。
この場合480pxをブレイクポイントとして、480px以上なら.testのcolorを赤、480px未満なら.testのcolorを青、にしています。
さてこの2点を理解したところで、実際にコードを追加していきましょう。
今回は992px,768pxをブレイクポイントとします。
現状.boxが3つ並んだ時は綺麗に画面が表示されています。
2つの場合はどうでしょうか?デベロッパーモード(Chromeブラウザ上、Ctrl+Shift+i)で確認します。
.boxが左に寄ってしまってます。更にいうと.warapperで指定したbackground-color: white;が右に長く伸びています。
ではどう書いたら良いでしょうか?
今回の目的を確認します。
・.boxを中央に寄せたい。
・白い背景が.box2つ分がちょうど収まるくらいのサイズにしたい。
ですね。そしてもう1つブレイクポイントはどうしたら良いでしょうか?
何度も言いますが現状3つまでは綺麗に表示されています。960pxまでは問題ないということになります。
なので普通に考えたら960pxをブレイクポイントと考えるはずです。
ですが通常の場合少し余裕を持たせるのが良いでしょう。970~1000pxくらいが良いと思います。
今回はせっかくなので、よく使う992pxを使いましょう。
ではコードを書いていきます。
/* 992px以下は.wrapperの幅を変えます */
@media screen and (max-width: 991.9px){
.wrapper{
/* .boxがちょうど2つ収まるように幅を計算 */
width: 640px;
}
}
ブラウザを確認します。
あら不思議!白い背景に良い感じに.boxが収まり、中央寄せにもできました。
続けて1つの場合もやっていきます。やりかたはさっきまでと同じです。
まずは画面を確認します。
さっきと同様左寄せになってしまってます。
なので今度は小さいブレイクポイントに対して.wrapperのwidthを320pxを指定します。
ブレイクポイントはちょっと広めですが768pxにしましょう。
/* 768px以下は.wrapperの幅を変えます */
@media screen and (max-width: 767.9px){
.wrapper{
width: 320px;
}
}
ブラウザを確認します。
まぁ多少不恰好な感じもしますが、今回はこれで良しとしましょう。
これでレスポンシブ完了です。
デベロッパーツールで動作を確認しましょう。
こんな感じに動けばOKですね!
次の章ではモバイルファーストなコードに変えていきます。
3.モバイルファーストなコードに書き換えます。
分かりやすいように最初はPCファーストな書き方で書きました。ですが基本的にはモバイルファーストで書くのが主流なのでこれに書き換えます。
初めに現状のCSSのコードを全て、掲載します。
@charset "UTF-8";
/* reset */
*{
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Noto Sans JP', sans-serif;
line-height: 1;
}
ul{
list-style: none;
}
a{
text-decoration: none;
}
/* main contents */
body{
background-color: rgb(230, 230, 230);
}
.wrapper{
background-color: white;
width: 960px;
margin: 0 auto;
/* 子要素を横並びにする */
display: flex;
/* .boxが幅の端まで来たら折り返し */
flex-wrap: wrap;
}
/* 992px以下は.wrapperの幅を変えます */
@media screen and (max-width: 991.9px){
.wrapper{
/* .boxがちょうど2つ収まるように幅を計算 */
width: 640px;
}
}
/* 768px以下は.wrapperの幅を変えます */
@media screen and (max-width: 767.9px){
.wrapper{
width: 320px;
}
}
/* .boxの共通CSS */
.box{
/* box本体のCSS */
width: 300px;
height: 200px;
background-color: pink;
/* 文字色、配置位置設定 */
line-height: 200px;
color: white;
font-size: 3rem;
text-align: center;
/* boxどうしの間隔を開ける */
margin: 10px;
}
/* 奇数番目の.boxのみ背景色を変える */
.box:nth-child(odd){
background-color: aquamarine;
}
どこがPCファーストかというと、今回の場合.wrapperのwidthをレスポンシブ対応用に変えました。
コードは頭から呼ばれて行くので今回の場合width:960px;→width:640px;→width:320px;という順番になってしまってます。これがPCファーストということになっています。
なんだそんなことか、と思うかもしれませんがスマホによるアクセスの増加を考えると馬鹿にできないことになります。
なのでモバイルファーストなコードに書き換えます。
といっても今回は変更箇所が少ないので解説はしません。変更後のコードを載せますので是非違いを見比べて見て下さい。以降は変更後のコードを使います。
※動作上には変わりありません。
@charset "UTF-8";
/* reset */
*{
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Noto Sans JP', sans-serif;
line-height: 1;
}
ul{
list-style: none;
}
a{
text-decoration: none;
}
/* main contents */
body{
background-color: rgb(230, 230, 230);
}
.wrapper{
background-color: white;
margin: 0 auto;
/* 子要素を横並びにする */
display: flex;
/* .boxが幅の端まで来たら折り返し */
flex-wrap: wrap;
/* モバイルファーストの場合 */
width: 320px;
}
/* モバイルファーストにすると */
@media screen and (min-width: 768px) and (max-width: 991.9px){
/* 768~991.9pxまで */
.wrapper{
width: 640px;
}
}
@media screen and (min-width: 992px){
/* 992以上 */
.wrapper{
width: 960px;
}
}
/* .boxの共通CSS */
.box{
/* box本体のCSS */
width: 300px;
height: 200px;
background-color: pink;
/* 文字色、配置位置設定 */
line-height: 200px;
color: white;
font-size: 3rem;
text-align: center;
/* boxどうしの間隔を開ける */
margin: 10px;
}
/* 奇数番目の.boxのみ背景色を変える */
.box:nth-child(odd){
background-color: aquamarine;
}
4.より実践的な形にする。
ある程度flexboxとレスポンシブ対応の事がわかってきたところで、仕上げにもう少しWEBページっぽくしていきたいと思います。
【完成イメージ】
今まで作った物の基本的なベースは崩さず作りました。
では早速改修作業に入ります。まずはhtmlから変えていきましょう。
現在ある.boxのテキストは消してしまいましょう。
そして画像、タイトル、テキストの順にタグを追加していきます。
そして文書構造をはっきりさせるためdivをarticleタグに差し替えます。
※画像は各自ご用意ください。
<h1>FlexBox記事プレビューサンプル</h1>
<div class="wrapper">
<article class="box">
<img src="../assets/img/image_1.jpeg" alt="サンプルイメージ1">
<h2>記事のタイトル</h2>
<p>サンプルテキスト。この記事では●●について書かれています。是非参考にして下さい。</p>
</article>
<article class="box">
<img src="../assets/img/image_2.jpeg" alt="サンプルイメージ2">
<h2>記事のタイトル</h2>
<p>サンプルテキスト。この記事では●●について書かれています。是非参考にして下さい。</p>
</article>
<article class="box">
<img src="../assets/img/image_3.jpeg" alt="サンプルイメージ3">
<h2>記事のタイトル</h2>
<p>サンプルテキスト。この記事では●●について書かれています。是非参考にして下さい。</p>
</article>
<article class="box">
<img src="../assets/img/image_4.jpeg" alt="サンプルイメージ4">
<h2>記事のタイトル</h2>
<p>サンプルテキスト。この記事では●●について書かれています。是非参考にして下さい。</p>
</article>
<article class="box">
<img src="../assets/img/image_5.jpg" alt="サンプルイメージ5">
<h2>記事のタイトル</h2>
<p>サンプルテキスト。この記事では●●について書かれています。是非参考にして下さい。</p>
</article>
<article class="box">
<img src="../assets/img/image_6.jpg" alt="サンプルイメージ6">
<h2>記事のタイトル</h2>
<p>サンプルテキスト。この記事では●●について書かれています。是非参考にして下さい。</p>
</article>
</div>
ブラウザを確認するとトンデモナイことになってると思いますw😅
このまま一気にCSSを書いていきましょう。
まず.box内のテキスト関連のCSSは一旦消します。
/* 文字色、配置位置設定 */のコメントから下4つを消します。
そして一番、大暴れしている.box内の画像のサイズ指定をします。
.box > img{
/* サイズ指定 */
width: 100%;
}
一旦ブラウザを確認しましょう。
なんとか見れるくらいにはなりました。
ただ画像サイズがバラバラです。それぞれの画像のアスペクト比を保ったままの状態になっているからです。
なのでサイズを揃えます。
他のデザインツールでトリミングしても良いのですが、正直無駄というかCSSであれば秒でできるのでCSSでサイズ調整します。まずは高さからです。
.box > img{
/* サイズ指定 */
width: 100%;
height: 140px;
}
画面を見ると高さは揃いました。ですが猫の画像なんか分かりやすいのですが少し潰れてます。そう高さだけを指定するとアスペクト比が崩れます。なのでもうひと手間加えます。
.box > img{
/* サイズ指定 */
width: 100%;
height: 140px;
/* アスペクト比を維持 */
object-fit: cover;
}
これで画像の変形もなく高さが揃いました。
次にテキストを調整したいのですが、その前に.boxそのものの調整をしたいです。
画像やテキストが.box内いっぱいに表示されています。
また高さも200pxじゃ足りない域に来ました、なのでここを調整します。
.box{
/* box本体のCSS */
width: 300px;
/* heightを子要素全体の高さに設定 */
height: 100%;
background-color: pink;
/* boxどうしの間隔を開ける */
margin: 10px;
/* 内側余白 */
padding: 10px;
}
余白も出来て、子要素が全て.boxの中に収まりました。これでだいぶ見やすくなりました。
ではタイトルとテキストの調整をしていきます。ここまで来ればもう簡単です。
h1{
text-align: center;
margin: 2rem 0;
}
.box > h2{
font-size: 20px;
margin: 10px 0;
text-align: center;
color: darkblue;
}
/* 偶数番目の.boxの子要素h2に対してのみ */
.box:nth-child(even) > h2{
color: darkred;
}
.box > p{
font-size: 16px;
color: gray;
}
今回は:nth-child(even)を使って、偶数番目の.boxの子要素h2に対してのみテキストの色を変えています。ついでにh1も配置の調整しました。
どうでしょう?目的通り画面を作成出来ましたでしょうか?出来なかった方は最終形コードを掲載するのでしっかり見比べて間違いを見つけましょう。コメントを適当に追加してるのでそこもちゃんと見て、どのようにグループ分けしているか、どのような意味のCSSなのかしっかり理解しましょう。動いたから終わりじゃないですよ?
@charset "UTF-8";
/* reset */
*{
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Noto Sans JP', sans-serif;
line-height: 1;
}
ul{
list-style: none;
}
a{
text-decoration: none;
}
/* main contents */
body{
background-color: rgb(230, 230, 230);
}
h1{
text-align: center;
margin: 2rem 0;
}
.wrapper{
background-color: white;
margin: 0 auto;
/* 子要素を横並びにする */
display: flex;
/* .boxが幅の端まで来たら折り返し */
flex-wrap: wrap;
/* モバイルファーストの場合 */
width: 320px;
}
/* モバイルファーストにすると */
@media screen and (min-width: 768px) and (max-width: 991.9px){
/* 768~991.9pxまで */
.wrapper{
width: 640px;
}
}
@media screen and (min-width: 992px){
/* 992以上 */
.wrapper{
width: 960px;
}
}
/* .boxの共通CSS */
.box{
/* box本体のCSS */
width: 300px;
/* heightを子要素全体の高さに設定 */
height: 100%;
background-color: pink;
/* boxどうしの間隔を開ける */
margin: 10px;
/* 内側余白 */
padding: 10px;
}
/* 奇数番目の.boxのみ背景色を変える */
.box:nth-child(odd){
background-color: aquamarine;
}
.box > img{
/* サイズ指定 */
width: 100%;
height: 140px;
/* アスペクト比を維持 */
object-fit: cover;
}
.box > h2{
font-size: 20px;
margin: 10px 0;
text-align: center;
color: darkblue;
}
/* 偶数番目の.boxの子要素h2に対してのみ */
.box:nth-child(even) > h2{
color: darkred;
}
.box > p{
font-size: 16px;
color: gray;
}
長くなりましたがこれでFlexBoxとレスポンシブの練習は終了です。
以下におまけとしてもう少しデザインやアクションを追加したコードサンプルを載せておきますので余裕のある方はで是非挑戦して見て下さい。
おまけ
今回の範囲ではないので解説はしません。
もう少し装飾やアクションを追加してもっと実用的な物にしましたので、是非参考にして下さい。
【完成品】
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Template</title>
<!-- Google Font -->
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@400;700&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Lobster&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Noto+Serif+JP:wght@400;700;900&display=swap" rel="stylesheet"> <!-- CSS -->
<link rel="stylesheet" href="../assets/css/responsive_traning.css">
</head>
<body>
<h1>FlexBox記事プレビューサンプル</h1>
<div class="wrapper">
<article class="box">
<div class="imageFrame">
<img src="../assets/img/image_1.jpeg" alt="サンプルイメージ1">
<div class="layer">
<p><a href="#">Show More</a></p>
</div>
</div>
<h2>記事のタイトル</h2>
<p>サンプルテキスト。この記事では●●について書かれています。是非参考にして下さい。</p>
</article>
<article class="box">
<div class="imageFrame">
<img src="../assets/img/image_2.jpeg" alt="サンプルイメージ2">
<div class="layer">
<p><a href="#">Show More</a></p>
</div>
</div>
<h2>記事のタイトル</h2>
<p>サンプルテキスト。この記事では●●について書かれています。是非参考にして下さい。</p>
</article>
<article class="box">
<div class="imageFrame">
<img src="../assets/img/image_3.jpeg" alt="サンプルイメージ3">
<div class="layer">
<p><a href="#">Show More</a></p>
</div>
</div>
<h2>記事のタイトル</h2>
<p>サンプルテキスト。この記事では●●について書かれています。是非参考にして下さい。</p>
</article>
<article class="box">
<div class="imageFrame">
<img src="../assets/img/image_4.jpeg" alt="サンプルイメージ4">
<div class="layer">
<p><a href="#">Show More</a></p>
</div>
</div>
<h2>記事のタイトル</h2>
<p>サンプルテキスト。この記事では●●について書かれています。是非参考にして下さい。</p>
</article>
<article class="box">
<div class="imageFrame">
<img src="../assets/img/image_5.jpg" alt="サンプルイメージ5">
<div class="layer">
<p><a href="#">Show More</a></p>
</div>
</div>
<h2>記事のタイトル</h2>
<p>サンプルテキスト。この記事では●●について書かれています。是非参考にして下さい。</p>
</article>
<article class="box">
<div class="imageFrame">
<img src="../assets/img/image_6.jpg" alt="サンプルイメージ6">
<div class="layer">
<p><a href="#">Show More</a></p>
</div>
</div>
<h2>記事のタイトル</h2>
<p>サンプルテキスト。この記事では●●について書かれています。是非参考にして下さい。</p>
</article>
</div>
</body>
</html>
@charset "UTF-8";
/* reset */
*{
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Noto Sans JP', sans-serif;
line-height: 1;
}
ul{
list-style: none;
}
a{
text-decoration: none;
}
/* main contents */
body{
background-color: rgb(230, 230, 230);
}
h1{
font-family: 'Noto Serif JP', serif;
font-weight: 900;
text-align: center;
margin: 2rem 0;
}
.wrapper{
background: url(../img/bg_1.jpg) center/cover;
border: 10px solid burlywood;
padding: 50px 0;
margin: 0 auto;
/* 子要素を横並びにする */
display: flex;
/* .boxが幅の端まで来たら折り返し */
flex-wrap: wrap;
/* モバイルファーストの場合 */
width: 340px;
}
/* モバイルファーストにすると */
@media screen and (min-width: 768px) and (max-width: 991.9px){
/* 768~991.9pxまで */
.wrapper{
width: 660px;
}
}
@media screen and (min-width: 992px){
/* 992以上 */
.wrapper{
padding: 100px 0;
width: 980px;
}
}
/* .boxの共通CSS */
.box{
/* box本体のCSS */
width: 300px;
/* heightを子要素全体の高さに設定 */
height: 100%;
background-color: pink;
/* boxどうしの間隔を開ける */
margin: 10px;
/* 内側余白 */
padding: 10px;
/* アクション時間調整 */
transition: .3s;
}
/* 奇数番目の.boxのみ背景色を変える */
.box:nth-child(odd){
background-color: aquamarine;
}
/* 5の倍数番目の.boxのみ背景色を変える */
.box:nth-child(5n){
background-color: #ffff46;
}
.box:hover{
transform: scale(1.01);
box-shadow: 10px 15px 10px gray;
}
.imageFrame{
position: relative;
}
.imageFrame > img{
border: none;
vertical-align: bottom;
/* サイズ指定 */
width: 100%;
height: 140px;
/* アスペクト比を維持 */
object-fit: cover;
}
.imageFrame > .layer{
/* layer本体 */
background-color: rgba(0, 0, 0, 0.3);
width: 100%;
height: 100%;
/* positioning */
position: absolute;
top: 0;
left: 0;
}
.imageFrame > .layer p{
text-align: center;
line-height: 140px;
}
.imageFrame > .layer a{
font-family: 'Lobster', cursive;
letter-spacing: 3px;
color: white;
border: 1px solid white;
box-shadow: 0 0 10px white;
border-radius: 3px;
padding: 5px 10px;
transition: .3s;
}
.imageFrame > .layer a:hover{
background-color: orange;
color: black;
box-shadow: 0 0 10px orange;
}
.box > h2{
margin: 10px 0;
font-family: 'Noto Serif JP', serif;
font-size: 20px;
text-align: center;
color: darkblue;
font-weight: 900;
}
/* 偶数番目の.boxの子要素h2に対してのみ */
.box:nth-child(even) > h2{
color: darkred;
}
.box:nth-child(5n) > h2{
color: rgb(50, 50, 0);
}
.box > p{
font-size: 16px;
color: gray;
letter-spacing: 3px;
}
こんな感じになりました。疑似クラスでアクションを追加するためにhtmlにクラスを追加したりしてます。あとはwebFontを3種類使ってます。.boxの色もパターンを増やしました。まだまだ改良の余地はありますがこれだけでもまぁまぁ見れる感じになったかと思います。