Gatsby: ¿Funciona [gatsby-image] con imágenes de fondo?

Creado en 16 oct. 2017  ·  22Comentarios  ·  Fuente: gatsbyjs/gatsby

¡Amar a Gatsby y al componente [gatsby-image]!

¿Hay alguna forma de usar [gatsby-image] también para imágenes de fondo? Con frecuencia creo secciones de página con una imagen de fondo ( background-size: cover ) y me encantaría aprovechar las funciones de optimización y cambio de tamaño automático de [gatsby-image] para este caso de uso.

(Si [gatsby-image] no se puede usar para imágenes de fondo, ¿se puede usar de alguna manera para simular background-size: cover ?)

Comentario más útil

Muy bien, hice algunos experimentos y encontré una solución funcional para usar gatsby-image para imágenes de fondo. Quería compartir esto con cualquier otra persona que se quede atascada en este problema, ¡ya que las características de gatsby-image son demasiado buenas para usarlas solo para imágenes en línea!

Esto es lo que funcionó para mí:

1. Agregar estilo CSS

Antes de agregar estilos, es bueno saber que el componente gatsby-image genera el siguiente 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>

Los estilos establecidos directamente en gatsby-image se aplicarán a <div class="gatsby-image-wrapper> . Los estilos que queremos aplicar a la imagen en sí deben usar un selector secundario para apuntar a las etiquetas <img> .

Para hacer que gatsby-image actúe como una imagen de fondo CSS, agregue los siguientes estilos (he usado gatsby-plugin-styled-components aquí):

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

Aquí hay una versión del mismo componente BgImage que usa accesorios para establecer los valores dinámicos:

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

El uso de !important aquí no es ideal, pero es necesario para anular los estilos object-fit/object-position .

Tenga en cuenta que las propiedades object-fit y object-position no necesitarán ajustarse a menos que la imagen de gatsby cubra un área con una altura establecida. Para estos casos de uso, object-fit: cover; generalmente todavía me funciona y solo necesito ajustar el object-position (gatsby-image lo establece en center center de forma predeterminada).

2. Agregue IE9 + Polyfill para ajuste de objeto / posición de objeto

Los estilos anteriores funcionarán en todos los navegadores excepto IE (consulte caniuse.com: object-fit / object-position ). Desafortunadamente, en IE, object-fit/object-position no funcionan, y cualquier imagen de fondo con una altura establecida se estirará para llenar su contenedor, distorsionando la imagen.

Afortunadamente, hay un polyfill que corrige esto en IE9 +, que puede encontrar aquí . (Gracias a @fk por señalar esto).

A continuación, se explica cómo implementar el polyfill:

  1. Asegúrese de haber incluido la declaración adicional font-family en su CSS (ver arriba)
  2. Instale el polyfill en su proyecto: npm install —save object-fit-images
  3. Cree un archivo gatsby-browser.js en la raíz de su proyecto
  4. Agregue lo siguiente a gatsby-browser.js :
import objectFitImages from 'object-fit-images'

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

NOTA: Activé el polyfill en onInitialClientRender porque las instrucciones del polyfill son colocar la llamada de activación "antes de </body> , o _en DOM ready_". En otro lugar, he visto a @KyleAMathews recomendar que los polyfills se implementen en onClientEntry lugar, así que no estoy seguro de si eso sería mejor (¿algún comentario, Kyle?).

¡Espero que ayude!

Todos 22 comentarios

¡Es genial saber que está funcionando bien para ti!

En las imágenes de fondo, consulte el sitio de demostración de imágenes de gatsby https://using-gatsby-image.gatsbyjs.org/

¿Es eso lo que quieres?

¡Gracias por la rápida respuesta!

Solo para asegurarme de que entiendo lo que está sucediendo en el sitio de demostración de gatsby-image ...

  1. En lugar de usar background-image , gatsby-image siempre usa <img /> y las imágenes de fondo se simulan usando position: absolute; ?
  2. En lugar de usar background-size/background-position para colocar imágenes, gatsby-image siempre usa object-fit/object-position ?

Estoy perfectamente feliz de usar gatsby-image de esta manera para todas mis imágenes siempre que se muestren correctamente en todos los navegadores modernos ... ¿Gatsby incluye medidas para admitir las propiedades de ajuste de objeto / posición de objeto en IE 11 y Edge ( ver problemas de soporte del navegador aquí: caniuse.com )?

