Gatsby: Работает ли [gatsby-image] с фоновыми изображениями?

Созданный на 16 окт. 2017  ·  22Комментарии  ·  Источник: gatsbyjs/gatsby

Люблю Гэтсби и компонент [gatsby-image]!

Есть ли способ использовать [gatsby-image] для фоновых изображений? Я часто создаю разделы страницы с фоновым изображением ( background-size: cover ) и хотел бы воспользоваться функциями автоматического изменения размера и оптимизации [gatsby-image] для этого варианта использования.

(Если [gatsby-image] нельзя использовать для фоновых изображений, можно ли его каким-то образом использовать для имитации background-size: cover ?)

Самый полезный комментарий

Хорошо, я поэкспериментировал и нашел рабочее решение для использования gatsby-image для фоновых изображений. Я хотел поделиться этим со всеми, кто застрял в этой проблеме, поскольку функции gatsby-image слишком хороши, чтобы использовать их только для встроенных изображений!

Вот что у меня сработало:

1. Добавьте стили CSS.

Прежде чем добавлять стили, важно знать, что компонент gatsby-image выводит следующий HTML-код:

<div class="gatsby-image-outer-wrapper">
  <div class="gatsby-image-wrapper">
    <div></div>
    <!-- Placeholder (hidden after main image loads) -->
    <img style="...object-fit: cover; object-position: center center;">
    <!-- Main image -->
    <img style="...object-fit: cover; object-position: center center;">
  </div>
</div>

Стили, установленные непосредственно для gatsby-image, будут применены к <div class="gatsby-image-wrapper> . Стили, которые мы хотим применить к самому изображению, должны использовать дочерний селектор для таргетинга на теги <img> .

Чтобы gatsby-image действовал как фоновое изображение CSS, добавьте следующие стили (здесь я использовал gatsby-plugin-styled-components ):

import React from 'react'
import Image from 'gatsby-image'
import styled from 'styled-components'

const BgImage = styled(Image)`
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  z-index: -1;
  height: 100vh; // or whatever

  // Adjust image positioning (if image covers area with defined height) and add font-family for polyfill
  & > img {
    object-fit: cover !important; // or whatever
    object-position: 0% 0% !important; // or whatever
    font-family: 'object-fit: cover !important; object-position: 0% 0% !important;' // needed for IE9+ polyfill
  }
`

export default BgImage

Вот версия того же компонента BgImage который использует реквизиты для установки динамических значений:

import React from 'react'
import Image from 'gatsby-image'
import styled from 'styled-components'

const BgImage = styled(Image)`
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  z-index: -1;
  height: ${props => props.height || 'auto'};

  // Adjust image positioning (if image covers area with defined height) and add font-family for polyfill
  & > img {
    object-fit: ${props => props.fit || 'cover'} !important;
    object-position: ${props => props.position || '50% 50%'} !important;
    font-family: 'object-fit: ${props => props.fit || 'cover'} !important; object-position: ${props => props.position || '50% 50%'} !important;'
  }
`

export default BgImage

Использование !important здесь не идеально, но необходимо для переопределения встроенных стилей object-fit/object-position .

Обратите внимание, что свойства object-fit и object-position изменять не нужно, если только изображение gatsby не покрывает область с заданной высотой. Для этих случаев использования object-fit: cover; обычно все еще работает для меня, и мне просто нужно настроить значение object-position (по умолчанию gatsby-image устанавливает его в center center ).

2. Добавьте IE9 + Polyfill для соответствия объекту / положению объекта.

Приведенные выше стили будут работать во всех браузерах, кроме IE (см. Caniuse.com: object-fit / object-position ). К сожалению, в IE object-fit/object-position не работают, и любое фоновое изображение с заданной высотой будет растягиваться, чтобы заполнить свой контейнер, искажая изображение.

К счастью, в IE9 + есть полифилл, который исправляет это, и его можно найти здесь . (Спасибо @fk за указание на это.)

