Adjusting the sizes of images with varying aspect ratios to perfectly fit within a div without distorting its shape

I'm currently in the process of developing my portfolio website and I am faced with creating a simplistic image browser feature. My goal is to have a container div that adjusts in size according to the browser window, allowing it to house images of various aspect ratios alongside captions of fixed height but width relative to the image's width. Rather than having the div stretch to accommodate the images, I aim to resize the images themselves (as demonstrated in the provided picture).

View illustration of the problem here

My initial attempt involved using JavaScript to calculate the image size, however, I encountered difficulties as I was unable to determine the element's dimensions before it had fully loaded. Below is an outline of how I approached this issue (excluding consideration for the titlebar):

var divAspectRatio = containerDiv.offsetHeight/containerDiv.offsetWidth;
var imageAspectRatio = image.offsetHeight/image.offsetWidth;
if(divAspectRatio>imageAspectRatio){
  image.style.height = content_in.offsetHeight;
}else{
  image.style.width = content_in.offsetWidth;
}
captionDiv.style.width = image.offsetWidth;

Any suggestions on how I can resolve this?

Answer №1

To achieve the desired layout, some calculations are necessary due to the difference in aspect ratios between an image and its container. It is important to ensure that the caption area is only as wide as the displayed image, while maintaining a fixed height.

The images are enclosed within an 'innerdiv' element, which also contains the caption. Upon loading, the image's aspect ratio is calculated and stored as a CSS variable. Additionally, various other CSS variables are pre-defined for customization options. The remaining calculations are then handled purely in CSS.

window.onload = function () {
  const imgs = document.querySelectorAll('.container .innerdiv .img');
  imgs.forEach(img => {
    img.parentElement.style.setProperty('--imgratio', img.naturalWidth / img.naturalHeight);
    img.parentElement.classList.add(( (img.naturalWidth / img.naturalHeight) > getComputedStyle(img).getPropertyValue("--containerratio") ) ? 'wider' : 'thinner');
  });
}
* {
  padding: 0;
  margin: 0;
}
.container {
/* SET THE NEXT 4 VARIABLES TO WHAT YOU REQUIRE */
  --unit: 1vmin; /* the basic unit - must be fixed e.g. vmin, px, ch not % */
  --containerw: 40; /* width of a container in these units */
  --containerratio: 1.5; /* the ratio of width to height */
  --captionh: 4vmin; /* height of a caption including its units (which must be fixed e.g. vmin, px, em */

  --containerh: calc(var(--containerw) / var(--containerratio));

  display: inline-block;
  width: calc(var(--containerw) * var(--unit));
  height: calc(var(--containerh) * var(--unit));
  position: relative;
  border: solid;
}

.innerdiv {
  display: inline-block;
  position: absolute;
  top: 0;
  left: 0;
}

.innerdiv.thinner {
  width: calc(var(--imgratio) * ((var(--containerh) * var(--unit)) - var(--captionh)));
  height: 100%;
  left: 50%;
  transform: translateX(-50%);
}

.innerdiv.wider {
  width: 100%;
  height: calc((var(--containerw) / var(--imgratio)) * var(--unit) + var(--captionh));
  top: 50%;
  transform: translateY(-50%);
}

.img {
  width: 100%;
  height: auto;  
}

.caption {
  font-size: 2vmin;
  background-color: yellow;
  text-align: center;
  width: 100%;
  height: var(--captionh);
  position: absolute;
  top: calc(100% - var(--captionh));
  left: 0;
}
<div class="container">
  <div class="innerdiv">
    <img class="img" src="https://picsum.photos/id/1016/200/300">
    <div class="caption">CAPTION</div>
  </div>
</div>
<div class="container">
  <div class="innerdiv">
    <img class="img" src="https://picsum.photos/id/1016/500/200">
    <div class="caption">CAPTION</div>
  </div>
</div>
<div class="container">
  <div class="innerdiv">
    <img class="img" src="https://picsum.photos/id/1016/300/300">
    <div class="caption">CAPTION</div>
  </div>
</div>

Answer №2

For a background image within a div element, ensure to include the following in your CSS, within the div section: background-size: cover;

If the image is contained within an img element, be sure to add the following to your CSS, within the img section: object-fit: cover;

Answer №3

Consider incorporating the following css property:

object-fit: cover

By doing so, your image will be adjusted to properly fit within its designated container!

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

"Utilizing Vue.js to make an AJAX request and trigger another method within a

