4 年ぶりにメインサイトをリニューアルしました (レスポンシブ対応)

1. Overview

メディアクエリを利用せずにレスポンシブ対応をしました. その場合, 重要となるのが以下の 2 つです.

  • calc
  • max-width

では具体的に, どのように重要となるのか ? 各ページの対応ともに解説します.

2. Implement

2 – 1. Header, Profile, Skills, Footer

これらのページでは, テキストを中心に構成されているので, レスポンシブ対応をするためには, font-size をデバイス幅に応じて変更する必要がありました. メディアクエリを利用せずにこれを実現するには, calc を利用して, font-size を以下のように設定します. 以下の設定では, max-width: 1280px, min-width: 320px, 最小の font-size を 12px, 最大の font-size を 16px とした場合の値です.

font-size: calc(4 * ((100vw - 320px) / (1280 - 320)) + 12px);

例えば, iPhone 5 のような, 320px 幅のデバイスの場合, 100vw = 320px となるので, font-size は 12px となります. 逆に, デスクトップで, 1280px 以上あるような場合, 100vw = 1280px となるので, font-size は 16px となります. つまり, 4 というのは, 変化量で, 真ん中の () でくくられた算出式は, max-width と min-width から決定され, 最後の 12px というのは, 最小の font-size になるわけです. 一般化すると,

font-size: calc({変化量} * ((100vw - {min-width}) / ({max-width} - {min-width})) + {最小の font-size});

これを, html などに指定し, rem や em で font-size を指定すれば, メディアクエリを利用せずに, レスポンシブな font-size を実装できます.

2 – 2. Portfolio

ポートフォリオページでは, カルーセルパネルのレスポンシブ対応が必要でした. まず, カルーセルパネルのコンテナとなる要素 (サイトでは, .Portfolio__carousel) に, 必要な max-width を指定します. また, カルーセルパネルに入る個々の画像 (img タグ) には, max-width (デスクトップでの表示幅) と width: 100vw を指定します. CSS の設定はこれだけです.

次に, HTML タグ (JSX) と JavaScript の処理です. img タグの width / height 属性指定しないようにします (CSS の width: 100vw によって, 比率を保ったままレスポンシブになります). そして, アニメーションさせるためのオフセット値を, img 要素の width から算出するようにします. ただし, これには欠点があり, 初回の render 時に表示がずれてしまうことがあります.

const offset           = this.image ? this.image.width : 400;  // 初回は 400 (デスクトップと決め打ち)
const slideAmountRight = (slide * -offset) + offset;
const slideAmountLeft  = slide * offset;
const style            = {
    transform : `translateX(${slideAmountRight}px)`,
    left      : `${slideAmountLeft}px`
};

この問題の解決は, issue としておきたいと思います.

2 – 3. Music

ミュージックページでは, Grid Layout を採用していましたが, そもそもコンテンツが多すぎたので, スマートフォンのサイズになると, すべてのコンテンツが縦 (height: 100vh) におさまりきらないという問題がありました. そこで, モバイルファーストの考えに基づいて, コンテンツ (動画) を 2 つに絞りました. さいわい, YouTube は, 動画終了後に関連動画が表示されるのでそれで十分という判断でもありました. デスクトップでは, 横に並び, スマートフォンなどでは, 段落ちして縦に並ぶように実装しました. そのさいに, 動画のサイズもレスポンシブになるように, エラスティックビデオの実装もしました.

.Music__grid {
    /* デスクトップでは, 横に並び, スマートフォンなどでは, 段落ちして縦に並ぶようにするための Grid Layout の設定 */
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(288px, 1fr));
    grid-auto-rows: 1fr;
    grid-gap: 0;
}

/* 以下は, エラスティックビデオの実装に必要なスタイル */
.Music__grid > li {
    display: block;
    position: relative;
    padding-bottom: 56.25%;  /* 315 / 560 */
    height: 0;
    overflow: hidden;
}

.Music__grid > li > iframe {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
}

2 – 4. ロゴの Retina 対応 + レスポンシブ対応

一般的に, 画像をレスポンシブ対応させるには, width / height 属性を指定せず, CSS で max-width: 100% を指定すればいいのですが, ロゴのように Retina ディスプレイでもきれいに見せたい場合, それだと意図した 2 倍のサイズで表示されてしまいます. しかし, 対応は簡単で, img タグの width 属性だけをオリジナルの画像の width の 1 / 2 に設定すれば, Retina 対応ができ, かつ, max-width: 100% によってレスポンシブ対応にもなります

3. Conclusion

メディアクエリを利用しないレスポンシブ対応の目的は, CSS の実装を複雑にしないことだと思います. しかし, 目的を忘れ, メディアクエリを利用しないことに固執し, 結果, CSS が複雑になってしまっては, 本末転倒です. ディアクエリを利用することは悪ではないので, 必要と判断したならば利用すべきだと思います (今回は, 私自身のトレーニングとして, CSS が複雑になってもメディアクエリを利用せずにチャレンジするというのが目的でしたので). もっとも, 今回実装をしてみて, よほどレイアウトが変わらない限り, たいていのケースでは calc と max-width でのりきれるのではないかと思いました !

コメントを残す