このブログの技術構成について④制作実績のレイアウト

komosyu
Next.js

目次

  1. はじめに
  2. やりたかったこと
  3. 実装の手順
    1. js でやること
    2. css でやること
  4. 参考
  5. さいごに

はじめに

前回に続いて、このブログの制作実績ページについての解説になりますが、今回はレイアウトについてのお話をします。

簡単にいうと、grid レイアウトで一工夫しておしゃれなレイアウトにする方法です。

やりたかったこと

全体的なデザインはアプリライクな感じにしたくて、割とシンプルなんですけど制作実績ページだけちょっと遊び心が出て一工夫してみました。

やりたかったことは、このサイトの works ページのように、同じサイズの card が並ぶデザインの中で数字+n 番目の倍数のものだけ、レイアウトを変更するというもの。

参考にしたサイトのデザインが格好良くて、~~ほとんどパクらせて~~非常に参考にさせていただきました。

実装の手順

このデザインを再現するのは、css で nth-child(n)~みたいな処理が必要なのはもちろんですが、Next.js の Image に設定する width と height を指定する必要があります。

js でやること

このデザインは pc デザインのみで sp 時にはすべて同じサイズにしておきたいので、useState を使用してレスポンシブのフラグを用意しておきます。   そして、useEffect の中で useState で設定した setResponsive の引数にブレイクポイントよりも画面サイズが大きい場合は true を返すようにしておきます。
useState の中で設定するのは window オブジェクトに直接アクセスしようとすると、エラーが出てしまうためです。
詳しくはこちらのブログがわかりやすく解説してくれていました。

const [responsive, setResponsive] = useState(false)

useEffect(() => {
  setResponsive(window.innerWidth > 768)
}, [])

そして、受け取った works の情報の中から、map で処理された index を受け取って、特定の倍数の場合に width,height をそれぞれ変更するような関数を作成します。

function widthLayout(index: number) {
  if (index % 11 === 3) {
    return '555'
  } else if (index % 11 === 9) {
    return '270'
  } else if (index % 11 === 10) {
    return '555'
  } else {
    return '270'
  }
}

function heightLayout(index: number) {
  if (index % 11 === 3) {
    return '473'
  } else if (index % 11 === 9) {
    // return '473'
    return '473'
  } else if (index % 11 === 10) {
    return '473'
  } else {
    return '200'
  }
}

それで、関数ができたらコンポーネント中の Image の中にある width,height の中で三項演算子を行なって、pc デザインの場合は関数を通して出てきた値が入り、sp デザインの場合はすべて同じ値を返すようにします。

<Image
  src={work.workData.thumbnail}
  alt={work.workData.name}
  width={responsive ? widthLayout(index) : 270}
  height={responsive ? heightLayout(index) : 200}
/>

js で行うことはこんな感じです。

css でやること

基本的には js で width,height を管理した関数で行ったことと同じようなものですが、ひとつ気をつけるところは js の場合 index 番号は 0 からスタートするけど、css の場合は 11 からスタートするので、js で指定した 3,9,10 の番号に+1 してあげて、4,10,11 を指定してあげる必要があります。

.list {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1.5rem;
}
.item {
  &:nth-child(11n + 4) {
    grid-column: 1/3;
    grid-row: span 2;
  }
  &:nth-child(11n + 10) {
    grid-row: span 1;
  }
  &:nth-child(11n + 11) {
    grid-column: 2/4;
  }
}

grid プロパティを用いると意外と簡単に実現できます。
grid-template-column で repeat(横並びの数, 横幅),gap でそれぞれの間隔を親要素の list クラスで設定します。

ここでポイントになるのは子要素の item クラスでの指定方法です。
検証ツールを開いて、gird マークをクリックすると添付画像のように数字とレイアウトが出てきます。

制作実績ページのレイアウト

この数字を頼りに grid-column,grid-row で要素の位置関係をしています。   例えば、grid-column: 1/3;の場合は横のレイアウトの一番左の 1-3 までの大きさにしてください。という指示をすることができます。
そんな感じで指定してくと、こんな感じでおもしろいレイアウトを組むことができたりします。

多分、もっと難しいこととかもできたりすると思うので、興味のある方は grid で遊んでみてください。(教えてください)

参考

デザイン: https://kodemedia.com/work
Next.js: https://dev-k.hatenablog.com/entry/how-to-access-the-window-object-in-nextjs-dev-k

さいごに

css で n 番目の指定ができるのと同じように、js でも引っ張ってきた index から関数を使って処理をすることができますので、js のフレームワークは楽しいですね。