Вот как реализовать полифилл:

  1. Убедитесь, что вы включили дополнительное объявление font-family в свой CSS (см. Выше)
  2. Установите полифилл в свой проект: npm install —save object-fit-images
  3. Создайте файл gatsby-browser.js в корне вашего проекта
  4. Добавьте в gatsby-browser.js :
import objectFitImages from 'object-fit-images'

exports.onInitialClientRender = () => {
  objectFitImages()
}

ПРИМЕЧАНИЕ. Я активировал полифил в onInitialClientRender потому что инструкции полифила должны размещать вызов активации «перед </body> или _в DOM ready_». В другом месте я видел, как @KyleAMathews рекомендовал вместо этого реализовать полифиллы в onClientEntry , поэтому я не уверен, что это будет лучше (любой комментарий, Кайл?).

Надеюсь, это поможет!

Все 22 Комментарий

Приятно слышать, что это хорошо работает для тебя!

Что касается фоновых изображений, посетите демонстрационный сайт gatsby-image https://using-gatsby-image.gatsbyjs.org/

Это то, что вы хотите?

Спасибо за быстрый ответ!

Просто чтобы убедиться, что я понимаю, что происходит на демонстрационном сайте gatsby-image ...

  1. Вместо использования background-image , gatsby-image всегда использует <img /> а фоновые изображения моделируются с помощью position: absolute; ?
  2. Вместо использования background-size/background-position для позиционирования изображений, gatsby-image всегда использует object-fit/object-position ?

Я совершенно счастлив использовать gatsby-image таким образом для всех моих изображений, если они правильно отображаются во всех современных браузерах ... Включает ли Gatsby меры для поддержки свойств object-fit / object-position в IE 11 и Edge ( см. вопросы поддержки браузера здесь: caniuse.com )?

Если да, порекомендуете ли вы вообще избегать фоновых изображений CSS (чтобы воспользоваться преимуществами автоматической обработки изображений Gatsby)? Есть ли рекомендуемый подход для настройки свойств object-fit / object-position с использованием gatsby-image?

Если нет, существует ли рекомендуемый кроссбраузерный способ использования фоновых изображений с background-size:cover в Gatsby?

@ooloth, компонент очень новый, поэтому я отвечу на ваш вопрос ... пожалуйста, поиграйте с использованием gatsby-image, как хотите, и сообщите, что вы нашли :-)

css фоновые изображения проблематичны, потому что они не позволяют (легко) добавлять несколько размеров миниатюр для устройств разного размера. Но вы можете обойти это с помощью медиа-запросов.

Ха-ха. Понял. Так и сделаю. Спасибо за вашу помощь!

Если кто-то еще захочет поделиться своими лучшими практиками в следующих областях, мне было бы очень интересно:

  1. Как поддерживать object-fit/object-position в IE 11 и Edge (Гэтсби уже это делает?)
  2. Как настроить значения object-fit/object-position ?

Что касается 1., взгляните на https://github.com/bfred-it/object-fit-images.

@fk Спасибо за полифил! По состоянию на 16 октября Edge поддерживает object-fit/object-position , но IE11 все еще нуждается в некоторой помощи.

Не могли бы вы посоветовать что-нибудь? Я понимаю, как установить и импортировать полифилл ...
npm install --save object-fit-images
import objectFitImages from 'object-fit-images'

..но я не уверен, где сделать вызов активации:
objectFitImages()

Подскажите, пожалуйста, где разместить эту строчку? Я немного новичок в React и Gatsby.

(Кстати, я понял, как настроить значения object-fit / object-position, и поделюсь этим кодом, как только разберусь с добавлением полифилла и его корректировок CSS.)

Хорошо, я поэкспериментировал и нашел рабочее решение для использования gatsby-image для фоновых изображений. Я хотел поделиться этим со всеми, кто застрял в этой проблеме, поскольку функции gatsby-image слишком хороши, чтобы использовать их только для встроенных изображений!

Вот что у меня сработало:

1. Добавьте стили CSS.

Прежде чем добавлять стили, важно знать, что компонент gatsby-image выводит следующий HTML-код:

