Center div on screen that has been rotated and scaled with css3 - html

I have the following jsfiddle:
https://jsfiddle.net/quacu0hv/
I cant figure out how to center this div. The fact that it is rotated makes it hard to actually center the object on screen. How exactly can this be achieved with pure css? I imagine its due to the point of origin that changed its position (upper left vertex of the div).
div {
transform: rotate(-45deg) scale(2) translate(-50%, -50%);
opacity: 1 !important;
top: 50%;
left: 50%;
width: 200px;
height: 200px;
background: black;
position: absolute;
}

Try rearranging the transform values and see what happens ;)
Turns out order does matter. If you think about it, it does makes sense:
Rotate > Scale > Translate
Once you've rotated it, the origin has been rotated too. That's why your square moves "left" and "up" from the origin.
Translate > Rotate > Scale
This is what you want to do. Position before you make any other adjustments that can affect the origin.

Use CSS transform-origin: 50% 50% or try 0 0. Remove position: absolute first.
This is at 0 0
This is at 50% 50%
This is at 45% -290% Centered?
Yeah, looks centered to me, see Full Page. Anyways, as you can see from the other answers transform-origin is the best solution. Scott suggested to remove the transform: -50% -50% which makes perfect sense if you wanted the div centered in the first place, but if you wanted that in there still and have it centered as a square in a rectangle (height is smaller than width), then 45% by -290%.
SNIPPET
.box {
position: relative;
}
.center {
transform: rotate(-45deg) scale(2) translate(-50%, -50%);
transform-origin: 45% -290%;
opacity: 1 !important;
width: 200px;
height: 200px;
background: black;
position: absolute;
}
<div class='box'>
<div class='center'></div>
</div>

You could just remove translate(50%, 50%);
div {
transform: rotate(-45deg) scale(2);
opacity: 1 !important;
top: 50%;
left: 50%;
width: 50px;
height: 50px;
background: black;
position: absolute;
}
<div></div>
Fiddle
or add transform-origin: 0 0; to start transformations in the upper left corner.
div {
transform: rotate(-45deg) scale(2) translate(-50%, -50%);
transform-origin: 0 0;
opacity: 1 !important;
top: 50%;
left: 50%;
width: 50px;
height: 50px;
background: black;
position: absolute;
}
<div></div>
Fiddle

Using transform-origin you can get the result, also scale and rotate goes before positioning.
div {
transform-origin: 0 0;
transform: rotate(-45deg) scale(2) translate(-50%, 50%);
opacity: 1 !important;
width: 100px;
height: 100px;
background: black;
}
<div></div>
jsfiddle: https://jsfiddle.net/quacu0hv/8/

Related

Why does translate(-50%, -50%) work to center an element in parent but not top, left: 50%? [duplicate]

