I am trying to rotate an image using a CSS
transform such that it stays correctly aligned within the surrounding div
, i.e. the top left corner of the image should be aligned with the top left corner of the div
.
As you can see here (-> click on [rotate]
) this does not work. Is there a way to fix this?
(Note that I'd be using this in an online image viewer so I cannot hardcode an offset for the rotated image. There's a lot of similar questions but I haven't found this exact question.)
If you want it to be done in CSS, this is the way:
.rot90 {
-webkit-transform: translateY(-100%) rotate(90deg); /* Safari */
-moz-transform: translateY(-100%) rotate(90deg); /* Firefox 3.6 Firefox 4 */
/*-moz-transform-origin: right top; */
-ms-transform: translateY(-100%) rotate(90deg); /* IE9 */
-o-transform: translateY(-100%) rotate(90deg); /* Opera */
transform: translateY(-100%) rotate(90deg); /* W3C */
-webkit-transform-origin: left bottom;
-moz-transform-origin: left bottom;
-ms-transform-origin: left bottom;
-o-transform-origin: left bottom;
transform-origin: left bottom;
}
updated demo
The trick is to rotate the image around the left bottom corner. Once done, it is down by 100% of the height; translate it and now it is ok.
To get the same effect for the inverse rotation: (hover to transform)
div:hover #myimage {
-webkit-transform: translateX(-100%) rotate(-90deg); /* Safari */
-moz-transform: translateX(-100%) rotate(-90deg); /* Firefox 3.6 Firefox 4 */
-ms-transform: translateX(-100%) rotate(-90deg); /* IE9 */
-o-transform: translateX(-100%) rotate(-90deg); /* Opera */
transform: translateX(-100%) rotate(-90deg); /* W3C */
-webkit-transform-origin: top right;
-moz-transform-origin: top right;
-ms-transform-origin: top right;
-o-transform-origin: top right;
transform-origin: top right;
}
<div style="border: 1px solid red;">
<img id="myimage" src="http://upload.wikimedia.org/wikipedia/mediawiki/a/a9/Example.jpg" style="border: 3px solid silver;" />
</div>
Using some jQuery, you can get the offset
of the parent, subtract that from the new rotated offset
and use margin to put it back to the container. It works with all rotations. Here is the Fiddle.
JS:
function rotate(elm, deg) {
var offsetContLeft, offsetContTop, offsetLeft, offsetTop, newLeft, newTop;
$(elm).css('transform', 'rotate('+ deg +'deg)');
// Get the container offset
offsetContLeft = $(elm).parent().offset().left;
offsetContTop= $(elm).parent().offset().top;
// get the new rotated offset
offsetLeft = $(elm).offset().left;
offsetTop = $(elm).offset().top;
// Subtract the two offsets.
newLeft = offsetContLeft - offsetLeft;
newTop = offsetContTop - offsetTop;
// Apply the new offsets to the margin of the element.
$(elm).css('margin-left', newLeft).css('margin-top', newTop);
}
$("#myrotate").click(function (e) {
// pass in the element to rotate and the desired rotation.
rotate('#myimage', 90);
});
From the answers given thus far I take it that there is no simpler approach than using JavaScript to "realign" the image. Let me therefore share the approach which I ended up using:
var step = 0;
$("#myrotate").click(
function (e) {
step += 1;
var img = $("#myimage");
img.css('transform', 'rotate('+ step*90 +'deg)'); // could be extended to work also in older browsers
var d = img.width() - img.height();
img.css('margin-left', -d/2*(step%2));
img.css('margin-top', d/2*(step%2));
}
);
myrotate
is the id
of the <a>
which I abuse as switch, myimage
is (guess) the id
of the img
to rotate.
Try it here.
I don't know if there is a simplier way, but you can set margin of the image after rotation like this.
margin:68px -66px;
You can use js to get image width and height so it sets values accordingly to the size of image. I used manual way.
EDIT:
You can always mess with
-webkit-transform-origin: 75px 75px;
-moz-transform-origin: 75px 75px;
-ms-transform-origin: 75px 75px;
-o-transform-origin: 75px 75px;
transform-origin: 75px 75px;
as found here: CSS "transform: rotate()" affecting overall design with "position: absolute" (not aligning properly)
I take the @Lost Left Stack example and changed it to work with all rotations, and be repetitive. Resets margins for repetitive rotations. Also set right and bottom margins.
function rotateImage(elm, deg) {
$(elm).css('margin-left', 0).css('margin-top', 0);
$(elm).css('transform', 'rotate(' + deg + 'deg)');
// Get the container offset
var offsetContLeft = $(elm).parent().offset().left;
var offsetContTop = $(elm).parent().offset().top;
// get the new rotated offset
var offsetLeft = $(elm).offset().left;
var offsetTop = $(elm).offset().top;
// Subtract the two offsets.
var newOffsetX = Math.floor(offsetContLeft - offsetLeft) + 1;
var newOffsetY = Math.floor(offsetContTop - offsetTop) + 1;
$("#a").text(newOffsetX + "-" + newOffsetY)
// Apply the new offsets to the margin of the element.
$(elm).css('margin-left', newOffsetX).css('margin-top', newOffsetY)
.css('margin-right', newOffsetX).css('margin-bottom', newOffsetY);
}
var rot = 0;
$("#myrotate").click(function (e) {
rot += 15;
rotateImage('#myimage', rot);
});
example: http://jsfiddle.net/v4qa0x5g/2/
来源:https://stackoverflow.com/questions/18531698/css-rotate-image-and-align-top-left