Skip to content Skip to sidebar Skip to footer

Css Resizable Images With Header

I'm trying to get an HTML layout of two images that are shown side-by-side, and fill the page while maintaining their aspect ratio and keeping the images next to each other (i.e. N

Solution 1:

Firstly, you can set max-width: 100%; and height: auto; on the image tags instead of hardcoding the height and max-widths on each image.

Then you can set top: 40px; on the .halfContainer divs to make the container start 40 pixels down.

Finally, set the max-height of the images to calc(100vh - 40px); so that they will always be the height between the header and the bottom of the page. top: 0; and bottom: 0; will then then make sure the images are lined up properly with the top and bottom of the container.

* {
  margin: 0;
  padding: 0;
  /* Fix CSS. */box-sizing: border-box;
}
body {
  margin: 20px;
}
html {
  background-color: #f4f4f6;
}
.halfContainer {
  width: 50vw;
  margin: auto;
  padding: 0;
  top: 40px;
  bottom: 0;
  position: absolute;
}
#leftContainer {
  left: 0;
}
#rightContainer {
  right: 0;
}
img {
  max-width: 100%;
  height: auto;
}
#leftImage {
  max-height: calc(100vh - 40px);
  margin: auto;
  position: absolute;
  top: 0;
  bottom: 0;
  right: 5%;
  /* Padding */
}
#rightImage {
  max-height: calc(100vh - 40px);
  margin: auto;
  position: absolute;
  top: 0;
  bottom: 0;
  left: 5%;
}
#instructions {
  margin: auto;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
}
<center><h1id="instructions">Choose an image.</h1></center><divid="leftContainer"class="halfContainer"><imgid="leftImage"src="http://www.washingtonpost.com/news/morning-mix/wp-content/uploads/sites/21/2014/09/Grumpy_Cat_Endorsement-017d7-ULFU.jpg" /></div><divid="rightContainer"class="halfContainer"><imgid="rightImage"src="http://upload.wikimedia.org/wikipedia/commons/2/22/Turkish_Van_Cat.jpg" /></div>

Solution 2:

I refactored your code to come up with this solution. This makes use of the background-image and background-size properties to size the images. I also moved away from vh and vw for sizing of other elements but you can change that back in .wrapper. The benefit is that it is a pure CSS solution; no JS. With a little tinkering it should fit your needs. Let me know if there are any concerns.

* { margin:0; padding:0; box-sizing:border-box; }
body { margin:20px; height:calc(100% - 40px); width:calc(100% - 40px); }
html { height:100%; width:100%; }