When working with hero images or full screen anything, I typically see text or images with the following bit of CSS:
.item {
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
What is this code actually doing?
The reason why transform: translate(-50%, -50%) is required is because you want the center of the element to line up with the center of its parent. In simple terms, it can be boiled down to translateX(-50%) translateY(-50%), which means:
move me leftwards by 50% of my width, along the x-axis, and
move me upwards by 50% of my height, along the y-axis
This effectively moves the center of the element to its original top left corner. Remember then when you set left: 50%; top 50% on the element, you are moving its top left corner to the center of its parent (which means it is not visually centered at all). By moving the element back leftwards and upwards by half of its width and height respectively, you are sure that its center now aligns with the parent's center, making it visually horizontally + vertically centered.
As a proof of concept, see the code snippet below: hover over the parent to cause the child element's "ghost" to reposition itself by means of transform: translate(-50%, -50%):
body {
margin: 0;
padding: p;
}
.parent {
background-color: #ccc;
width: 100vw;
height: 100vh;
position: relative;
}
.child {
background-color: rgba(0,0,255,0.5);
width: 50px;
height: 50px;
position: absolute;
top: 50%;
left: 50%;
}
.child::before {
background-color: rgba(255, 0, 0, 0.5);
position: absolute;
top: 0;
left: 0;
width: 50px;
height: 50px;
content: '';
transition: all .5s ease-in-out;
}
body:hover .child::before {
transform: translate(-50%, -50%);
}
<div class="parent">
<div class="child"></div>
</div>
TL;DR version
Let's say there is a .container and an .item inside.
This code below is positioning .item relatively to .container; meaning .item top left corner is in the center of its container
.item {
top: 50%;
left: 50%;
}
While the below is positioning .item relatively to its own width and height; meaning minus 50% of its width and height.
.item {
transform: translate(-50%, -50%);
}
If the two code snippets below are combined, then the expected center will show up.

Transform: translate(-50%, -50%)

When working with hero images or full screen anything, I typically see text or images with the following bit of CSS:
.item {
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
What is this code actually doing?
The reason why transform: translate(-50%, -50%) is required is because you want the center of the element to line up with the center of its parent. In simple terms, it can be boiled down to translateX(-50%) translateY(-50%), which means:
move me leftwards by 50% of my width, along the x-axis, and
move me upwards by 50% of my height, along the y-axis
This effectively moves the center of the element to its original top left corner. Remember then when you set left: 50%; top 50% on the element, you are moving its top left corner to the center of its parent (which means it is not visually centered at all). By moving the element back leftwards and upwards by half of its width and height respectively, you are sure that its center now aligns with the parent's center, making it visually horizontally + vertically centered.
As a proof of concept, see the code snippet below: hover over the parent to cause the child element's "ghost" to reposition itself by means of transform: translate(-50%, -50%):
body {
margin: 0;
padding: p;
}
.parent {
background-color: #ccc;
width: 100vw;
height: 100vh;
position: relative;
}
.child {
background-color: rgba(0,0,255,0.5);
width: 50px;
height: 50px;
position: absolute;
top: 50%;
left: 50%;
}
.child::before {
background-color: rgba(255, 0, 0, 0.5);
position: absolute;
top: 0;
left: 0;
width: 50px;
height: 50px;
content: '';
transition: all .5s ease-in-out;
}
body:hover .child::before {
transform: translate(-50%, -50%);
}
<div class="parent">
<div class="child"></div>
</div>
TL;DR version
Let's say there is a .container and an .item inside.
This code below is positioning .item relatively to .container; meaning .item top left corner is in the center of its container
.item {
top: 50%;
left: 50%;
}
While the below is positioning .item relatively to its own width and height; meaning minus 50% of its width and height.
.item {
transform: translate(-50%, -50%);
}
If the two code snippets below are combined, then the expected center will show up.

Translate property not working on div

I've been trying to center both horizontally and vertically a specific div, and I got the vertical part to center, just not the horizontal part.
I'm using translate(-50%, -50%), which should be centering in a center, but is not working...
The part that says "Or login to your acccount" is the part I'm trying to vertically center.
Link to the site
Relevant CSS:
.logindiv {
position: relative;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
you need to do 2 things:
add a wrapper(this will be the green div), let's call login-wrap, and give it this properties:
.login-wrap {
float: left;
height: 100%;
position: relative;
width: 40%;
}
change relative to absolute here
.logindiv {
left: 50%;
position: absolute;
top: 50%;
transform: translate(-50%, -50%);
}
Try adding margins for horizontal center positioning
.logindiv {
margin-right: auto;
margin-left: auto;
}
transform is working. Try this one. You have to define your transform style for all the browsers.
.logindiv {
left: 50%;
transform: translate(-23%, -38%);
-ms-transform: translate(-23%, -38%); /* IE 9 */
-webkit-transform: translate(-23%, -38%) /* safari*/
width: 382px;
position: relative;
}
Here is your original code:
.logindiv {
position: relative;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
By changing the position to absolute, you can move the logindiv around with the transform: translate() (which does X first, then Y)
I chose 60%, -70% as that looked centered with the left on my screen, but mess around with it. This was the only way I could find to let it resize the same way as the welcome text on the left.
New code:
.logindiv {
position: absolute;
top: 50%;
left: 50%;
transform: translate(60%, -70%);
}

Rotate element and place in corner of parent

I'm trying to position an element in the bottom right corner of it's parent. At the moment, you can see it's in the center, but touching the bottom:
http://jsfiddle.net/03r7gabp/
Ideally, I'd like it to be touching the bottom, flushed all the way to the right (what right: 0; typically does).
This is the desired effect:
Is this possible? I'm already using:
transform-origin: bottom left;
There are couple of solutions to achieve that, however I found this one more flexible.
Due to the fact that you can combine multiple transform notations, you'll end up with:
.info {
position: absolute;
bottom: 0; right: 0;
transform: rotate(-90deg) translateX(100%);
transform-origin: 100% 100%;
}
The key point is that a percentage value on translate() notation is relative to the size of bounding box. I.e. the size of border-box of the absolutely positioned element in this case.
Here is a demo:
.container {
width: 300px;
height: 200px;
border: 1px solid red;
position: relative;
}
.info {
position: absolute;
bottom: 0; right: 0;
background-color: gold;
-webkit-transform: rotate(-90deg) translateX(100%);
-moz-transform: rotate(-90deg) translateX(100%);
-o-transform: rotate(-90deg) translateX(100%);
-ms-transform: rotate(-90deg) translateX(100%);
transform: rotate(-90deg) translateX(100%);
-webkit-transform-origin: 100% 100%;
-moz-transform-origin: 100% 100%;
-ms-transform-origin: 100% 100%;
-o-transform-origin: 100% 100%;
transform-origin: 100% 100%;
}
<div class="container">
<div class="info">
hello this is a sentence
</div>
</div>
Okay, so here's how I've done it!
http://jsfiddle.net/03r7gabp/2/
CSS
.info {
position: absolute;
bottom: 0;
left: 0;
background-color: lime;
transform: rotate(-90deg);
transform-origin: bottom left;
margin-left: 100%;
width: 200px; /* height of container */
}
The only bodge that I'm not happy with is the width having to be a fixed value (equal to the height of the container).
Breakdown
Step 1
Not much to see here, move along!
Step 2
Note that we've specified the origin of rotation to be the bottom left. Imagine you stick a pin in that corner of the <div> and you then spin it about this point.
Step 3
In the previous image our <div> was sat on the outside of the container. We can now adjust its margin to make it appear on the other side. Remember that the percentage specified is a measure of the width of the parent element
Step 4
Now we "bump" the item to the bottom of the container.
Step 5
Finally we have to give our div a width equal to the height of the parent container
An alternative solution would be to set the container to have overflow: hidden; and then put the width of the child element to arbitrarily large. Obviously if the length of sentence exceeded the height of the container, the words would be clipped (e.g. http://jsfiddle.net/03r7gabp/6/)
One solution is to change transform-origin: bottom left; to right and also change frombottom: 0 to top: 35px
.container {
width: 300px;
height: 200px;
border: 1px solid red;
position: relative;
}
.info {
position: absolute;
top: 35px;
right: 0;
-webkit-transform: rotate(-90deg);
-moz-transform: rotate(-90deg);
-o-transform: rotate(-90deg);
-ms-transform: rotate(-90deg);
transform: rotate(-90deg);
transform-origin: bottom right;
}
<div class="container">
<div class="info">
hello this is a sentence
</div>
</div>

Align rotated div with another div

I have a main div (the red div in the fiddle) that has a smaller vertical tab on the side (the blue div in the fiddle).
The RED div is standard BUT the Blue div is rotated through 90 degrees (as I need to have vertical text in it). This is where the problems starts.
The red div is vertically positioned at 50% so it is in the middle of the page and locked with scrolling etc.
I want to align the blue div so that the top edge of the blue div is at the same Y position as the top edge of the red div.
I would prefer NOT to use jQuery but can do if required.
Desired output :
Fiddle is here : http://jsfiddle.net/kBKf6/
Here is the code I am using :
<div id="main" style="position: fixed; top: 50%; margin-top: -250px; left:0; height: 500px; width: 450px; background-color:red;">
Main Content Div
</div>
<div id="vertical_div" style="overflow:hidden; position: fixed; left:350px; height:40px; width:200px; margin: auto; background-color:blue; text-align:center; color:white; -webkit-transform: rotate(90deg) translate(-50%, -50%); -moz-transform: rotate(90deg) translate(-50%, -50%); -ms-transform: rotate(90deg) translate(-50%, -50%); -o-transform: rotate(90deg) translate(-50%, -50%); transform: rotate(90deg) translate(-50%, -50%);">
Side Tab
</div>
You don't need JS to align the rotated div. You can define a transform origin in CSS then, it becomes easy to align.
Side note : You can remove the -moz- and -o- vendor prefixes see caniuse
DEMO
HTML :
<div id="main">Main Content Div
<div id="verticaldiv">Side Tab</div>
</div>
CSS :
#main {
position: fixed;
top: 50%;
margin-top: -250px;
left:0;
height: 500px;
width: 450px;
background-color:red;
}
#verticaldiv {
overflow:hidden;
position: absolute;
left:100%;
bottom:100%;
height:40px;
width:200px;
background-color:blue;
text-align:center;
color:white;
-webkit-transform: rotate(90deg);
-ms-transform: rotate(90deg);
transform: rotate(90deg);
-ms-transform-origin:0 100%;
-webkit-transform-origin: 0 100%;
transform-origin: 0 100%;
}
You can also do it without relying on hardcoded sizes that move your div into position, but you need a wrapper around your .verticaldiv
demo:
http://jsfiddle.net/MCr6f/
demo 2:
http://jsfiddle.net/9LtKw/ (to show that different sizes don't matter)
html:
<div class="one">
Hello
<div class="pivot">
<div class="two">
Pretty!
</div>
</div>
</div>
css:
.one {
background: red;
position: relative;
float: left;
/*strange and difficult sizes*/
font-size: 3.237827em;
padding: 10px;
}
.pivot {
position: absolute;
top: 0;
right: 0;
-webkit-transform: rotate(90deg);
-moz-transform: rotate(90deg);
transform: rotate(90deg);
width: 0px;
height: 0px;
}
.two {
background: blue;
color: white;
position: absolute;
left: 0;
bottom: 0;
/*strange and difficult sizes*/
font-size: 12px;
padding: 0.3em;
}