CSS: Keep Aspect Ratio of an Element for Given Height - html

The above link to a possible duplicate is not a solution for this case, because the height will be a fixed value for several breakpoints.
I have some DIVs with display:inline-block, so they are floating nicely side by side. These DIVs all have the same height, e.g. height:300px. Later, I will load an image inside every DIV with Ajax, and I want the DIV to keep the aspect ratio of the image, so they won't wiggle all around, when the image is actually loaded.
So when the DIVs are displayed in the browser, the images are not yet there, so fixing the height for the image with height:auto; won't work.
Sample code:
<div class="wrapper">
<div class="item">...</div>
<div class="item">...</div>
<!-- More items here -->
</div>
CSS:
.item {
display:inline-block;
vertical-align:top;
height: 300px;
width: /* depending on the image ratio */
}
Now I know how to keep the aspect ratio of an element for a given width (see here or here). But since my DIVs should all have the same height, how can I keep the aspect ratio and change just the width?
One (not really good) solution would be to insert a blank image and to resize this image to the right dimensions.
The problem is: when resizing the window, the height of all the DIVs will change, so just calculating the width is not enough. I could recalculate the width with Javascript, but I prefer a plain CSS version (if possible).
So here is my question: how can I keep the aspect ratio for an element for a given height by CSS only?
Thanks

You have the aspect ratio but not actual image dimensions. I think you can use the calc function for this. Browser support is an issue though:
/* Note: using 30px height for demonstration */
.item {
display: inline-block;
vertical-align: top;
height: 30px;
background: #FC0;
}
.ratio-3-2 .item {
/* 3:2 = 1.5 */
width: calc(30px * 1.5);
}
.ratio-4-3 .item {
/* 4:3 = 1.3333 */
width: calc(30px * 1.3333);
}
<div class="wrapper ratio-3-2">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
<div class="wrapper ratio-4-3">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
In the above demo, the first set of divs will be 45px wide and the second set will be 40px wide.

I would set the width of the DIV according to template I'm using, so it would be responsive, and add this to my code:
img.item {
width:auto; height:300px;width: auto\9; // for IE
}
This will make sure you could control the DIV while the images would fit there nicely
Mind due you may want to change it to max-height:300px; for responsive site

Related

Container height equal to it's overlapping children with dynamic heights

Consider you are a block container with fixed width, height: auto and two elements inside of you. Each element has it's own height based on the number of items inside it. Now, you want your children to be positioned at the top, overlapping each other. But, at the same time you want your height to be equal to the height of the child with the most items.
Do you think you can handle it on your own, without asking that weird JS wizardly-guy to look after you and your children?
Also, your children seems to like dynamically changing the number of items inside of them, so you sadly can't use fixed heights here.
Desired result:
(each item is translated to the left a bit for better view)
Yay, some code!
<div class="container">
<div class="child">
<div class="item"></div>
<!-- ... -->
</div>
<div class="child">
<div class="item"></div>
<!-- ... -->
</div>
</div>
.container {
width: 300px;
}
.menu {
}
.item {
height: 30px;
}
👨‍💻 JSFiddle with example
Yes, you can do this! If you are a CSS grid.
According to the specs, if you put two elements in the same cell. they will overlap each other and with align-items: start; you can align items by their tops.
<div class="container">
<div class="child">
<div class="item"></div>
<!-- ... -->
</div>
<div class="child">
<div class="item"></div>
<!-- ... -->
</div>
</div>
/** Creating a CSS grid with a single cell */
.container {
display: grid;
grid-template-columns: 1fr;
grid-template-rows: 1fr;
grid-template-areas: 'cell';
align-items: start;
}
/** Putting both children in the first cell */
.child {
grid-area: cell;
}
.item {
height: 30px;
}
And here's the updated JSFiddle to demonstrate the solution.
CSS grid has a pretty good browser coverage. Make sure to use autoprefixer for IE though.
If you know another/better approach, please add it as well, I'm sure it will be useful.

Flexbox layout losing proportions when reduced in size

