Gatsby Image で画像をトリミングせずに中央寄せする

  • Gatsby

gatsby-image を使って画像を表示させると、だいたい下記のような構造になります。タグはわかりやすように名前をつけてますが実際は div とかです。

<wrapper>
  <inner>
  <noscript>
  <source>
</wrapper>

wrapper や inner は source 内の画像の比率によって動的に設定されるようです。

中央寄せする

例えば、100px のブロックの中に画像を配置し、中央に寄せる方法です。Img コンポーネントを使用し、props に値を渡してあげます。imageは適当に作った変数で、srcaltを持っているとします。

import Img from 'gatsby-image';

<Img
  className={classes.thumbImage}
  name={image.src}
  alt={image.alt}
  styles={{
    height: '100px',
    width: '100px',
    maxHeight: '100px',
    maxWidth: '100px',
  }}
  imgStyles={{
    objectPosition: 'center',
    objectFit: 'contain',
    maxHeight: '100px',
    maxWidth: '100px',
  }}
/>
  • sytles … wrapper に渡すスタイル
  • imgStyles … ソース画像に渡すスタイル

wrapper の width と height を指定します。なんだか max 値も入るのでそれを上書きもしておきます。img はobject-positionでセンタリング、object-fitcontainにすることで画像がはみ出ないようにします。

また、画像はposition: absoluteになっているのでmax-widthmax-heightを px 単位で指定します。

これで画像は縦横100pxよりも大きくなることはなく、それでいて中央に寄せることができます。が、あまりに冗長すぎるのでもっといいやり方がある気がします…

スタイルを設定した時の構造

多分こんな感じ。

<wrapper {...styles}>
  <inner>
  <noscript>
  <source>
    <img {...imgStyles}>
  </source>
</wrapper>

wrapper の親を一つ作って、そこに width と height を指定し、先ほどのスタイルは全て 100% にすればもっと楽なのでは?とも思いましたが、position: absolute で位置を設定しているため上手く設定できませんでした。

まあ、全部オーバーライドしてしまえばどうとでもなるんでしょうけど…。
その辺りは gatsby-image の props を確認してみてください。

interface GatsbyImageProps {
  resolutions?: FixedObject
  sizes?: FluidObject
  fixed?: FixedObject | FixedObject[]
  fluid?: FluidObject | FluidObject[]
  fadeIn?: boolean
  durationFadeIn?: number
  title?: string
  alt?: string
  className?: string | object
  critical?: boolean
  crossOrigin?: string | boolean
  style?: object
  imgStyle?: object
  placeholderStyle?: object
  placeholderClassName?: string
  backgroundColor?: string | boolean
  onLoad?: () => void
  onError?: (event: any) => void
  onStartLoad?: (param: { wasCached: boolean }) => void
  Tag?: string
  itemProp?: string
  loading?: `auto` | `lazy` | `eager`
  draggable?: boolean
}