<div class="gatsby-image-outer-wrapper">
  <div class="gatsby-image-wrapper">
    <div></div>
    <!-- Placeholder (hidden after main image loads) -->
    <img style="...object-fit: cover; object-position: center center;">
    <!-- Main image -->
    <img style="...object-fit: cover; object-position: center center;">
  </div>
</div>

Стили, установленные непосредственно для gatsby-image, будут применены к <div class="gatsby-image-wrapper> . Стили, которые мы хотим применить к самому изображению, должны использовать дочерний селектор для таргетинга на теги <img> .

Чтобы gatsby-image действовал как фоновое изображение CSS, добавьте следующие стили (здесь я использовал gatsby-plugin-styled-components ):

import React from 'react'
import Image from 'gatsby-image'
import styled from 'styled-components'

const BgImage = styled(Image)`
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  z-index: -1;
  height: 100vh; // or whatever

  // Adjust image positioning (if image covers area with defined height) and add font-family for polyfill
  & > img {
    object-fit: cover !important; // or whatever
    object-position: 0% 0% !important; // or whatever
    font-family: 'object-fit: cover !important; object-position: 0% 0% !important;' // needed for IE9+ polyfill
  }
`

export default BgImage

Вот версия того же компонента BgImage который использует реквизиты для установки динамических значений:

import React from 'react'
import Image from 'gatsby-image'
import styled from 'styled-components'

const BgImage = styled(Image)`
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  z-index: -1;
  height: ${props => props.height || 'auto'};

  // Adjust image positioning (if image covers area with defined height) and add font-family for polyfill
  & > img {
    object-fit: ${props => props.fit || 'cover'} !important;
    object-position: ${props => props.position || '50% 50%'} !important;
    font-family: 'object-fit: ${props => props.fit || 'cover'} !important; object-position: ${props => props.position || '50% 50%'} !important;'
  }
`

export default BgImage

Использование !important здесь не идеально, но необходимо для переопределения встроенных стилей object-fit/object-position .

Обратите внимание, что свойства object-fit и object-position изменять не нужно, если только изображение gatsby не покрывает область с заданной высотой. Для этих случаев использования object-fit: cover; обычно все еще работает для меня, и мне просто нужно настроить значение object-position (по умолчанию gatsby-image устанавливает его в center center ).

2. Добавьте IE9 + Polyfill для соответствия объекту / положению объекта.

Приведенные выше стили будут работать во всех браузерах, кроме IE (см. Caniuse.com: object-fit / object-position ). К сожалению, в IE object-fit/object-position не работают, и любое фоновое изображение с заданной высотой будет растягиваться, чтобы заполнить свой контейнер, искажая изображение.

К счастью, в IE9 + есть полифилл, который исправляет это, и его можно найти здесь . (Спасибо @fk за указание на это.)

Вот как реализовать полифилл:

  1. Убедитесь, что вы включили дополнительное объявление font-family в свой CSS (см. Выше)
  2. Установите полифилл в свой проект: npm install —save object-fit-images
  3. Создайте файл gatsby-browser.js в корне вашего проекта
  4. Добавьте в gatsby-browser.js :
import objectFitImages from 'object-fit-images'

exports.onInitialClientRender = () => {
  objectFitImages()
}

ПРИМЕЧАНИЕ. Я активировал полифил в onInitialClientRender потому что инструкции полифила должны размещать вызов активации «перед </body> или _в DOM ready_». В другом месте я видел, как @KyleAMathews рекомендовал вместо этого реализовать полифиллы в onClientEntry , поэтому я не уверен, что это будет лучше (любой комментарий, Кайл?).

Надеюсь, это поможет!

Черт возьми, извини, что не вернулся раньше @ooloth! Рад, что ты это понял!
Спасибо, что вернулись и опубликовали свои выводы! 👍 ❤️

Не за что!

@stolinski сталкивается с той же проблемой в одном из своих руководств. Он поступает иначе:
https://www.youtube.com/watch?v=zhM6C0P7VO0

