建物の応答、水平方向の写真グリッド


私が私の写真撮影のためにウェブページを構築するためにセットするとき、グリッドで写真をレイアウトすることは最大の挑戦でした.これは、グリッド内の別のアスペクト比の写真を表示することは簡単ではない、いくつかのトレードオフが行われる必要がありますがあります.このポストでは、このようなレイアウトを実装する方法について説明します.結果を見るために、私のチェックアウトphotography page .

問題記述


我々は、行ごとに複数の写真をフィードに似たようなもので複数の写真を表示したい.我々はまた、このグリッドは敏感であることを望んでいる、それは広いデバイスでは、複数の写真を示していることを意味し、一方、携帯電話で1つまたは最大1行あたり2つの写真を示しています.写真はそれらの間にいくつかのスペースを持つ必要があります.
レイアウトについては、我々は、写真は、行ごとに写真の可変数を意味する千鳥格子と呼ばれる何かに表示されるようにしたい.私はどのようにこのレイアウトは、レンガの壁のパターンを作成し、風景や肖像画の両方の風景や肖像画を維持し、まっすぐな行と右側のフォーカスを維持します.しかし、このレイアウト応答、高速かつJavaScriptを実行時にいくつかのトリックが必要です.

水平千鳥格子

実施詳細


このレイアウトは、APPflickr and 500px . フリッカーは、自分のウェブサイト上の写真グリッドを作成するためのアルゴリズムをオープンソースとそれについてのブログ記事を書いたhere . 私は自分のアルゴリズムを自分のアルゴリズムに基づいていますが、それがどのように機能するかについては詳細には触れません.彼らの観察は、任意のアスペクト比と任意の順序で写真のコレクションを収容しながら、一貫した行の高さで写真グリッドを構築することはできませんでした.しかし、レイアウトのための一貫した行の高さが良いに見える必要はありませんし、最後の行に現在の写真を追加したり、新しい1つを作成するかどうかを決定するかどうかを決定する1つの写真を配置する良い良い解決策につながる.
単にこのアルゴリズムを使用して、また、応答であるレイアウトを持つことは、あらゆるウインドウサイズ変更でそれを実行する必要があります.また、クライアント側のレンダリングの典型的な問題があります-最初のページをレンダリングした後の写真を表示し、初期の、空の状態をサポートする必要があります.私は、私のページが速くて、サーバー側がレンダリングされて欲しかったです.

プレレンダリングレイアウト


最初の負荷問題を回避するには、ビルド時にFlickrアルゴリズムを実行することができます.さらに、レイアウトを応答させるために、私はFlickrアルゴリズムのために複数の構成を作成することができます.これらの構成は、レイアウト幅と希望の高さを指定し、幅と高さの私のコレクション内の各写真の絶対値を持つボックスの配列を生成します.写真を変更可能にするには、それぞれの箱の幅をコンテナ幅に分けることができます.それから、それぞれの写真をflexbox コンテナとflex: 0 0 ${box.widthPercent} CSSプロパティ.使用するgatsby 私のページをビルドするにはstyled-components JavaScriptを補間するbox.widthPercent CSSメディアクエリには、このロジックのすべてを構築した時間で実行している.上で説明した単純なコードです.
// import the Flickr algorithm
import layout from "justified-layout";

const breakPoints = [
  // media query is null for the default style
  { mediaQuery: null, containerWidth: 400 },
  { mediaQuery: 568, containerWidth: 600 },
  // add more if needed
];

