How can I make a resizable flex item retain its aspect ratio? - html

I have an effect on my website, and it only works within a 16:9 aspect ratio. This means I need to keep it within that aspect ratio. I wanted to make a box that was vertically and horizontally centered which could resize proportionally to contain the effect. I looked up many tutorials and guides on flex resizing, but i still cant get it to work properly. The padding in the that contains the box is lopsided, and it doesnt align properly either. It scrolls horizontally even though im using 100vh/vw?? Does 100% of the viewport's height really mean what it says?
I'm really not sure what to do...
Codepen example of my code below:
https://codepen.io/Ktashi/pen/KKeOJey
html
<div class="flex-align">
<div class="aspect-ratio-box"></div>
</div>
css
body {
padding: 0;
margin: 0;
}
.flex-align {
width: 100vw;
height: 100vh;
margin: 0;
padding: 1vw;
display: flex;
align-items: center;
justify-content: center;
}
.aspect-ratio-box {
height: auto;
aspect-ratio: 16/9;
background: red;
flex-grow: 1;
flex-shrink: 1;
flex-basis: 94vw;
max-height: 94vw;
max-width: 94vw;
}
I tried changing the flex-grow: property's value, along with flex-shrink: and flex-basis: but that didn't help much. I'm very stuck as I've only really been coding with html and css for about a year off and on.

You can use the CSS media query to test whether the item will fit within the parent which has 100vw/100vh dimensions.
This snippet is just to give the idea.
It does a couple of things - makes the parent's padding be part of its dimensions by setting box-sizing border-box and sets the height or width as % of the parent dimensions.
.aspect-ratio-box {
aspect-ratio: 16/9;
background: red;
}
#media (max-aspect-ratio: 16 / 9) {
.aspect-ratio-box {
width: 94%;
}
}
#media (min-aspect-ratio: 16 / 9) {
.aspect-ratio-box {
height: 94%;
}
}
body {
padding: 0;
margin: 0;
background: black;
}
.flex-align {
background: blue;
width: 100vw;
height: 100vh;
margin: 0;
padding: 1vw;
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
}
<div class="flex-align">
<div class="aspect-ratio-box"></div>
</div>

Related

How can I make three containers grow at the same size