<Img
  sizes={dataSizes}
  style={{
    position: "absolute",
    left: 0,
    top: 0,
    width: "100%",
    height: "100%"
  }}
/>

Намного проще! Спасибо @ grod220.

@ grod220, это было легко ... Спасибо 😄

@enten Это сработает, но вы упустите преимущества в производительности от использования gatsby-image для доставки версии изображения с соответствующим изменением размера для каждого размера области просмотра с помощью srcset и sizes атрибуты.

Для меня возможность использовать gatsby-image для простой доставки оптимальной копии каждого изображения - лучшая особенность Гэтсби. Эти преимущества недоступны при использовании фоновых изображений CSS.

@ooloth Спасибо, что

@ fucata55 С удовольствием!

Фактическое изображение - это то, что вы сначала запрашиваете через graphql, а затем передаете как опору в свой gatsby-image компонент fluid или fixed prop (или, если вы используете v1, его sizes или resolutions prop).

Компонент gatsby-image затем сгенерирует все копии изображения, которые вам понадобятся, и добавит за вас сложный атрибут sizes к <img /> в итоговом HTML.

Пошаговое руководство по использованию gatsby-image (и отправке на него изображения) см. В документации gatsby-image здесь для v2 или здесь для v1 (они великолепны).

@ooloth, ваша работа очень помогла. Спасибо.

Можно ли использовать "background-attachment: fixed;"? Если да, то где именно. Я могу заставить его работать, но не с сафари. Когда он работает, изображение выглядит хорошо, пока я не добавлю на страницу дополнительные компоненты. Чем больше компонентов добавлено, тем крупнее становится изображение. Итак, я полифилю для проблемы сафари, но тогда "background-attachment: fixed;" больше не вариант, по крайней мере, так кажется. Любая помощь очень ценится.

@zachgaskin Хотел бы я помочь!

Похоже, это, вероятно, проблема с CSS (т.е. не связанная с Гэтсби или gatsby-image ), и я боюсь, что у меня нет большого опыта использования background-attachment: fixed и я не сталкивался с проблемой, которую вы ' повторное описание. Если вы можете опубликовать ссылку на минимальное воспроизведение этой проблемы, я буду рад взглянуть.

Согласно caniuse.com , iOS Safari не поддерживает background-attachment: fixed , но macOS Safari должен работать (должен ...).

Разобраться, почему определенные браузеры по-разному обрабатывают один и тот же CSS, может быть настоящей проблемой, так что я вам сочувствую. Удачи!

@zachgaskin @ooloth Я тоже с этим сталкивался. Это не идеально, но решение, которое я придумал, - добавить к изображению position: 'fixed' . Хотя это означает, что он находится на заднем плане всей страницы. Вы должны убедиться, что у вас есть фон, указанный везде. z-index: -1 позаботится о том, чтобы он был скрыт за другими вашими фонами.

<Img
  sizes={dataSizes}
  style={{
    position: "fixed",
    left: 0,
    top: 0,
    width: "100%",
    height: "100%",
    z-index: -1
  }}
/>

Фоновое изображение Gatsby - это шаг вперед ...

Возможно, вам будет полезно импортировать gatsby-image напрямую с полифилом IE и применить к нему objectFit и objectPosition в качестве свойств вместо использования! Important в ваших стилях.

import Img from 'gatsby-image/withIEPolyfill'

<Img
      fixed={heroImage.childImageSharp.fixed}
      style={{ width: '100%', height: '100%' }}
      objectFit="cover"
      objectPosition="bottom left"
   />

Спасибо, @AronBe

Я сейчас не работаю с Гэтсби, поэтому не знаю последних; однако фоновое изображение Gatsby (упомянутое выше) действительно помогло мне в моем последнем проекте.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги

Смежные вопросы

kalinchernev picture kalinchernev  ·  3Комментарии

jimfilippou picture jimfilippou  ·  3Комментарии

3CordGuy picture 3CordGuy  ·  3Комментарии

hobochild picture hobochild  ·  3Комментарии

ferMartz picture ferMartz  ·  3Комментарии