Reputation: 795
Consider this javascript code:
const profileImageURL = 'https://api.images.com/image/' + id +'/profile';
let profileImage = [];
async function getProfileImage() {
const response = await fetch(profileImageURL);
profileImage = await response.json();
};
and this svelte template code:
<div class="thumbImg">
{#await getProfileImage()}
<div class='spinnerHolder'
in:fade={{duration: 500}}
out:fade={{duration: 500}}
on:introstart={() => doneLoading = false}
on:outroend={() => doneLoading = true}
>
<svg class="spinner" viewBox="0 0 50 50">
<circle class="path" cx="25" cy="25" r="20" fill="none" stroke-width="5"></circle>
</svg>
</div>
{:then value}
{#if doneLoading}
<img transition:fade alt='profile-image' src={profileImage.url}/>
{/if}
{/await}
</div>
and css:
.thumbImg {
width: 64px;
height: 64px;
display:inline-block;
background-color: var(--border-color);
border: none;
border-radius: var(--large-radius);
overflow: hidden;
img {
min-width: 64px;
border-radius: var(--large-radius);
border-image-width: 0;
}
}
The above loaded images arrive at different widths and heights. Some portrait and some landscape. They need to all be displayed in a square 1:1 box that is 64px x 64px without white space at the side or the bottom. How can I maintain the aspect ratio of these dynamically loaded images so that they either fill the width or height depending on which is needed ? Ideally they would also be offset so they are centered in the 1:1 box.
Visual Examples of the problem:
Upvotes: 0
Views: 61
Reputation: 9959
Updated answer building on Rich's comment below
You can use the object-fit and object-position CSS properties together to fine tune the way the image is displayed inside its content box:
.thumbImg {
width: 64px;
height: 64px;
display:inline-block;
background-color: var(--border-color);
border: none;
border-radius: var(--large-radius);
overflow: hidden;
img {
height: 64px;
width: 64px;
object-fit: cover; // this will make the image cover the content box, clipping horizontally if the original image is landscape orientation, or vertically if it is portrait orientation
object-position: 50% 50%; // this will center the image in the content box (i.e. clip on the left & right if source is landscape and clip top & bottom if source is portrait)
}
}
With this, you do not need to modify your code any further.
Original answer, using CSS background images
You can achieve the desired positioning by using background image CSS properties rather than an img
tag, for example:
.avatar {
height: 64px;
width: 64px;
background-size: cover; // this will make the image cover the div, clipping horizontally if the original image is landscape orientation, or vertically if it is portrait orientation
background-position: 50% 50%; // this will center the image (i.e. clip on the left & right if source is landscape and clip top & bottom if source is portrait)
}
With this, all you have to do is replace your <img>
tag with a <div class="avatar">
tag and set the background image source dynamically:
<div class="thumbImg">
{#await getProfileImage()}
<div class='spinnerHolder'
in:fade={{duration: 500}}
out:fade={{duration: 500}}
on:introstart={() => doneLoading = false}
on:outroend={() => doneLoading = true}
>
<svg class="spinner" viewBox="0 0 50 50">
<circle class="path" cx="25" cy="25" r="20" fill="none" stroke-width="5"></circle>
</svg>
</div>
{:then value}
{#if doneLoading}
<div
transition:fade
class="avatar"
alt="Profile image"
style="background-image: url('{profileImage.url}')"
/>
{/if}
{/await}
</div>
Of course the downside is that you're not using a native image tag anymore, and maybe this is important to you. On the upside, it works without having to use javascript-based DOM manipulation.
Upvotes: 1
Reputation: 71
You can either make the images width and height relative to the parent div by using percentage values or just set the images to the required max-width and max-height
.thumbImg {
max-width: 64px;
max-height: 64px;
display:inline-block;
background-color: var(--border-color);
border: none;
border-radius: var(--large-radius);
overflow: hidden;
img {
max-width: 100%; //relative to the parent DIV
border-radius: var(--large-radius);
border-image-width: 0;
}
}
Upvotes: 0