Si es así, ¿recomendaría que evitemos las imágenes de fondo CSS por completo (para aprovechar el procesamiento de imágenes automatizado de Gatsby)? Usando gatsby-image, ¿hay un enfoque recomendado para ajustar las propiedades de ajuste de objeto / posición de objeto?

Si no es así, ¿existe una forma recomendada en todos los navegadores de utilizar imágenes de fondo con background-size:cover en Gatsby?

@ooloth, el componente es muy nuevo, así que mi respuesta a su pregunta es ... por favor, juegue con el uso de gatsby-image como desee e informe lo que encuentre :-)

Las imágenes de fondo de CSS son problemáticas porque no le permiten agregar (fácilmente) múltiples tamaños de miniaturas para dispositivos de diferentes tamaños. Pero podría solucionar este problema con consultas de medios.

Ja ja. Comprendido. Y lo haré. ¡Gracias por tu ayuda!

Si alguien más quiere compartir sus mejores prácticas para lo siguiente, estaría muy interesado:

  1. Cómo admitir object-fit/object-position en IE 11 y Edge (¿Gatsby ya hace esto?)
  2. ¿Cómo modificar los valores de object-fit/object-position ?

Con respecto a 1., eche un vistazo a https://github.com/bfred-it/object-fit-images

@fk ¡ Gracias por el polyfill! A partir del 16 de octubre, Edge admite object-fit/object-position , pero IE11 aún necesita ayuda.

¿Puede aconsejarme sobre una cosa? Tengo claro cómo instalar e importar el polyfill ...
npm install --save object-fit-images
import objectFitImages from 'object-fit-images'

... pero no estoy seguro de dónde realizar la llamada de activación:
objectFitImages()

¿Puede recomendarme dónde colocar esta línea? Soy un poco nuevo tanto en React como en Gatsby.

(Por cierto, he descubierto cómo ajustar los valores de ajuste de objeto / posición de objeto y compartiré ese código tan pronto como haya resuelto agregar el polyfill y sus ajustes de CSS).

Muy bien, hice algunos experimentos y encontré una solución funcional para usar gatsby-image para imágenes de fondo. Quería compartir esto con cualquier otra persona que se quede atascada en este problema, ¡ya que las características de gatsby-image son demasiado buenas para usarlas solo para imágenes en línea!

Esto es lo que funcionó para mí:

1. Agregar estilo CSS

Antes de agregar estilos, es bueno saber que el componente gatsby-image genera el siguiente 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>

Los estilos establecidos directamente en gatsby-image se aplicarán a <div class="gatsby-image-wrapper> . Los estilos que queremos aplicar a la imagen en sí deben usar un selector secundario para apuntar a las etiquetas <img> .

Para hacer que gatsby-image actúe como una imagen de fondo CSS, agregue los siguientes estilos (he usado gatsby-plugin-styled-components aquí):

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

Aquí hay una versión del mismo componente BgImage que usa accesorios para establecer los valores dinámicos:

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

El uso de !important aquí no es ideal, pero es necesario para anular los estilos object-fit/object-position .

Tenga en cuenta que las propiedades object-fit y object-position no necesitarán ajustarse a menos que la imagen de gatsby cubra un área con una altura establecida. Para estos casos de uso, object-fit: cover; generalmente todavía me funciona y solo necesito ajustar el object-position (gatsby-image lo establece en center center de forma predeterminada).

2. Agregue IE9 + Polyfill para ajuste de objeto / posición de objeto

Los estilos anteriores funcionarán en todos los navegadores excepto IE (consulte caniuse.com: object-fit / object-position ). Desafortunadamente, en IE, object-fit/object-position no funcionan, y cualquier imagen de fondo con una altura establecida se estirará para llenar su contenedor, distorsionando la imagen.

Afortunadamente, hay un polyfill que corrige esto en IE9 +, que puede encontrar aquí . (Gracias a @fk por señalar esto).

A continuación, se explica cómo implementar el polyfill:

  1. Asegúrese de haber incluido la declaración adicional font-family en su CSS (ver arriba)
  2. Instale el polyfill en su proyecto: npm install —save object-fit-images
  3. Cree un archivo gatsby-browser.js en la raíz de su proyecto
  4. Agregue lo siguiente a gatsby-browser.js :
