Responsive Div that Resizes Proportionally within Parent Container

Having a div element that adjusts its height based on width to maintain aspect ratio, I aim to place this div within another while maximizing available space vertically and horizontally without any cropping. It seems that object-fit: contain, typically used for images, may be the closest option.

The goal is to ensure the div covers the maximum height and width possible while still adhering to the aspect ratio, with no crop in either vertical or horizontal directions.

Can this be achieved using CSS alone? If so, how?

Want more insight? Check out this informative article.

Code snippet (or any alternate solution):

html,
body {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 100%;
}

.container {
  position: relative;
  width: 100%;
}

.container:before {
  content: "";
  display: block;
  width: 50%;
  padding-top: 50%;
}

.embed {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: red;
}
<div class="container">
  <div class="embed">
    this should accommodate all the available space and maintain aspect ratio, no crop when width is too wide
  </div>
</div>

https://i.stack.imgur.com/rs95z.png

Answer №1

Learn about aspect-ratio and how it can be used with overflow:hidden in Chromium 88 to create visually pleasing designs.

Update for January 2023:

A new container query @container (aspect-ratio > X) is now required for Firefox version v110.0b2, Safari, and Chromium browsers. Make sure to update your code accordingly.

You can find the updated code snippet below and also view a demo on jsitor by visiting this link.

html,
body {
  display: flex;
  justify-content: center;
  align-items: center;

/* Rest of the CSS code omitted for brevity */
}
<div class="container">
  <div class="embed">
    <div>1:1</div>
  </div>
</div>

Answer №2

After exploring various options, it appears that a CSS-only solution may not be feasible for this particular challenge. For those who are curious, I have developed a custom React component that addresses the issue (Expect tests and an improved README in the near future).

This component encapsulates its content within a div, utilizing JavaScript to determine the dimensions of the containing element so that it can adjust accordingly while maintaining the desired aspect ratio. Essentially, it adjusts the container size until one side reaches its maximum limit.

LATEST UPDATE: A recent breakthrough has led to the discovery of a potential CSS-based solution!

Answer №3

One way I found to work around this issue is by enclosing the child element within an svg's foreignObject tag:

const container = document.getElementById('container');
document.getElementById('btn').addEventListener('click', () => {
  container.style.height = container.style.height === '100px' ? '200px' : '100px';
});
body {
  margin: 1rem;
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

button {
  margin-bottom: 1rem;
}


#container {
  background-color: #ffceaf;
  width: 400px;
}

svg {
  background-color: #b8d6ff;
  height: auto;
  width: auto;
  max-width: 100%;
  max-height: 100%;
  overflow: hidden;
}

#content {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  border: solid;
}
<button id="btn">Change parent height</button>

<div id="container" style="height: 100px;">
  <svg width="15000" height="5000">
    <foreignObject width="100%" height="100%">
      <div id="content">
        content content content content content content content
        (...continued)
      </div>
    </foreignObject>
  </svg>
</div>

However, there are some drawbacks to this approach:

  • Limited browser compatibility (IE/Edge do not fully support foreignObject)
  • It may not be considered best practice. Introducing elements from a different XML namespace could lead to potential issues(?).

Considering these factors, using JavaScript might be a more reliable option in this scenario.

Answer №4

Check out this CSS-only solution I came up with:

View Codepen Demo or you can run the demo below ⬇

.resizable-container {
  resize: both;
  overflow: scroll;
  border: 1px solid black;
  padding: 3px;
  height: 140px;
  width: 330px;
}
.container {
  height: 100%;
  box-sizing: border-box;
}
.aspect-thing {
  aspect-ratio: 16/9;
  border: 2px red solid;
  box-sizing: border-box;
  max-width: 100%;
  max-height: 100%;
  margin: auto;
}
<div class="resizable-container"> 
  <div class="container">
    <div class="aspect-thing">
    </div>
  </div>
</div> 
<p>You can resize me ^</p>

https://i.stack.imgur.com/7HOQA.gif

Answer №5

This solution utilizes pure CSS with nested flexboxes. The outer container has a flex-direction: row property, while the inner container has a flex-direction: column property. It is crucial that the inner container's aspect-ratio is set to 1/1 and the height of the inner container is defined, along with the width of the pseudo-element inner:before.

<div class="outer">
  <div class="inner"></div>
</div>
.outer {
  width: 80%;
  height: 80%;
  margin: auto;
  background-color: red;
  padding: 50px;
  display: flex;
  justify-content: center;
  align-items: center;
}

.inner {
  height: 100%;
  aspect-ratio: 1 / 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  overflow: hidden;
}

.inner:before {
  content: '';
  width: 100%;
  aspect-ratio: 1 / 1;
  background-color: blue;
}

Answer №6

Take a look at this refined version of the solution inspired by Ben Winding, which effectively centers the div vertically:

Codepen Link or try out the demo below ⬇

:root {
  --aspect-ratio: 16/9;
  --container-max-width: 90%;
}

.resizable-container {
  resize: both;
  overflow: scroll;
  border: 1px solid black;
  padding: 3px;
  height: 140px;
  width: 330px;
}

.container {
  height: 100%;
  box-sizing: border-box;
  width: 100%; 
  max-width: var(--container-max-width);
  margin: auto; 
  display: flex;
}

.inner-container {
  flex-grow: 1; 
  align-self: center;
  max-width: 100%;
  max-height: 100%; 
  aspect-ratio: var(--aspect-ratio);
}

