Blacksad
Blacksad

Reputation: 15422

Rotate and scale image to "fit" container div

I'm using transform to rotate an image according to its EXIF data. Then, I'd like to display it "full screen" by fitting it to its parent div.

The problem is, max-width / max-height and all other sizing directives "ignore" the rotation (which is normal, according to transform specs, the element's transformation is "ignored" in the flow.

Jsfiddle: http://jsfiddle.net/puddjm4y/2/

div.top {
    position: fixed;
    width: 100%;
    height: 100%;
    border: 1px solid blue;
}
img {
    transform: rotate(90deg);
    max-width: 100%;
    max-height: 100%;
}
<div class="top">
    <img src="http://www.androidpolice.com/wp-content/uploads/2014/02/nexusae0_wm_DSC02232.jpg">
</div>

Is there a way to achieve this?

Upvotes: 28

Views: 22686

Answers (9)

george
george

Reputation: 1

make a copy of source image, rotate it, source the rotated image?

Upvotes: 0

user7148391
user7148391

Reputation:

Make the height of an element equal it's width and vice versa, is a Javascript thing, since it can retrieve those values and set them back.

In CSS there's no way of accomplishing that, and also not possible with dynamic dimensions, we don't know what 100% would equal to exactly, and even if we did we wouldn't be able to use them, because there's no reference to them.

However if you would go with fixed values, that can be manipulated with media queries, then why not use variables, this way we have the value, and a reference to it.

:root {
  --width: 100px;
  --height: 140px;
}

div.top {
  position: fixed;
  width: var(--width);
  height: var(--height);
  border: 1px solid blue;
}

img {
  width: var(--width);
  height: var(--height);
  animation: rotate 3s alternate infinite;
}


/* translate values are the difference between the height */
/* and width divided between the X and Y */
/* 100 - 140 = 40 / 2 = 20px each */

@keyframes rotate {
  to {
    transform: rotate(90deg) translate(20px, 20px);
    width: var(--height);
    height: var(--width);
  }
}
<div class="top">
  <img src="http://www.androidpolice.com/wp-content/uploads/2014/02/nexusae0_wm_DSC02232.jpg">
</div>

Then again, this is just an idea.

Upvotes: 3

Travis Unangst
Travis Unangst

Reputation: 21

I finally found the answer to what I needed for this problem, maybe it will help someone else. I have a flex parent and the child I needed to be rotated based on EXIF. I needed image-orientation: from-image;

imgBox {
    flex: 1;
    padding: 1rem;
    overflow: hidden;
 }

 .img1 {
     object-fit: cover;
     max-width: 100%;
     image-orientation: from-image;
 }

Upvotes: 2

Darren Cooney
Darren Cooney

Reputation: 1060

You could do this in JavaScript by checking the container height and setting the maxWidth of the image to the height of the container.

 /**
 * Set max width of a rotated image to container height
 * @param {*} container
 * @param {*} image
 */
function setRotatedImageWidth(container = null, image = null) {
    if (!container || !image) {
        return false; // exit if empty
    }
    var h = container.offsetHeight; // Container height
    var w = image.offsetWidth; // Image width

    // If image width is greater container height
    if (w > h) {
        image.style.maxWidth = h + 'px';
    }
}

var container = document.querySelector('.container');
var image = container.querySelector('img');
setRotatedImageWidth(container, image);

Upvotes: 1

Salman Arshad
Salman Arshad

Reputation: 272106

For full screen display, the simplest solution is to use viewport units to specify width and height of images:

  • Normal image should be 100vw wide and 100vh tall
  • Rotated image should be 100vh wide and 100vw tall

The image could be moved to the middle using CSS transformations. Here is an example, it uses two images that are larger and smaller than the viewport:

body {
  margin: 0;
}
img {
  display: block;
}
img.normal {
  max-width: 100vw;
  max-height: 100vh;
  transform: translatex(calc(50vw - 50%)) translatey(calc(50vh - 50%));
}
img.rotated {
  max-width: 100vh;
  max-height: 100vw;
  transform: translatex(calc(50vw - 50%)) translatey(calc(50vh - 50%)) rotate(90deg);
}
/* demo */
.demo {
  height: 100vh;
  position: relative;
}
.demo:nth-child(odd) {
  background-color: #CCC;
}
.demo:nth-child(even) {
  background-color: #EEE;
}
.demo::after {
  content: attr(title);
  position: absolute;
  left: 0;
  top: 0;
  padding: .25em .5em;
  background-color: rgba(255, 255, 255, .8);
}
<div class="demo" title="Large image, normal"><img class="normal" src="https://i.sstatic.net/2DdPE.jpg"></div>
<div class="demo" title="Large image, rotated"><img class="rotated" src="https://i.sstatic.net/2DdPE.jpg"></div>
<div class="demo" title="Small image, normal"><img class="normal" src="https://i.sstatic.net/ustNQ.jpg"></div>
<div class="demo" title="Small image, rotated"><img class="rotated" src="https://i.sstatic.net/ustNQ.jpg"></div>

Upvotes: 14

vssadineni
vssadineni

Reputation: 454

If you could ignore the transform part as it is a question of aspect ratio and there is no answer for it, but displaying an image to 100% of the parent element is possible and will not be needing any media queries to it. 100 percent is relative to the parent and with images it is the aspect ratio that rules the dimensions. we can stretch it but that will not serve the purpose. Hope below css might help you in some way.

div.top {
    position: fixed;
    width: 100%;
    height: 100%;
    border: 1px solid blue;
    background-image:url("http://www.androidpolice.com/wp-content/uploads/2014/02/nexusae0_wm_DSC02232.jpg");
    background-size:cover;
    background-repeat:no-repeat;
    background-position:50%;
}
div.top img {
    /* transform: rotate(90deg); */
    min-width: 100%;
    min-height: 100%;
    visibility:hidden;
}

Upvotes: 0

Maciej Kwas
Maciej Kwas

Reputation: 6419

I would probably go for something like this (swapped max-width/height using viewport sizing)

* {
  box-sizing:border-box;
}

html, body {
  margin:0;
}

div.top {
    position: fixed;
    width: 100%;
    height: 100%;
    top:0;
    left:0;
    border: 1px solid blue;
    display:flex;
}
img {
    transform: rotate(90deg);
    max-width: 100vh;
    max-height: 100vw;
    margin:auto;
}
<div class="top">
    <img src="http://www.androidpolice.com/wp-content/uploads/2014/02/nexusae0_wm_DSC02232.jpg">
</div>

Upvotes: 2

Rafael
Rafael

Reputation: 7746

Here's a scant attempt that requires manually syncing the width / height. For those who are willing to use JS, that should be fairly easy to sync.

Here it is:

div.top {
    border: 1px solid blue;
    box-sizing: border-box;
    width: 100%;
    height: 300px;/* SYNC */
    position: relative;
    overflow: hidden;
}

div.top:before {
  content: "";
  position: absolute;
  width: 300px;/* SYNC */
  height: 100%; 
  transform: rotate(90deg);
  background-image: url(http://www.androidpolice.com/wp-content/uploads/2014/02/nexusae0_wm_DSC02232.jpg);
  background-size: contain;
  background-repeat: no-repeat;
}
<div class="top"></div>

Positioning becomes awkward. However, my hope is that someone will branch from here and conjure a better solution.

Upvotes: 0

Dexter0015
Dexter0015

Reputation: 1039

For the exif part you can't do it with css as css ins't able to ready exif datas.

For the CSS part though, you need to use transform-origin, not just transform and also use width 100% and heigh auto to keep ratio.

Here is an exemple : http://jsfiddle.net/yxqgt2d1/1/

Upvotes: -2

Related Questions