How can I include another method within a jQuery ajax call? methods : { calert(type,msg="",error=""){ console.log("call me"); }, getData(){ $.ajax({ type: "GET", success: function(data){ / ...

Activate Bootstrap datetimepicker by using the enter key to automatically populate the initial date

Check out the Bootstrap datetimepicker on this page: I'm trying to make it so that when the datetimepicker is first shown, pressing the enter key will hide the widget and insert the current date into the input field. I've experimented with a few ...

Deploy a Node.js websocket application on Azure Cloud platform

After smoothly running on Heroku, the server app encountered a problem with startup after moving to Azure. Below is the code snippet: const PORT = process.env.PORT || 2498; const INDEX = '/index.html'; const server = express() .use((req, res ...

Is it impossible for both <a> and <name=""> to collaborate in HTML and PHP?

Is it possible to make both <a href works > and name="send" work at the same time within isset($_POST['send']) in this code? Currently, it's not functioning as intended. Is there a way to achieve this for both cases? The requirement i ...

Use the color specified within the string

Recently, we have been revamping an outdated product using VueJs. The original application utilized Spring Web Flow, where all the text editing information was stored in a string. After some research, I discovered that adding white-space: pre-line; as a ...

Unable to save captured signature image during saveEvent function in React Native

I am a beginner in the world of React Native and I am facing an issue with saving a signature image. It seems like the function responsible for this task is not being called properly. I suspect there might be an issue with the onPress event handler, as whe ...

Having trouble with jQuery toggle fade: Unable to make the div fade in/out when toggling

Is there a way to modify the functionality of my black button so that when clicked, the red div fades out while the blue div fades in? Right now, clicking the button switches between the two divs without any fading effect. Fiddle: http://jsfiddle.net/ddac ...

What is the best way to implement buttons dynamically in multiple divs created by Django using JavaScript loops?

I have been working on a Django project where I've created several HTML divs. My goal is to add a single button to each div. https://i.sstatic.net/DEIqL.png In the image provided, you can see a div with the class card-footer that I created using a Dj ...

Troubleshooting not locating view files in ExpressJS and implementing client-side JavaScript and CSS deployment in ExpressJS

My JavaScript file is located in the same directory as my HTML file, and I am trying to render it. I'm unsure of what I may be missing. How difficult could it possibly be? var express = require('express'); var app = express(); app.engine( ...

Leveraging node.js for website development

After setting up Node.js and installing the latest version of Express 3.4.1, I started coding. However, when trying to send parameters other than /, I encountered an error. In my index.js file, I have the following code: exports.speakers = function(req, ...

Boundary around an object within a unified picture

I'm facing a bit of difficulty with a task. I need to add a border around an element within an image (I can't insert an image due to low reputation), and this border should match the width and height of the element exactly. It also needs to be re ...

Running Angular without dependencies causes it to malfunction

I recently ventured into the world of AngularJS and started by creating a module without any services or factories. Everything was running smoothly until I decided to introduce services and factories into my code. Suddenly, things stopped working. Here is ...

I'm curious if there's a method to ensure that the content within a mat-card stays responsive

So I'm working with this mat-card: <mat-card> <mat-card-content> <div *ngFor="let siteSource of siteSources | paginate: { itemsPerPage: 5, currentPage: page};"> <site-details [site]='siteSource'></s ...

What is the fallback mechanism in Astro js when the cache is unavailable?

When the cache is not accessible in Next.js, the page will be server-side rendered and displayed using either the true or blocking fallback approach. I am curious about the approach taken by Astro.js in this situation. I am planning to develop a dynamic b ...

Insert an item into an array of objects at regular intervals of X objects

Here is an example of the array of objects I am working with: [ {_id: "59b6433532b60cfc0a253cec", description: "", imagepath: "https://xxx.1", likes: 0, downvotes: 0} {_id: "59b6433532b60cfc0a253ceb", description: "", imagepath: "https://xxx.2", ...

Swapping a value within an array and moving it to a new position

Consider this scenario: I am dealing with a list of arrays containing values like: let data = [ "10-45-23:45", "10-45-22:45", "10-45-20:45", "10-45-23:45", "10-45-23:59,00:00-04:59", "10-45-23:59, 0 ...

Guidelines for sending an array from a Laravel Controller through AJAX and generating a button based on the received data

Before making a selection, I click on the Color button: <form class="form form-variant"> {{ csrf_field() }} <button type="submit" class="btn btn-success che ...

Using Javascript's .replace() method to preserve HTML elements

This is a JavaScript function I wrote function replaceCharacters(text_input){ return text_input .replace(/O/g, 0) .replace(/I/g, 1) .replace(/o/g, 0) .replace(/i/g, 1) .replace(/t/g, 4) .replace(/d/g, 9) ...

Creating interactive PDF files using ReactJS

Is there a way to create a PDF using React that supports styling and allows the content to be hidden on the page? I need to have a link in my app that, when clicked, generates a PDF and opens it in a new tab. I've tried out various packages but none s ...

Developing tabbed sections in XSLT

Utilizing Angular JS within XSLT, I am aiming to develop a tab-based user interface using XML data. The requirement is to generate multiple links and corresponding div elements based on the number of nodes in the XML. To manage the display of these div ele ...