.wrapper { position:relative; height:100%; width:100%; background-color: #f4f4f6; }
.title { text-align:center; height:2.4em; overflow:hidden; }

.left, .right { padding:15px; height:calc( 100% - 2.4em); width:50%; position:absolute; }
.left.imgCanvas, .right.imgCanvas { width:100%; height:100%; background-repeat:no-repeat; background-size:contain;  }

.left { right:50%; }
.left.imgCanvas { float:right; background-position:right;}
.right { left:50%;  }
.right.imgCanvas { float:left; background-position:left; }
<divclass="wrapper"><divclass="title"><h1>Choose an image</h1></div><divclass="left"><divclass="imgCanvas"style="background-image:url('http://placekitten.com/g/500/3000')"></div></div><divclass="right"><divclass="imgCanvas"style="background-image:url('http://placekitten.com/g/3000/500')"></div></div></div>

Solution 3:

You can give yourself more control over how your photos resize, and make your HTML and CSS a lot simpler if you use background-image for this (and it works in IE9) – here is how:

Step 1 - Break this into smaller problems

Right now you are trying to position two different images, while taking their surroundings into account. Lets break that into two simpler problems by putting your images inside a <div> that I will call #displayArea. This way we can solve the placement of the #displayArea separately from solving the placement of the images.

So now we are trying to solve to easier problems:

  1. Make our #displayArea - it should take up as much of the screen as possible without covering up the header at the top
  2. Inside #displayArea place two images that are shown side-by-side, and fill the page while maintaining their aspect ratio and keeping the images next to each other

Step 2 - make our #displayArea

We want #displayArea to take up as much space as possible. Lets start with width. In your css you set your .halfContainer to have widths of 50vw, but you also set your body to have 20px of margin - that means if we made our #displayArea100vw wide, the whole page would end up being 100vw + 40px wide because of the left and right margins.

To allow you to change your page margins in the future without having to update your other css, I suggest you make your #displayArea fill all of the available space by setting its width to 100%.

Next we need to set the #displayArea height. There are many ways to do this, but they all fall into two categories - ones that allow your header to have a dynamic height, and ones where it has a fixed height. I will assume that a fixed height for the header is ok, but do know that you will need a different solution if you want your header to have a dynamic height (such as allowing the text in it to wrap).

If we assume a fixed height, lets say of 40px, then using CSS calc() we can set the height of #displayArea to be the height of the view port minus the header area and minus the body margin. It will look like this:

height: calc(100vh - 40px - 40px) /* 40px header, 40px for 2x20px top/bottom margin */

Step 3 - Make the two images

Because we've already done some hard work setting up #displayArea, this step is pretty straight forward. While we can certainly make this work with the HTML you provided, I want to recommend you consider using background-image for this project. The amount of control css gives you on exactly how background images appear can save you a lot of time and trouble - for instance, when these images get small due to the browser window shrinking, do you want them to be vertically centered, or always as high up as possible? Easy to do with css background-image.

In my code below I use a class .half so the image divs can share styles. I then use their unique ids to set the specific image I want each of them to have.

Here is the finished CSS and HTML (note how simple the HTML is now).

*
{
    margin: 0;
    padding: 0;
	/* Fix CSS. */box-sizing: border-box;
}

body
{
	margin: 20px;
}

html
{
	background-color: #f4f4f6;
}

#instructions {
  height: 40px;
}

#displayArea {
  height: calc(100vh - 40px - 40px); /* 40px header, 40px for 2x20px top/bottom margin */width: 100%;
  margin: 0;
  padding: 0;
}

.half {
  float: left;
  width: 50%;
  margin: 0;
  height: 100%;
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center top;
}

#leftImg {
  background-image: url(http://www.washingtonpost.com/news/morning-mix/wp-content/uploads/sites/21/2014/09/Grumpy_Cat_Endorsement-017d7-ULFU.jpg);
  background-position: right top;
}

#rightImg {
  background-image: url(http://upload.wikimedia.org/wikipedia/commons/2/22/Turkish_Van_Cat.jpg);
  background-position: left top;
}
<center><h1id="instructions">Choose an image.</h1></center><divid="displayArea"><divid="leftImg"class="half"></div><divid="rightImg"class="half"></div></div>

Solution 4:

I know you've already selected an answer, but I wanted to give you this option anyways.

Because you are using vh and vw measurements but not defining a header height, what you're asking to do is currently impossible without utilizing JavaScript to dynamically detect the size of the header to resize the columns. At that point, you might as well just use JavaScript to handle it and forget the viewport units.

Having said that, here is a JavaScript solution that will render the content, I believe, exactly how you want it rendered:

window.onload = function() {
    window.left = document.getElementById("leftImage"),
   window.right = document.getElementById("rightImage"),
    window.head = document.getElementById("instructions"),
   window.leftW = parseInt(window.getComputedStyle(left, null).getPropertyValue('width')),
  window.rightW = parseInt(window.getComputedStyle(right, null).getPropertyValue('width')),
   window.leftH = parseInt(window.getComputedStyle(left, null).getPropertyValue('height')),
  window.rightH = parseInt(window.getComputedStyle(right, null).getPropertyValue('height'));

console.log(leftW);
    resize(leftW, rightW, leftH, rightH);
}

