William Larsen Bang
William Larsen Bang

Reputation: 197

Keep div centered with keeping aspect ratio and resizing vertically or horizontally

I can find multiple half solutions, but I am looking for a complete solution to my issue. I have a div that I would like to be centered in the screen with a fixed aspect ratio, that div should in essence always be completely visible, so that div is always the largest it can be whilst keeping the aspect ratio. regardless of resizing the window vertically and horizontally.

There is a codepen here: https://codepen.io/william-bang/pen/ZjyWRd

That I created, this only solves the issue horizontally but not vertically. I have managed to get it working with and but sizing behaves differently for that. I am looking for a CSS solution, although I am open to a JS solution, if anyone is absolutely sure that no solution exists.

body {
  width: 100%;
  height: 100%;
}

.wrapper {
  width: 40%;
  height: 100%;
  margin: auto
}

.img {
  padding-top: 50%;
  width: 100%;
  background: #ccc;
  text-align: center;
}
<div class="wrapper">

  <div class="img">
    **IMG HERE**
  </div>
  
</div>

I would be grateful for any suggestions, this has had me stumped for many hours. thanks in advance :)

Update, the div needs to maintain its aspect ratio on a varying page and at all times be its own maximum size.

@Grenther Thanks for your response, I tried modifying the answer you gave to do it purely in CSS and not having to use a CSS preprocessor. That went really well, until I realized that CSS media queries does not support standard CSS variables, otherwise the method you proposed would have been possible without SCSS but perhaps you already knew that.

:root {
  --ogW: 1600;
  --ogH: 900;
  --ratio: calc( var(--ogW) / var(--ogH));
}

 body {
  width: 100%;
  height: 100%;
}

.ratio {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  
  @media screen and (max-width: 177vh) {
    width: 90vw; 
    height: calc( 90vw / var(--ratio)); 
  } 

  @media screen and (min-width: 177vh) {
    width: calc( 90vh * var(--ratio));  
    height: 90vh;
  }

}

.div {
  width: 100%;
  height: 100%;
  background: red;
  text-align: center;
}
<div class="ratio">

  <div class="div">
    
    Hello!
    
  </div>
  
</div>

Upvotes: 3

Views: 1216

Answers (3)

Rylee
Rylee

Reputation: 1656

See the below code snippet. As you adjust the wrapper width, the img will scale to fit while maintaining it's aspect ratio

The img will also be vertically centered and horizontally within the .wrapper element

* {
  box-sizing:border-box;
}

html,
body {
  width: 100%;
  height: 100%;
}

.wrapper {
  width: 50%;
  height: 100%;
  margin: auto;
  position: relative;
}

.img {
  max-width: 100%;
  max-height: 100%;
  padding:20px 40px;
  background:grey;
  position: absolute;
  top: 50%;
  left: 0;
  right: 0;
  height: fit-content;
  width: fit-content;
  margin: auto;
  transform: translateY(-50%);
}

.img img {
  max-width: 100%;
  height: auto;
  max-height: 100%;
}
<div class="wrapper">
  <div class="img">
    <img src="https://cdn.pixabay.com/photo/2013/01/29/00/47/search-engine-76519_960_720.png">
  </div>
</div>

Upvotes: 1

Grenther
Grenther

Reputation: 476

Final Update:

It turned into a SCSS question, with any input for variable width or height it can be done like this:

http://jsfiddle.net/832v5f0L/41

 $div-width : 1600;
 $div-height : 900;

 $ratio: $div-width / $div-height;

  @media screen and (max-width: (100 * $ratio) + vh) {
    width: 100vw; // always 100vw to fill
    height: (100 / $ratio) + vw; // 100 / ratio
  }

  @media screen and (min-width: (100 * $ratio) + vh) {
    width: (100 * $ratio) + vh;  //100 * ratio
    height: 100vh; // always 100vh to fill
  }

Updated answer:

Media query portrait automatically activates when width is smaller than height. Which makes sure we can use the vh and vw to obtain the maximum possible size without reaching an overflow.

The ratio between the width and height will make sure you can get a fixed aspect ratio.

    body {
  width: 100%;
  height: 100%;
}
.wrapper {
  position: absolute;
  left: 50%;
  top: 50%;
  -webkit-transform: translate(-50%, -50%);
  transform: translate(-50%, -50%);
}

/* 
100vh * (100 / height) 
with hright 50:
100vh * 100 / 50 = 200vh
*/

@media screen and (max-width: 200vh) {
  .wrapper {
      width: 100vw;
      height: 50vw;
  }
}
@media screen and (min-width: 200vh) {
  .wrapper {
      width: 200vh;
      height: 100vh;
  }
}

.img {
/*   padding-top: 50%; */
  width: 100%;
  height: 100%;
  background: #ccc;
  text-align: center;
  background-img: url()
}
<div class="wrapper">

  <div class="img">
    **IMG HERE**
  </div>
  
</div>

Update: min - max width queries

Upvotes: 3

joshmoto
joshmoto

Reputation: 5088

This is a great question, I've been trying for ages to solve but getting it to resize on a vertical height with out using flex was proving a hard task.

But @Grenther answer seems to actually work without using an image. His 1x2 ratio div stays true when adjusting the window width and height.

I then modified his code so that there is a max-height and max-width on the div. I could only get this to work with his 200px x 400px ratio.

It would be awesome if @Grenther could update my jsfiddle code so what ever div size/ratio variable is set, his clever vh method sizes would adjust using sass math so that any set div size would work. Even I'm struggling to see how his version works. But if the math is in the sass code for each vh dimension, we might be able to understand his wizardry.

@Grenther version here: https://jsfiddle.net/joshmoto/jndmoz6v/

 /* div size vars and div ratio3 */
 $div-width : 400;
 $div-height : 200;

 body {
  width: 100%;
  height: 100%;
}

.ratio {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);

  /* set your div max-size here  */
  max-width: $div-width + px;
  max-height: $div-height + px;

  @media screen and (max-width: 200vh) {
    width: 100vw;
    height: 50vw;

  }

  @media screen and (min-width: 200vh) {
    width: 200vh;
    height: 100vh;

  }

}

.div {
  width: 100%;
  height: 100%;
  background: red;
  text-align: center;

}

I know this is not sass question, but i'm just using this so we can see @Grenther's answer logic.


I tried the math myself but when I change the div sizes/ratio it does not work like his version.

See my fail: https://jsfiddle.net/joshmoto/Lkebpyws/

$div-width : 400;
$div-height : 200;

.ratio {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);

  /* set your div max-size here  */
  max-width: $div-width + px;
  max-height: $div-height + px;

  @media screen and (max-width: $div-height + 'vh') {
    width: ($div-width / 4) + vw;
    height: ($div-height / 4) + vw;

  }

  @media screen and (min-width: $div-height + 'vh') {
    width: ($div-width / 2) + vh;
    height: ($div-height / 2) + vh;

  }

}

...

Upvotes: 0

Related Questions