So I am building a 3 column preview card using HTML, CSS and FLEXBOX. I built it using the mobile-first approach. It starts off as a column but when it is being expanded and it reaches a certain dimension, it transforms into a row. The problem I am having is that as the containers transform to a row, they grow in different sizes. The heights grow differently as some become columns become taller than others. How can I make sure they all grow at the same rate? How do I make sure that one column does not become larger than the other as they are being expanded? I tried setting flex-grow to 1 and flex-shrink to 1 but it is not working. Please find relevant parts of my code below.
Here is a link to the live version of my site
body {
box-sizing: border-box;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
--The panel is the container as a whole--
.panel {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
border: 1px solid white;
border-radius: 10px;
width: 100%;
max-width: 960px;
height: 100%
}
--I am styling each column below--
.panel section {
display: flex;
padding: 2.5rem;
flex-direction: column;
text-align: left;
border-bottom: none;
height: 100%;
#media only screen and (min-width: 560px) {
.panel {
display: flex;
flex-direction: row;
border-radius: 10px ;
width: 80%;
height: 100%;
}
.panel section {
height: 100%;
}
}
Remove the height: 100% from the child elements and just simply change the align-items to stretch on desktop, that will create equal height columns.
Well there can be different ways to solve this.
Problem : Due to which this error occur . It the difference between the amount of content in three containers as middle has more content that is you have told more about SUVS . This is the cause
Solution : Either you can make the content almost equal or can make the height of container bigger so that content can easily fit
Content equal and Content fixed height - Less compatible as content can vary on need
Increase height of container - Using hard code(400px; 30em) you can increase the height of the container according to need of content . And you can position Learn more btn at bottom using absolute position . So that it positioned at equal height
#media only screen and (min-width: 560px)
.panel section {
height: 30em;
position: relative;
}
.general-button {
background-color: var(--major-color);
border-radius: 5rem;
padding: 0.89rem;
margin: 1.1em 0;
border: none;
width: 8rem;
position: absolute;
bottom: 0;
}

How can I use "object-fit: contain" in CSS and still have a border radius on the image?

I'm trying to show an image in a "lightbox" style so that it will fill the available area on screen, in this case 90% of the width of the page and 70% of the height.
Using object-fit: contain; seems to be the de facto way to do that but it's not quite working with border-radius. Is it possible to use object-fit on an <img> and still have the border radius applied as intended?
You'll need to resize your browser window to see what happens when you run the below snippet. I've got the same code running in JSFiddle, as per the below video.
div {
margin: auto;
width: 90vw;
height: 70vh;
background-color: DeepSkyBlue;
}
img {
width: 100%;
height: 100%;
object-fit: contain;
border-radius: 50px;
background-color: Crimson;
}
<div>
<img src="https://images.freeimages.com/images/large-previews/773/koldalen-4-1384902.jpg">
</div>
Contain isn't really helping here.
Instead, set the max width and height of the img to 100%. The system will fit it in either totally top to bottom or side to side, but the img element will have whatever dimensions it needs so the border radius will work on it OK.
To center the img, if that is what you want, you can display: flex the parent div and justify/align items to the center.
div {
margin: auto auto;
width: 90vw;
height: 70vh;
display: flex;
justify-content: center;
align-items: center;
background-color: DeepSkyBlue;
}
img {
max-width: 100%;
max-height: 100%;
border-radius: 50px;
background-color: Crimson;
}
<div>
<img src="https://images.freeimages.com/images/large-previews/773/koldalen-4-1384902.jpg">
</div>
As commented, setting max-width and max-height seems to be what you need or expect:
div {
margin: auto;
width: 90vw;
height: 70vh;
display:grid;
background-color: DeepSkyBlue;
}
img {
max-width: 100%;
max-height: 100%;
margin:auto;/* x,y center if inside a grid or flex box */
object-fit: contain;/* useless by now, img should keep its ratio */
border-radius: 50px;
border-radius: calc( 5vw + 5vh); /* will scale, maybe you find this usefull */
background-color: Crimson;
}
<div>
<img src="https://images.freeimages.com/images/large-previews/773/koldalen-4-1384902.jpg">
</div>
Use object-fit: cover; instead of contain

Flexbox is not fitting on mobile

This is my first week working with flexbox, and I like it a lot until now. I am doing everything I can to get away of floating elements. Therefore my main purpose is not a solution there is floating elements in. I run into 2 problems, that I am not quite sure of the correct saolution.
Problem 1:
When I hit around 1200px I can see the 2 columns is starting moving together. How can that be?
Problem 2:
Why is my columns not fitting on viewport under 768px? I can see on the mobile the 900x200 is going over the edge of the max width on telephone.
Example page of my code here.
.column-layout {
max-width: 1200px;
background-color: #fff;
margin: 40px auto 0 auto;
}
.column-layout-one {
max-width: 1200px;
background-color: #fff;
margin: 40px auto 0 auto;
}
.header-item-one {
order: 1;
}
.header-item-two {
order: 2;
}
#media (min-width: 768px) {
.column-layout-one {
display: flex;
justify-content: space-between;
}
}
<div class="column-layout-one">
<div class="header-item-one">
<img src="http://placehold.it/280x200">
</div>
<div class="header-item-two">
<img src="http://placehold.it/900x200">
</div>
</div>
.column-layout {
max-width: 1200px;
background-color: #fff;
margin: 40px auto 0 auto;
}
img {max-width: 100%;}
.column-layout-one {
max-width: 1200px;
background-color: #fff;
margin: 40px auto 0 auto;
}
.header-item-one {
order: 1;
}
.header-item-two {
order: 2;
}
#media (min-width: 768px) {
.column-layout-one {
display: flex;
justify-content: space-between;
}
}
<div class="column-layout-one">
<div class="header-item-one">
<img src="http://placehold.it/280x200">
</div>
<div class="header-item-two">
<img src="http://placehold.it/900x200">
</div>
</div>
When I hit around 1200px I can see the 2 columns is starting moving together. How can that be?
Your .column-layout-one has max width 1200 set, inner elements has 280+900 = 1180 px, and you have used space-between on its parent. so, when the parent has space more than its defined width, inner items will be seprated by diffrence of 1200-1180 = 20px; as soon as its parent will shrink this space will reduce, because its the space left by these 2 divs,
Space-between = outerWidth - (Total of inner width)
if you want your images to fit in screen on mobile, then provide it
max-width: 100%, if you will not do so, itwill take its orignal width and distort your design.
Set your .header-item-one and -two to flex: 1; to fill up the whole space in your flex box. Then, set max-width values for the expected results.
.header-item-one {
flex: 1;
max-width: 200px;
background-color: red;
height: 300px;
}
.header-item-two {
flex: 1;
max-width: 900px;
background-color: blue;
height: 300px;
}
About the other problem -- the divs go over the viewport boundaries, because you have placeholder images. Images are fixed-width inline block elements, meaning they won't fit the user's viewport, unless you crop them out with overflow-x: hidden; in the parent div or do something like div img { max-width: 100%; }.
Remove the images and try out that css. Fiddle: https://jsfiddle.net/59meh6vs/