window.onresize = function() {
    resize(leftW, rightW, leftH, rightH);
}

functionresize(leftW, rightW, leftH, rightH) {
    var winW = window.innerWidth,
      hcPadW = (winW * .025 * 2),
        winH = window.innerHeight,
      hcPadH = (winH * .025 * 2),
        colW = (winW / 2),
        colH = (winH - parseInt(window.getComputedStyle(head, null).getPropertyValue('height'))),
        colR = ((colW - hcPadW) / (colH - hcPadH)),
       leftR = (leftW / leftH),
      rightR = (rightW / rightH);
    
    if(colR < leftR) {
        left.style.width = (colW - hcPadW) + 'px';
        left.style.height = (((colW - hcPadW) * leftH) / leftW) + 'px';
    } else {
        left.style.height = (colH - hcPadH) + 'px';
        left.style.width = (((colH - hcPadH) * leftW) / leftH) + 'px';
    }
    
    if(colR < rightR) {
        right.style.width = (colW - hcPadW) + 'px';
        right.style.height = (((colW - hcPadW) * rightH) / rightW) + 'px';
    } else {
        right.style.height = (colH - hcPadH) + 'px';
        right.style.width = (((colH - hcPadH) * rightW) / rightH) + 'px';
    }
}
* {
    margin: 0;
    padding: 0;
}

html, body {
    height: 100vh;
}

#wrapper {
    height: 100vh;
    background-color: #dedede;
    display: table;
}

#instructions, .hidden {
    display: table-row;
}

.hidden {
    visibility: hidden;
}

#instructions {
    text-align: center;
    background-color: #9a9a9a;
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
}

#cols {
    display: table-row;
}

.halfContainer {
    display: table-cell;
    width: 50vw;
    height: 100%;
    padding: 2.5vh2.5vw;
    vertical-align: middle;
}

#leftContainer {
    background-color: #797979;
    text-align: right;
}
<divid="wrapper"><divclass="hidden"><h1>Choose an image.</h1></div><divid="instructions"><h1>Choose an image.</h1></div><divid="cols"><divid="leftContainer"class="halfContainer"><imgid="leftImage"src="http://www.washingtonpost.com/news/morning-mix/wp-content/uploads/sites/21/2014/09/Grumpy_Cat_Endorsement-017d7-ULFU.jpg"class="image" /></div><divid="rightContainer"class="halfContainer"><imgid="rightImage"src="http://upload.wikimedia.org/wikipedia/commons/2/22/Turkish_Van_Cat.jpg"class="image" /></div></div></div>

JSFiddle: http://jsfiddle.net/rLuf9zso/

Here's a bit more simplified of a route, minimizing the JavaScript to an absolute minimum:

window.onload = function() {
    var mH = document.getElementsByClassName('image');
    for(var i = 0; i < mH.length; i++) {
        mH[i].style['maxHeight'] = 'calc(94vh - ' + parseInt(window.getComputedStyle(document.getElementById('instructions'), null).getPropertyValue('height')) + 'px)';
    }
}
* {
    margin: 0;
    padding: 0;
}

html, body {
    height: 100vh;
}

#wrapper {
    height: 100vh;
    display: table;
}

#instructions, .hidden {
    display: table-row;
}

.hidden {
    visibility: hidden;
}

#instructions {
    text-align: center;
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
}

#cols {
    display: table-row;
}

.halfContainer {
    display: table-cell;
    width: 50vw;
    height: 100%;
    padding: 2.5vh2.5vw;
    vertical-align: middle;
}

#leftContainer {
    text-align: right;
}