import objectFitImages from 'object-fit-images'

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

NOTA: Activé el polyfill en onInitialClientRender porque las instrucciones del polyfill son colocar la llamada de activación "antes de </body> , o _en DOM ready_". En otro lugar, he visto a @KyleAMathews recomendar que los polyfills se implementen en onClientEntry lugar, así que no estoy seguro de si eso sería mejor (¿algún comentario, Kyle?).

¡Espero que ayude!

¡Maldita sea, perdón por no haber vuelto antes @ooloth! ¡Me alegro de que lo hayas descubierto!
¡Gracias por regresar y escribir sus hallazgos! 👍 ❤️

¡Mi placer!

@stolinski se encuentra con el mismo problema en uno de sus tutoriales. Lo hace de una manera diferente:
https://www.youtube.com/watch?v=zhM6C0P7VO0

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

¡Mucho más sencillo! Gracias @ grod220.

@ grod220 eso fue fácil ... Gracias 😄

@enten Eso funcionaría, pero te perderías las ventajas de rendimiento de usar gatsby-image para ofrecer una versión de la imagen con el tamaño adecuado en cada tamaño de ventana gráfica a través de srcset y sizes atributos.

Para mí, la capacidad de usar gatsby-image para entregar fácilmente la copia óptima de cada imagen es la mejor característica de Gatsby. Esos beneficios no están disponibles cuando usa imágenes de fondo CSS.

@ooloth Gracias por cubrir esto. Aquí el novato de Gatsby. En sus instrucciones con el estilo, ¿dónde se menciona la imagen real?

@ fucata55 ¡ Mi placer!

La imagen real es algo que primero consulta a través de graphql y luego pasa como un accesorio a su gatsby-image componente fluid o fixed prop (o si usa v1, su sizes o resolutions prop).

El componente gatsby-image generará todas las copias de la imagen que necesitará también y agregará el complicado atributo sizes al <img /> en el HTML resultante para usted.

Para obtener un tutorial sobre cómo usar gatsby-image (y enviarle una imagen), consulte los documentos de gatsby-image aquí para v2 o aquí para v1 (son geniales).

@ooloth tu trabajo ha sido de gran ayuda. Gracias.

¿Es posible utilizar "archivo adjunto de fondo: fijo"? Si es así, dónde exactamente. Puedo hacerlo funcionar, pero no con safari. Cuando lo hago funcionar, el comportamiento es que la imagen se ve bien hasta que agrego más componentes en la página. Cuantos más componentes se agreguen, más grande se vuelve la imagen. Entonces, hago polyfill para el problema del safari, pero luego el "archivo adjunto de fondo: fijo;" ya no es una opción, o eso parece. Cualquier ayuda muy apreciada.

@zachgaskin ¡Ojalá pudiera ayudar!

Esto parece que probablemente sea un problema de CSS (es decir, no relacionado con Gatsby o gatsby-image ) y me temo que no tengo mucha experiencia en el uso de background-attachment: fixed y no he encontrado el problema. estoy describiendo. Sin embargo, si puede publicar un enlace a una reproducción mínima de este problema, me complacerá echarle un vistazo.

Según caniuse.com , iOS Safari no es compatible con background-attachment: fixed , pero macOS Safari debería funcionar (debería ...).

Puede ser una verdadera molestia entender por qué ciertos navegadores tratan el mismo CSS de manera diferente, así que tiene mi simpatía. ¡Buena suerte!

@zachgaskin @ooloth También me he encontrado con esto. No es ideal, pero la solución que se me ocurrió es agregar position: 'fixed' a la imagen. Aunque, esto significa que está en el fondo de toda la página. Debe asegurarse de tener un fondo especificado en todos los demás lugares. El z-index: -1 se asegurará de que esté oculto detrás de sus otros fondos.

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

La imagen de fondo de Gatsby es un paso adelante ...

Puede resultarle útil importar gatsby-image directamente con un polyfill de IE y aplicar objectFit y objectPosition como accesorios, en lugar de usar! Important en sus estilos

import Img from 'gatsby-image/withIEPolyfill'

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

Gracias, @AronBe

No estoy trabajando con Gatsby en este momento, así que no sé lo último; sin embargo, la imagen de fondo de Gatsby (mencionada anteriormente) realmente me ayudó en mi último proyecto.

¿Fue útil esta página
0 / 5 - 0 calificaciones