0

I am working on a Christmas gift website and have just two elements on it, which I want to have like this:

The bottom element is an image, which should be aligned to the bottom of the viewport. It should be resized proportionally and take maximum 90% of the viewport width and maximum 70% of the viewport height. The upper element is a text element and I want it to fill the remaining vertical space and align that text to the center horizontally and vertically.

In the case, if the bottom element takes 70vh, the solution is easy, the upper element should take 30vh. But If the bottom element is smaller, the height of the upper box should be (view port height - upper element height).

This is what I have so far.

body { 
    background-image: url('https://i.imgur.com/sWfZ8nq.png');
    background-repeat: repeat;
}

.fg {
    margin: auto;
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    max-height: 100%;
}

.fg div {
    display: flex;
    align-items: center;
    position: absolute;
    width: 100%;
    height: 100%;
    max-height: 30%;
}

.fg span {
    width: 100%;
    text-align: center;
    color: white;
    font-size: 10vmin;
    letter-spacing: 3px;
    text-shadow:  2px  2px 2px green,
                  2px -2px 2px green,
                 -2px  2px 2px green,
                 -2px -2px 2px green;
}

.fg img {
    position: absolute;
    bottom: 0;
    left: 50%;
    transform: translateX(-50%);
    max-height: 70%;
    max-width: 90%;
}
<html>
  <head>
    <title>HNY</title>
    <meta charset="utf-8">
  </head>
  <body>
    <div class="fg">
      <div>
        <span>Happy new year!</span>
      </div>
      <img src="https://i.imgur.com/Ql8A585.png"/>
    </div>
  </body>
</html>

That works fine for bottom element height = 70vh, for example for resolution 1920 x 1080. But if I flip it, i.e. switch to 1080 x 1920, the upper box takes only 30vh, but i want it to fill the space. Any suggestions?

Danny Lo
  • 1,553
  • 4
  • 26
  • 48
  • Sorry, that was an incorrect duplicate but you can still use flex box for this – Pete Dec 20 '18 at 10:12
  • [something like this?](http://jsfiddle.net/7hkfmayx/1/) – Pete Dec 20 '18 at 10:18
  • it doesn't look right with my image: http://jsfiddle.net/7hkfmayx/2/ – Danny Lo Dec 20 '18 at 10:27
  • Yeah it uses object fit to resize the image but keep it's aspect ratio. If you are wanting to keep the full image you can try using `contain` instead of cover: http://jsfiddle.net/7hkfmayx/3/ (but if you use this you will need a polyfill for ie) – Pete Dec 20 '18 at 10:28
  • Your solution doesn't align the bottom element to the bottom of the viewport (sorry, I forgot to mention it in my question). Apart from that, your image box has a static height of 70vh, but I want it to be variable, with a constraint of max 70vh https://i.imgur.com/0o9jk81.png – Danny Lo Dec 20 '18 at 10:51
  • Think you may need a bit of js then to calculate whether or not your image is landscape or portrait and add a class accordingly – Pete Dec 20 '18 at 11:12

2 Answers2

0

I made .fg a flexbox as well, which got rid of the need to absolutely position the image. I wrapped the image in a div so that it scales while preserving it's aspect ratio, when the div enlarges due to flex-grow: 1;

body { 
    margin: 0;
    background-image: url('https://i.imgur.com/sWfZ8nq.png');
    background-repeat: repeat;
    font-size: 0;
}

* {
    box-sizing: border-box;
}

.fg {
    display: flex;
    flex-direction: column;
    align-items: center;
    width: 100vw;
    height: 100vh;
}

.fg .text {
    display: flex;
    align-items: center;
    flex-basis: 0;
    flex-grow: 1;
    flex-shrink: 1;
}

.fg span {
    color: white;
    font-size: 10vmin;
    letter-spacing: 3px;
    text-shadow:  2px  2px 2px green,
                  2px -2px 2px green,
                 -2px  2px 2px green,
                 -2px -2px 2px green;
}

.fg .img {
    flex-basis: 0;
    flex-grow: 1;
    flex-shrink: 0;
    max-height: 70%;
    max-width: 90%;
}

@media (orientation: landscape) {
    img {
        height: 100%;
    }
}

@media (orientation: portrait) {
    img {
        width: 100%;
    }
}
<html>
  <head>
    <title>HNY</title>
    <meta charset="utf-8">
  </head>
  <body>
    <div class="fg">
      <div class="text">
        <span>Happy new year!</span>
      </div>
      <div class="img">
          <img src="https://i.imgur.com/Ql8A585.png" />
      </div>
    </div>
  </body>
</html>
  • Your solution unfortunately doesn't fulfill my requirement, i.e. the upper box doesn't fill the vertical space https://i.imgur.com/6AJRRcw.png – Danny Lo Dec 20 '18 at 10:38
  • Oops, forgot to remove the `max-height: 30%;` I'll update it. –  Dec 20 '18 at 10:43
  • Now the image overlaps the text :) – Danny Lo Dec 20 '18 at 10:47
  • 1
    I noticed... I'm going to give this another look. See if I can figure out what exactly is going on. –  Dec 20 '18 at 10:48
  • Alright @DannyLo I'm positive this one works, the scrollbars are due to it being in an iframe, opened it locally in Chrome and there are no issues. –  Dec 20 '18 at 11:07
  • Thank you very much for your effort, but your solution works fine only for certain viewport ratios. The maximum resolution, on which it works is approx. 1360 x 1928. If you decrease the width or increase the height, the positioning doesn't look fine anymore. I.e. 1920x1080 looks fine, but 1080x1920 doesn't. https://i.imgur.com/T0ltRwh.png I use device toolbar of chrome's devtools for that. – Danny Lo Dec 20 '18 at 12:30
  • Should be working properly on portrait as well, I just added some media rules which switch the scaling of the image by using width instead of height. Also got rid of the vertical scrollbar introduced by having font-sizes on non text elements. –  Dec 20 '18 at 13:40
  • Almost perfect... but it still doesn't work for all resolutions https://i.imgur.com/DoMT94V.png ` I think `div.img` should take less vertical space in that case – Danny Lo Dec 20 '18 at 15:00
0

I used grid css for this. I set .fg to 100vh and the body margin to 0 to avoid the overflow problem. Because you needed the upper to repond to the img size, I set the grid rows to: grid-template-rows: 1fr auto;, meaning the top half of the grid takes the remaining space. Also changed the image position to relative to get it working with grid.

body { 
    background-image: url('https://i.imgur.com/sWfZ8nq.png');
    background-repeat: repeat;
    margin: 0;
}

.fg {
    display: grid;
    grid-template-rows: 1fr auto;
    margin: auto;
    height: 100vh;
}

.fg div {
    display: flex;
    align-items: center;
    width: 100%;
    height: 100%;
}

.fg span {
    width: 100%;
    text-align: center;
    color: white;
    font-size: 10vmin;
    letter-spacing: 3px;
    text-shadow:  2px  2px 2px green,
                  2px -2px 2px green,
                 -2px  2px 2px green,
                 -2px -2px 2px green;
}

.fg img {
 position: relative;
 bottom: 0;
 left: 50%;
 transform: translateX(-50%);
 max-height: 70vh;
 max-width: 90vw;
}
<html>
  <head>
    <title>HNY</title>
    <meta charset="utf-8">
  </head>
  <body>
    <div class="fg">
      <div>
        <span>Happy new year!</span>
      </div>
      <img src="https://i.imgur.com/Ql8A585.png"/>
    </div>
  </body>
</html>