.image {
    min-height: 0;
    min-width: 0;
    max-width: 40vw;
    margin: auto;
}
<divid="wrapper"><divclass="hidden"><h1>Choose an image.</h1></div><divid="instructions"><h1>Choose an image.</h1></div><divid="cols"><divid="leftContainer"class="halfContainer"><imgid="leftImage"src="http://www.washingtonpost.com/news/morning-mix/wp-content/uploads/sites/21/2014/09/Grumpy_Cat_Endorsement-017d7-ULFU.jpg"class="image" /></div><divid="rightContainer"class="halfContainer"><imgid="rightImage"src="http://upload.wikimedia.org/wikipedia/commons/2/22/Turkish_Van_Cat.jpg"class="image" /></div></div></div>

JSFiddle: http://jsfiddle.net/18ynkzd0/

The primary difference between the two is going to be compatibility. The first one, with the more extensive JavaScript, will be compatible in most major browsers going back several versions, whereas the second one follows your original scheme of ignoring browsers like IE 8/9, and Android 4.1/.3.

Something else to remember about these options is that the height of the header may be retrieved from div#instructions, but the positioning on the images isn't affected by it. Since the header was positioned, it's height won't affect the rendering on the image positions. To compensate, I added div#hidden with identical values/CSS and set its visibility to hidden. This will add the height needed inline without displaying it. If you change the displayed header, make sure you update the hidden div to match.

I hope this helps. ^^

Solution 5:

Ok, slightly different answer now. I added the following to your code:

@media (max-height: 500px) {
    .halfContainer {
        top: 100px;
        overflow: auto;
    }
}

This will push down the images as soon as the screen-height gets below 200px. Overflow on auto wil disallow scrolling. You'll probably see less of the images.

*
{
    margin: 0;
    padding: 0;
	/* Fix CSS. */box-sizing: border-box;
}

body
{
	margin: 20px;
}

html
{
	background-color: #f4f4f6;
}

.halfContainer
{
    width: 50vw;
    height: 100vh;
    margin: auto;
    padding: 0;
    top: 0;
    bottom: 0;
    position: absolute;
}

@media (max-height: 500px) {
    .halfContainer {
        top: 100px;
        overflow: auto;
    }
}

#leftContainer
{
    left: 0;
}

#rightContainer
{
    right: 0;
}

/* AR is height/width. */#leftImage
{
    /* Set to half width, minus padding. 50-padding = 45 */width: 45vw; 
	/* Multiply by aspect ratio. 45 * AR = ... *//*height: 35vw;*//* Clip by height if necessary, minus padding. 100-padding*2 = 90 */max-height: 90vh;
	/* Divide by aspect ratio. 90 / AR = ... *//*max-width: 140vh; */margin: auto;
    position: absolute;
    top: 0;
    bottom: 0;
    right: 5%; /* Padding */
}


#rightImage
{
    /* Set to half width, minus padding. 50-padding = 45 */width: 45vw; 
	/* Multiply by aspect ratio. 45 * AR = ... *//*height: 35vw;*//* Clip by height if necessary, minus padding. 100-padding*2 = 90 */max-height: 90vh;
	/* Divide by aspect ratio. 90 / AR = ... *//*max-width: 140vh;*/margin: auto;
    position: absolute;
    top: 0;
    bottom: 0;
    left: 5%;
}

#instructions
{
	margin: auto;
	position: absolute;
	top: 0;
	left: 0;
	right: 0;
}
<!DOCTYPE html><htmllang="en"><head><metacharset="utf-8"><title></title></head><body><center><h1id="instructions">Choose an image.</h1></center><divid="leftContainer"class="halfContainer"><imgid="leftImage"src="http://www.washingtonpost.com/news/morning-mix/wp-content/uploads/sites/21/2014/09/Grumpy_Cat_Endorsement-017d7-ULFU.jpg"style="height: 33.70vw; max-width: 120.15vh;"/></div><divid="rightContainer"class="halfContainer"><imgid="rightImage"src="http://upload.wikimedia.org/wikipedia/commons/2/22/Turkish_Van_Cat.jpg"style="height: 49.41vw; max-width: 81.95vh;"/></div></body></html>

Post a Comment for "Css Resizable Images With Header"