I'm working on an app in React Native for both Android and iOS.
I have a View that I would like to display an image with no white space. My View is sized using Flex, so it is dynamic in sizing based on the screen size. I would like the centre of the image to be in the centre of the View. If the width is larger than the height, I would like the width of the Image to equal the width of the View, with the top and bottom of the Image being clipped off. If the height is larger than the width, I would like the height of the Image to match the height of the View with the sides being clipped off.
I have tried to use 'contain' and 'cover', but they don't seem to achieve what I would like. I could also just not be setting my styles up properly. This is what I have right now:
<Image style={{ flex: 1, width: width, height: height, resizeMode: 'cover' }}
source={require('../../images/Road03.png')}
/>
Width and height are equal to the width and the height of the window:
var {height, width} = Dimensions.get('window');
I've also tried to look for libraries that achieve this, but I haven't found any that let me size the mask.
Related
I built an iOS app with React Native. I used Expo to build it. In dev mode, I have an image that I manipulate and it works as expected. In production mode the image is zoomed in and cut off. Here is the code:
<Image
source={require("../assets/Logo.png")}
resizeMode={"center"}
style={{
resizeMode: "center",
transform: [{ scale: 0.8 }],
width: 250,
height: 75,
}}
/>
The reason I have both the resizeMode prop and the style is because it wasn't working earlier so I just added both in hopes that one of them would work. Please let me know if you know what the problem might be. Thanks.
There is the issue with center resize mode in iOS, see the issue for details.
Use contain instead, which is probably the right approach anyway in this case.
contain: Scale the image uniformly (maintain the image's aspect ratio) so that both dimensions (width and height) of the image will be equal to or less than the corresponding dimension of the view (minus padding).
See all options for resize mode.
Lighthouse keeps telling me that "Image elements do not have explicit width and height" eventhough i've tried to add it both in css or in img but the problem persists:
img.medium {
max-width: 29rem;
width: 100%;
}
or
<img
src={user.seller.logo}
alt={user.seller.name}
width="100%"
height="auto"
/>
How can i tackle this?
Short Answer
Add the image's native width and height in pixels as attributes on the image. This lets the browser calculate the aspect ratio for the image.
<img width="600" height="400" src="some-image.webp"/>
Long Answer
width: 100% does not give an element an explicit width.
What it does is define the width relative to it's parent container.
height:auto also does not give an image an explicit height, you are instructing the browser to make the image height whatever it thinks is appropriate based on the image proportions or the size of the container.
The biggest problem with this is the height of an image (as although the width of 100% is not explicit, it will be easy to calculate the actual width purely from the CSS).
When the page is requested the browser does not know the proportions of the image until it starts downloading.
For this reason the page renders (assuming you have inlined your critical CSS) then it requests the image and finds out how tall the image is. The container for the image will then change size to accommodate this image and you will get a layout shift, contributing to cumulative layout shift.
How to fix it
Option 1 - define the width and height using attributes
Option one is to define the image height and width as integers representing pixels by using attributes:
<img width="600" height="400" src="some-image.webp"/>
In modern browsers this will then be used to calculate an aspect ratio for the image and sufficient space will then be allocated on the page before the image starts downloading.
You can then use width:100%; height: auto; as you do now and it will all work as expected.
Using width and height attributes is the recommended best practice.
please note - the width and height values only have to be the correct aspect ratio if you are using CSS to override the dimensions (so width=200 height=100 would give the same result as width=400 height=200 assuming you set the width in the CSS).
Option 2 - use "Aspect Ratio Boxes"
In this technique you define the image height as a proportion of the width within your CSS.
In essence we give the image a zero height and then use padding to allocate the correct amount of space.
.image-div {
overflow: hidden;
height: 0;
padding-top: 56.25%; /*aspect ratio of 16:9 is 100% width and 56.25% height*/
background: url(/images-one.webp);
}
If you don't need to support Internet Explorer (as it is a little temperamental) you can use calc().
padding-top: calc(900 / 1600 * 100%);
This padding technique is explained in detail in this article from css-tricks.
Although this is a bit of a hack, the advantage is no inline attributes on your images, so it is useful for people who like to keep their HTML clean (and for certain scenarios such as if you want make all images the same aspect ratio)
The problem with both
There is only one issue with both techniques, you need to know the image width and height before they are rendered in order to calculate the aspect ratio.
There isn't much you can do to avoid this unless you are willing to make a fixed height and width container for the image.
Then if the image is a different aspect ratio to your container you will have some white space around the image but the page will not have a layout shift (which would be preferable in most circumstances) - assuming you use overflow:hidden etc. on the container.
.container{
width:50vw;
height:28.125vw; /*fixed height, doesn't have to be aspect ratio correct, see example 2 */
overflow:hidden;
margin: 20px;
}
.container2{
width:50vw;
height:40vw; /*fixed height, but this time there is extra white space (shown as dark grey for the example) below the image.*/
overflow:hidden;
background: #333;
margin: 20px;
}
img{
width: 100%;
height: auto;
}
<div class="container">
<img src="https://placehold.it/1600x900"/>
</div>
<div class="container2">
<img src="https://placehold.it/1600x900"/>
</div>
I am trying to figure out how to precisely position an image in a container in React Native.
Right now I have what is on the left, and I would like to be able to position the image like the example on the right. (and not justifying center as the part of the image I want to show is not necessarily the center of the image)
To be more clear what I want is to be able to re-position the part of the image that is showing. (ie: move it to the right but keeping it only taking up the same space)
and here is a snack:snack.expo.io
As far as I understand, what you are looking for is resizeMode property.
resizeMode = "cover"
Scale the image uniformly so that both
dimensions of the image will be equal to or larger than the
corresponding dimension of the view.
Try this. Note that I added resizeMode="cover".
<Image style={styles.image} resizeMode="cover" source={{uri: 'https://www.gstatic.com/webp/gallery/1.jpg'}} />
So... I did find that I can get the result I want if I add:
width: '170%'
image:{
flex: 1,
height: '100%',
width: '170%'
},
My assumption would be that this would stretch the image out but it just seems to re-position it. I am not sure why this behaves this way. I would think that there would be a better way to approach this problem but I haven't found anything.
I'm working on an Ionic app. I have a two column layout of squares, for an example let's say they're 100x100. I'd like to rescale and then center (horizontally and vertically) images within those squares.
The images to put in them, however, do not have identical aspect ratios. I'd like to resize images to cover the same surface area, regardless of dimensions.
Again, for example, let's say that I want each image to cover 25% of my squares in the grid. If I have a 1000x1000 image, it would be resized to 50x50 to cover 25% of the area within a square. If I had a 500x250 image, it would be resized to ~70x35.
Mathematically I understand at least one way how to do this: image dimension * sqrt((image width x image height) / (0.25)(div width x div height)). It's in code with Angular, however, that I'm struggling.
Any advice?
I would try to use CSS if possible. It will be much lighter for the browser to render this and much easier for you to implement.
To do this, create boxes in your template and each box will have an image as a background. You can set that using ng-style attribute on the box.
In your CSS you could do something like this:
.image-box {
width: 50px;
height: 50px;
background-size: cover;
}
I have a fixed container of 100vh x 100vw that contains 6 absolutely positioned divs that are 100vh x 100vw.
I use a dummy element that is positioned relative w/ 6 divs that are 100vh to trigger each scene.
When I resize the window, the scene's animation moves forward and backward in time. Is there a way to prevent that from happening?
The issue is that when you resize the window, the position of the scroll bar remains fixed at an absolute number of pixels. However, because your content is based on view height, the height of the document changes dynamically as you resize the window. Thus, the window scroll position as a percentage of the document body height is also changing, and this is what ScrollMagic bases progress on.
To illustrate with simplified math:
A) Given a window height of 1000px, your document height will be 6vh * 1000px = 6000px tall. If your window scroll position is 1200px, you'll be 20% of the way through the overall ScrollMagic timeline.
B) If you resize the browser to 800px tall, that changes the document height to 6hv * 800px = 4800px tall. However the window scroll position will remain at 1200px, which is now 25% of the way through the ScrollMagic timeline.
The simplest solution is probably to keep your document a fixed height.