const PhotoGrid = ({ photos }) => {
  const ratios = photos.map((photo) => photo.aspectRatio);
  const layouts = breakPoints.map((breakPoint) => ({
    breakPoint,
    layout: layout(ratios, {
      boxSpacing: 0,
      containerPadding: 0,
      containerWidth: breakPoint.containerWidth,
    }),
  }));

  const getRatiosAndBreakpointsForPhoto = (photoIndex) => {
    // returns an array containing the media query and the width percentage the photo should take on that media query
    // example: [{ mediaQuery: null, ratio: 0.3 }, { mediaQuery: null, ratio: 0.8 }]
    return layouts.map((layout) => ({
      mediaQuery: layout.breakPoint.mediaQuery,
      ratio:
        (layout.boxes[photoIndex].width / layout.breakPoint.containerWidth) *
        100,
    }));
  };

  return (
    <div style={{ display: "flex", flexWrap: "wrap" }}>
      {photos.map((photo, index) => {
        <PhotoBox responsiveRatios={getRatiosAndBreakpointsForPhoto(index)}>
          <ImageComponent photo={photo} />
        </PhotoBox>;
      })}
    </div>
  );
};

const flexCssValue = (photoBreakPoint) =>
  photoBreakPoint.mediaQuery === null
    ? `flex: 0 0 ${photoBreakPoint.ratio}%;`
    : `@media (min-width: ${photoBreakPoint.breakpoint}px) {
        flex: 0 0 ${photoBreakPoint.ratio}%;
      }`;

const PhotoBox = styled`
  ${(props) => {
    return props.responsiveRatios.map((r) => flexCssValue(r)).join("\n");
  }}
`;
メディア問合せが最初にモバイルで書かれていることに注意してください@media 注釈付きの値は、モバイルデバイス上でレンダリングする必要があります1つです.デフォルトの設定をbreakPoints arrayに設定します.面白い観察として.styled-components ビルド時にJavaScriptの値を結果のスタイルシートに注入することができます.これはgatsby-plugin-styled-components プラグイン.確認してくださいofficial guide Gatsbyのスタイルコンポーネントを取得します.The ImageComponent が実装されていません-それは<img style={{width: '100%}} /> タグ.
このようにして、ビューポートの変更に反応するのではなく、実際の画像サイズをブラウザのCSSエンジンに計算するようにしました.メディアクエリは、ビューポートのサイズに基づいてレイアウトを切り替えることができます.

写真のギャップ


写真間のギャップを追加するには、上記のアプローチとの新しいトレードオフが必要になります.Flickrの正当化されたレイアウトアルゴリズムはboxSpacing and containerPadding プロパティと実際には、アルゴリズムを実行するときに素晴らしい動作しますcontainerWidth . しかしながら、上記の方法は、参照コンテナ幅の一握りを選んで、これらの参照に基づく百分率として幅の間でINを表示する.間隔を固定し、実際のコンテナの幅をアクティブな基準幅より大きくする場合は、任意のgigipの行の写真は別の要因によって成長されますので、スペーシングが固定されたままです.また、写真が異なるアスペクト比を持っている場合は、高さが同期し、小さなミスアラインメントが表示されますが表示されます.それが全く退屈であるので、私は数学を含みません.
この問題を解決するために,わずかな作物を導入した.我々は、パディングがないかのようにレイアウトを計算し、PhotoBox ES行を空白で埋めます.それから、CSSで、我々は彼らを作りますbox-sizing: border-box パディングを追加します.の間隔10px , 私たちはそれぞれの箱にパッドを入れる5px . それから、変な方法でイメージを広げて、また、一貫してギャップを保つために、我々はobject-fit: cover 画像のCSSプロパティ.あなたはそれについてもっと読むことができますhere , しかし、長い話短い、それはコンテナのクリップを埋めるために画像のサイズをコンテナの範囲外です.このアプローチは粒状の十分なメディアのクエリとペアは、レイアウトが写真から作物のあまりに多くを必要とするたびに、写真が追加されるか、またはそれらが良い探し続けるために、各行から削除されることを保証します.

結論


これは、プリレンダリングされた、垂直の千鳥格子のグリッドを表示するための私のアプローチだった.私はそのトレードオフと技術的な複雑さに満足しています.これは、純粋なCSSとのトリミングでこれを達成する方法がありますし、私はこのような実装にガイドを読んできたhere . 私はおそらくいくつかの後の時点でこれに深く潜入するでしょうが、一方、私はさらに私の写真のウェブページを開発に焦点を当てています.私は、私が見つけるかもしれない他のおもしろい挑戦をここで文書化します.