.aspect-thing {
  aspect-ratio: var(--aspect-ratio);
  border: 2px red solid;
  box-sizing: border-box;
  
  max-width: 100%;
  max-height: 100%;
  margin: auto;
}
<div class="resizable-container"> 
  <div class="container">
    <div class="inner-container">
      <div class="aspect-thing">
      </div>
    </div>
  </div>
</div> 
<p>Resize me ^</p>

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

Can you navigate to HTML files using Vue router?

Hey there! I'm currently utilizing VueJS along with the webpack template. I've got a variety of components that I can easily showcase with Vue Router. However, the testing framework utilized by my team is Robot Framework and we typically create a ...

What is the best way to iterate over my JSON data using JavaScript in order to dynamically generate cards on my HTML page?

var data = [ { "name":"john", "description":"im 22", "email":"<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="4c7d7e7f0c2b212d2520622f">[email protected]</a>" }, { "name":"jessie", ...

Experiencing a hiccup in your jQuery animation?

Click here to access the fiddle demonstrating the issue. A situation arises where a span with display: inline-block houses another span that is being slowly hidden. The container span unexpectedly shifts back to its original position once the hiding proces ...

How do I easily show/hide a submenu in AngularJS with a toggle menu?

After browsing some Stacks, I've come to the realization that I need to create separate directives in order to hide or toggle a menu from its sub-menu items. I want the menu to be hidden when any of the sub-menu items are clicked. However, I can&apo ...

Can CSS3 be utilized to craft this specific shape?

Can CSS3 be used to create the shape I need? I came across this website http://css-tricks.com/examples/ShapesOfCSS/, but I am unsure if any of the shapes on that page can be customized to match the specific shape I have in mind. Thank you! ...

Vertical centering of inline-block elements remains unaffected by line-height changes

I attempted to center an inline-block vertically in the following manner: div { width: 50px; height: 50px; background: red; line-height: 50px; } span { display: inline-block; width: 20px; height: 20px; background: white; } <div> ...

Tips for connecting a Vuetify v-menu to its parent element within a list that can be scrolled

Within the project I am working on, there exists a scrollable inventory of items. Each item possesses a menu that is triggered open when the respective activator button is hovered over. By default, v-menu components are connected to the v-app element, ser ...

Having Trouble with Your Instafeed Script

I've been working on a project that involves integrating an Instagram feed into a website. However, I'm facing difficulties getting it to function properly. Here's the code that I have implemented. <script type="text/javascript"> ...

Is there a way to showcase a block of Python code using a combination of HTML, CSS, and Javascript to enhance its

On my website, I want to display code blocks similar to how StackOverflow does it. The code block should be properly colored, formatted, and spaced out for better readability. All the code blocks on my site will be in python. def func(A): result = 0 ...

Retrieve the most recent 5 entries from a database using PHP and display them in an ordered list on an HTML page

Currently, I am in the process of learning how to populate an ordered list within an HTML page with the 5 most recent records from a table using PHP. While I have managed to grasp most components (with some difficulties in PHP), my main challenge lies in e ...

Creating Sleek Tables - comparing the benefits of using table-layout:fixed versus setting individual td-width to

Several weeks ago I posted a query (Table overflows parent div when td content is too wide) related to table design. The response I received seemed to resolve the issue perfectly. Now, as I attempted to redesign the table yesterday, I encountered a challen ...

Showing the name of a class

Hello everyone, I have a piece of JavaScript code that generates HTML buttons when the page loads. The button attributes are fetched from a database through an ASP page. Everything is working fine except for displaying the class attribute - it shows as u ...

Can floating elements be disregarded by block elements?

According to W3C, the behavior of floating elements is such that: When a float is present, non-positioned block boxes that come before and after the float flow vertically as if the float doesn't exist. However, line boxes positioned next to the fl ...

Unused sizing attributes in IMG tags

I can't seem to figure out what's going wrong here... I want the image tag to initially display the 250px wide "small" image, and then allow the browser to select the most suitable image using the srcset and sizes attributes - essentially, the " ...

CSS - fixed table headers

Check out my CodePen example here - Code In this demo, I have a table inside a container where the table is larger than the container. As you scroll horizontally, both the table and headers move accordingly. However, when scrolling vertically, I want th ...

The navigation bar is failing to display all of the titles

Having trouble with my HTML page. I can only see the first word of the title in the drop-down list. The navigation bar refuses to center despite trying various styles. Below is my CSS code: background-color: #78706e; height: 100%; font-family: Arial; c ...

What is the best way to allocate a unique color to every item within an array?

I've been working on some JavaScript code that pulls a random color from a selection: const colors = [blue[800], green[500], orange[500], purple[800], red[800]]; const color = colors[Math.floor(Math.random() * colors.length)]; Within my JSX code, I ...

Customizing Your JQuery.awesomeCloud.plugin with a Tooltip Functionality using jQuery

Is it possible to integrate a jQuery Tooltip feature when hovering over specific words in a word cloud? I am currently using [jQuery.awesomeCloud.plugin]:https://github.com/indyarmy/jQuery.awesomeCloud.plugin If there is an alternative method to add toolt ...

What is the best way to insert a row into a JavaScript table while incorporating a cell that utilizes the datepicker function in jQuery?

Currently, I am working on a javascript function: function addItem(tableID){ var table = document.getElementById(tableID); var rowCount = table.rows.length; var row = table.insertRow(rowCount); var cell1 = row.insertCell(0); var el ...

Separate sentence to one word per line

Can CSS be used to display each word of a sentence on a separate line? Input: <div>Hello world foo bar</div> Rendered output: Hello world foo bar It is not ideal to set the width to 1px, as specified. ...