I'm reproducing a golden spiral using CSS flexbox and percentage size for cells.
The round shape is drawn using a regular border and border-radius combination.
Everything is proportional until I resize the window to smaller widths.
I tried removing borders completely and turns out the layout is still losing proportions at some point.
Big container:
Small container:
Demo:
https://jsfiddle.net/s09rkwub/1/
html
<div class="wrapper">
<div class="rows fib">
<div class="cols fill">
<div class="rows fill">
<div class="fr tl">3</div>
<div class="fill cols">
<div class="fc bl">4</div>
<div class="fill rows">
<div class="fill cols">
<div class="fill tl fr">7</div>
<div class="fc tr">6</div>
</div>
<div class="fr br">5</div>
</div>
</div>
</div>
<div class="fc tr">2</div>
</div>
<div class="fr br">1</div>
</div>
</div>
css
.rows {
flex-direction: column;
}
.cols {
flex-direction: row;
}
.rows,
.cols {
display: flex;
.fill {
flex: 1;
}
> * {
outline: solid 1px rgba(127,127,127, 0.3);
}
}
...
Update:
Working demo with applied solution.
Update 2
Thanks to Your support guys. I could finish my fib spiral codepen.
Solution
Add this to your code:
* {
flex-shrink: 0;
min-width: 0;
min-height: 0;
}
revised fiddle
Explanation
Two concepts to consider:
An initial setting of a flex container is flex-shrink: 1.
This means that, by default, flex items are allowed to shrink below any defined width, height or flex-basis.
To prevent this behavior use flex-shrink: 0.
More details here: What are the differences between flex-basis and width?
An initial setting of a flex item is min-width: auto.
This means that, by default, a flex item cannot be smaller than the size of its content (regardless of flex-shrink or flex-basis).
To allow flex items to shrink past their content use min-width: 0 (row direction), min-height: 0 (column direction), or overflow: hidden (other values also work, except visible).
More details here: Why doesn't flex item shrink past content size?
With the adjustment below, your flex items can shrink past the text you have in your divs, allowing the scaling to continue without any obstacles:
* {
flex-shrink: 0;
min-width: 0;
min-height: 0;
}
Taking <div class="fr br">5</div> as an example, it's min-width is 26px. Thus, scaling the spiral down to a level, where the mentioned div's height becomes less than 26px, it's getting distorted.
If you change the border width to 1px instead of 5px, you'll see, that suddenly, it's able to scale down to 18px perfectly fine and breaks in smaller sizes.
That's why you probably tried to reduce the border. However, the reason for the distortion is much simpler: You have content inside the divs and they do require some space (even if the font color is transparent). If you remove all the numbers from the div elements, you get the desired result. See the demo at https://jsfiddle.net/s09rkwub/2/

Creating equal height divs in Bootstrap 4 flexbox

I use Bootstrap 4 flexbox enabled. I can not make row > col > div box equal heights.
I have tried position: absolute but it is not the best.
Here's a screenshot:
<div class="row" >
<div class="col-xs-12" >
<div class="home_category" ></div>
</div>
<div class="col-xs-12" >
<div class="home_category" ></div>
</div>
</div>
col-xs-12's height always equals but .home_category height varies based on content size.
I'm looking for a solution to have 100% height for .home_category. Same height as col-xs-12.
Live demo at https://officestock.ca/
I appreciate your feedbacks.
In reviewing your code, the boxes are currently getting their height from the content. You'll notice that some image labels are two-line and others are three-line. The differences in those line numbers are causing differing heights for the boxes.
To apply full, equal height to all boxes simply make this adjustment to your CSS:
#media (min-width: 48em) {
.col-md-6 {
flex: 0 0 50%;
display: flex; /* NEW */
}

align horizontal divs centrally

I am trying to have a horizontal row of divs, all of the same width and containing some text. Ideally, I don't want to set their positions manually because it will be difficult to maintain/replicate with a different number of divs. My two approaches so far, neither of which have been satisfactory, are:
1. Use a series of divs, setting float: left in css. This way they all fall to the left, when I want them, essentially, justified so they fill the width of their container with even spacing.
2. Use a series of spans, setting text-align: center for their parent in css. This justifies then correctly but the text inside the spans are of varying length, meaning the ones with less text are less wide than the others.
How can I combine these two properties: the ability to set the width manually as for divs, but the ability to set the position to be central as for spans with text-align. Is there a property like floating-child-align?
You can set the width of your spans if you give them display: inline-block.
You can do it right if you calculate the margins and sizes of the divs properly. For example look at the following fiddle : http://jsfiddle.net/r7KMB/
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
.container {
width : 230px; height:20px;
border : 1px solid black;
}
.item {
width: 30px; height: 15px;
border : 1px solid red;
margin: 1px 5px 1px 5px;
display: inline-block;
}

Setting a fixed height for 3 div's

Im having an issue with the header of my code. The header is split into 3 different column's two of which are currently populated with text and an image. (center is yet to be filled).
I notice that when i reduce the size of my browser (zoom in,out) two of the header column's start to break away from the content. The right column stays fixed to the content below because it is populated with text however the center column and the left column being less populated start to break away.
Is it possible to force my 3 column header to stay attached to the content below? Im worried that if someone views the site on a large screen or perhaps a retina display it is going to break away.
<div class="col span_1_of_3 a">
<div class="col span_1_of_3 b">
<div class="col span_1_of_3 c">
CSS is as follows:
.span_3_of_3 {
width: 100%;
}
/* line 28, ../sass/test.scss */
.span_2_of_3 {
width: 66.1%;
height:100%;
}
/* line 32, ../sass/test.scss */
.span_1_of_3 {
width: 33.32%%;
height:100%;
}
Wrap the divs in a parent div. Then float the children and give them a relative width.
<div class="header">
<div class="col span_1_of_3 a">
<div class="col span_1_of_3 b">
<div class="col span_1_of_3 c">
</div>
css:
.header { width:100%; overflow:auto; }
.col { float:left; width:30% }
You can use display: table-cell on each .col and display: table on parent (*). That will force your "cells" to have the same height and stay on the same row.
Though I wonder how you managed your witdths? Is it in percentage or em? You didn't include any CSS so it's impossible to figure.
(*) Add table-layout: fixed on this same parent if you want precise widths to be applied, otherwise the browser will also adapt to the content of each "cell".
Image re sizing will be out of control unless you set the Width/Height to percentage or relative values.
if you don't want to do this, simply set the min-width and min-height CSS Properties.
i prefer the relative sizing (ex. width: 30%; text-align: left;)