Using <Img />
from gatsby-image with childImageSharp fluid; the image responsively sizes to fill the parent container width wise, but how is it possible to constrain the the responsive sizing by height? Like a normal image with height: 100%; will responsively maintain it's aspect ratio when constrained by a parent elements height, in a grid row for example. If you explicitly set the parent containers height a gatsby-image <Img />
does not responsively resize but continues to fill the width, cutting off the top and bottom of the image or overflowing out of the containing parent.
Can you query by maxHeight and use aspectRatio
to keep it from getting cut off?
aspectRatio example: https://dev.to/laurieontech/rewriting-a-static-website-using-gatsby-and-graphql---part-3-4ho9#mce_31
Gatsby Image docs: https://www.gatsbyjs.org/docs/gatsby-image/#fluid-image-query-parameters
@marcysutton thanks for the suggestion I'll take a look. using imgStyle={{objectFit: 'contain'}}
is getting me close in combination with styling the outer wrapper of Img.
Using the aspectRatio gives the same results with the cropping or overflow as just providing the fluid prop.
This is the closet I have so far
<Img
fluid={mike.childImageSharp.fluid}
style={{ margin: '1rem', maxHeight: 'calc(50vh - 4rem)' }}
imgStyle={{ objectFit: 'contain' }}
/>
with the 4rem accounting for the margin and padding it then takes up half of the viewport with margin and padding.
I have run into a similar problem I'm trying to overcome. It seems that gatsby-image-wrapper fills 100% of the available width. Which can easily be changed with css but there is no way to treat landscape images different from portrait. What if, like the example below you wanted to have landscape images fill 80% of the available width but have portrait images fill no more than 40-50% each which would result in a layout like this...
So ideally each gatsby-image-wrapper gets a class added depending on it's aspect ratio, which would be either; landscape, portrait or square.
One way to do this could be to write some conditional statement using the aspectRatio that comes with childImageSharp:
edges {
node {
name
childImageSharp {
fluid(maxWidth: 915, quality: 90) {
aspectRatio
...GatsbyImageSharpFluid_withWebp
}
}
}
}
In years gone by I'd probably write some jQuery to do this. Being new to React, would it be possible to write a conditional statement which would add those classes to gatsby-image-wrapper? And if so, how?
When I map over all my gallery images, I can grab the aspect ratio and add it to each gatsby-image-wrapper using className but it's not very useful in it's raw format as the returned data for aspectRatio are numbers like 0.6666666666666666
for portrait images or 1.5003750937734435
for landscape. Having those classes mentioned above would be better to work with; landscape, portrait or square.
{data.allFile.edges.map(({ node }, index) => (
<div>
<Img
key={index}
className={node.childImageSharp.fluid.aspectRatio}
alt={node.name}
fluid={node.childImageSharp.fluid}
/>
</div>
))}
Perhaps this is more of a feature that could be included into gatsby-image itself?
Got a working solution with some help from the friendly people on StackOverflow which I put into a component.
components/imageOrient.js
import React from "react";
import Img from "gatsby-image";
// we only care about `aspectRatio`, the rest will be passed directly to `Img`
const ImgWithOrient = ({ aspectRatio, ...props }) => {
let orientation;
if (aspectRatio >= 1.2) orientation = "landscape";
if (aspectRatio <= 0.8) orientation = "portrait";
if (aspectRatio > 0.8 && aspectRatio < 1.2) orientation = "square";
return <Img className={`${orientation}`} {...props} />;
};
export default ImgWithOrient;
Then using it in templates/post.js
import ImgWithOrient from "../components/imageOrient";
{data.allFile.edges.map(({ node }, index) => (
<ImgWithOrient
key={index}
aspectRatio={node.childImageSharp.fluid.aspectRatio}
alt={node.name}
fluid={node.childImageSharp.fluid}
/>
))}
// remember to query the aspect ratio under Fluid
allFile(
filter: {
extension: { regex: "/(jpg)|(png)|(tif)|(tiff)|(webp)|(jpeg)/" }
absolutePath: { regex: $absolutePathRegex }
}
) {
edges {
node {
name
childImageSharp {
fluid(maxWidth: 915, quality: 90) {
aspectRatio
...GatsbyImageSharpFluid_withWebp
}
}
}
}
}
Hiya!
This issue has gone quiet. Spooky quiet. 馃懟
We get a lot of issues, so we currently close issues after 30 days of inactivity. It鈥檚 been at least 20 days since the last update here.
If we missed this issue or if you want to keep it open, please reply here. You can also add the label "not stale" to keep this issue open!
As a friendly reminder: the best way to see this issue, or any other, fixed is to open a Pull Request. Check out gatsby.dev/contributefor more information about opening PRs, triaging issues, and contributing!
Thanks for being a part of the Gatsby community! 馃挭馃挏
@gillkyle can you take a look at this issue when you get a chance?
@gmossong it looks like this was your question on StackOverflow in case anyone is interested in the link there: https://stackoverflow.com/questions/56832712/react-gatsbyjs-add-class-to-gatsby-image-based-on-aspect-ratio happy you found something that works!
Is the discussion in #15167 relevant to what you are trying to accomplish @bushblade? From what I'm reading there it makes it look like maybe there is something that could fixed in gatsby-image
that could make it so images aren't overflowing or are respected by height
attributes better.
@gillkyle No not quite #15167 looks to be trying to set the height in the graphql query whereas I am trying to style the component as you would a regular <img />
by constraining the height and expecting the image to resize appropriately.
Does this GIF help outline the problem?
When you adjust the height, rather than fill the width you'd expect it to scale down like it does when you set just the width correct? So you _can_ achieve it by setting both the width and height but you'd expect it to just resize like it does when you set width alone?
Correct yes. Like styling a normal image.
Hiya!
This issue has gone quiet. Spooky quiet. 馃懟
We get a lot of issues, so we currently close issues after 30 days of inactivity. It鈥檚 been at least 20 days since the last update here.
If we missed this issue or if you want to keep it open, please reply here. You can also add the label "not stale" to keep this issue open!
As a friendly reminder: the best way to see this issue, or any other, fixed is to open a Pull Request. Check out gatsby.dev/contribute for more information about opening PRs, triaging issues, and contributing!
Thanks for being a part of the Gatsby community! 馃挭馃挏
I'm using styled-components. I was having the same issue. I thought I had resolved with the following declaration:
const componentName = styled(Img)`
picture > img {
height: auto !important;
}
`
This correctlly allows images to scale based on the responsive images techinique i.e width: 100% height: auto.
The problem is that the pre-loading blurred image still comes in loads with height 100% which looks pretty Janki.
Resolved targeted the blured pre-loading images with the following css selector
> img {
height: auto !important;
}
so the full code to make the height auto using styled-component is as follows:
const ShowcaseMockup = styled(Img)`
picture > img{
height: auto !important;
};
> img {
height: auto !important;
}
`
Would love to know if there is a native way to do this through the graphql query for example
There has been discussion similar to this in #15167 and work around this happening on #17006. Maybe that would be able to help find a better solution than a workaround. I'll try and dig into those issues and the PR too when I get the chance.
Did anyone find any kind of workaround? I need to have fixed height images (60vh
) with a variable width.
Edit: I could work around this in my particular case: I set the main <figure />
's height to 60vh
and the width to (aspectRatio * 60)vh
.
Let's track progress in https://github.com/gatsbyjs/gatsby/issues/15167
Does this GIF help outline the problem?
When you adjust the height, rather than fill the width you'd expect it to scale down like it does when you set just the width correct? So you _can_ achieve it by setting both the width and height but you'd expect it to just resize like it does when you set width alone?
Is there any update on this?
Most helpful comment
@marcysutton thanks for the suggestion I'll take a look. using
imgStyle={{objectFit: 'contain'}}
is getting me close in combination with styling the outer wrapper of Img.