Vertically center element without it becoming inaccessible offscreen

I'm trying to center an element in the middle of the page. I can center it just fine, but if I resize the page vertically until the view height is smaller than the centered element, the element goes offscreen vertically without a scrollbar. You can see a demonstration of the issue here:
http://codepen.io/mse/pen/BWayXV
* {
padding: 0;
margin: 0;
}
html, body {
height: 100%;
}
.outer {
text-align: center;
position: relative;
top: 50%;
transform: translateY(-50%);
}
.inner {
display: inline-block;
width: 400px;
height: 800px;
background: grey;
}
<div class="outer">
<div class="inner"></div>
</div>
I should mention that I have tried a couple of other methods of vertical centering, including flexbox, and I'm still running into the same issue. Is there a way to solve this problem with this method of vertical centering, or is there at least a vertical centering method that does not have this issue?
Try this
* {
padding: 0;
margin: 0;
}
html, body {
height: 100%;
}
.outer {
display:flex;
justify-content:center;
align-items:center;
}
.inner {
background: #ccc;
width: 400px;
height: 600px
}
<div class="outer">
<div class="inner"> I'm a block-level element centered vertically within my parent.</div>
</div>
More info: https://css-tricks.com/centering-css-complete-guide/
CSS VH center generator: http://howtocenterincss.com/
This should work
* {
padding: 0;
margin: 0;
}
html, body {
height: 100vh;
}
.outer {
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.inner {
width: 400px;
height: 800px;
background: grey;
}
<div class="outer">
<div class="inner"></div>
</div>
You can try to limit the size of your inner element. If you define size by a fixed px amount it will start scrolling as soon as the screen becomes smaller than that px amount. If you are ok with changing the height of the inner element you could use vh or you can implement #media queries to decrease the size on smaller screens. Here#s an example:
.inner { height: 100vh; /* 100 view height percentage*/}
Note: The viewport-percentage lengths are relative to the size of the initial containing block and affected by the presence of scrollbars on the viewport.

get the height of the previous element

Can i get the height of the previous element using only CSS?
I am using calc() function to set dynamically height of the div B.
#b{
height:calc(100vh - heightOfPreviousElement);
}
I need to know the height of the previous element.
what i know is that, 100vh is equal to 100% of the screen height.
I used the code in the answer below.Using flex,
I have one problem. The height of the color orange become smaller.
You can easily achieve the effect you're looking for using flexbox. The trick is to allow the blue container (the one with the flexible height) to grow in size whenever the need arises, using flex: 1 1 auto, which is simply a shorthand for:
flex-grow: 1;
flex-shrink: 1;
flex-basis: auto;
See proof-of-concept code snippet below:
body {
padding: 0;
margin: 0;
}
.wrapper {
display: flex;
flex-direction: column;
flex-wrap: no-wrap;
align-items: center;
justify-content: center;
height: 100vh;
}
.wrapper > div {
width: 100%;
}
#c1 {
background-color: #880015;
color: #fff;
height: 60px;
margin-bottom: 10px;
}
#c2 {
background-color: #ff7f27;
}
#c3 {
background-color: #00a2e8;
flex: 1 1 auto;
margin-bottom: 10px;
}
<div class="wrapper">
<div id="c1">height: 60px</div>
<div id="c2">height: auto (determined by content?)</div>
<div id="c3">flexible height</div>
</div>
No you can't select a previous element in CSS.
You might be interested in JQuery Prev OR Parents method for selecting previous element and apply height using .css() method?