CSS Centering with Transform - css

why does centering with transform translate and left 50% center perfectly (with position relative parent) but not right 50%?
Working example:
span[class^="icon"] {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
Example that doesn't center:
span[class^="icon"] {
position: absolute;
top: 50%;
right: 50%;
transform: translate(-50%, -50%);
}

Because translateX(-50%) moves something back to the left 50% (because of the - negative value), which means it pairs with left: 50%; to center something.
If you want to use right: 50%; then use that with translateX(50%) to center.
* {margin:0;}
span {
position: absolute;
top: 50%; right: 50%;
transform: translate(50%,-50%);
background: black;
color: white;
}
body:after, body:before {
content: '';
position: absolute;
background: red;
}
body:after {
top: 50%;
left: 0; right: 0;
height: 1px;
}
body:before {
left: 50%;
top: 0; bottom: 0;
width: 1px;
}
<span>center me</span>

From what I understand, top: and left: actually mean how far the object's top edge is from the top of its container (container refers to the closest parent element with a relative position) and how far the object's left edge is from the left of its container. Specifically, top: 50% means that the object is shifted by 50% of the container's height and left: 50% means the object is shifted 50% of the container's width.
Once the origin of the element is at the center, you can see that by shifting the element to the left by half of its width and up by half of its height, the center of the object will be at the origin rather than its upper left corner.
If we did right: 50% instead, then the right side of the element would be shifted from the right side of the container by 50% of the container's width, meaning that its upper-right edge is on the origin. Therefore, by shifting it to the right by 50% of its width and up by 50% of its height (transform(50%, -50%)), we will center the object.

Related

How does centering using absolute positioning and CSS transform work? [duplicate]

This question already has answers here:
How to center a "position: absolute" element
(31 answers)
How can I center an absolutely positioned element in a div?
(37 answers)
Closed 3 years ago.
I learnt a new (new to me) way of centering divs from an online resource. I can not get hold of the author, so please explain what exactly is happening here.
<header class="header">
<div class="header-box">
<h1>
Lorem Ipsum <br>
Dolor sit amet
</h1>
</div>
</header>
.header {
position: relative;
height: 100vh;
background-image: linear-gradient(
to right bottom,
rgba(17, 63, 112),
rgba(253, 135, 31));
background-position: top;
}
.header-box {
position: absolute;
top: 50%; /*This and next line*/
left: 50%;
transform: translate(-50%, -50%); /*and this*/
}
h1 {
text-align: center;
}
How exactly the Transform property is aligning the div in center perfectly when the position property pushed it away?
https://jsfiddle.net/ux1r3eb0/
I'll describe this in the context of horizontal alignment, but exactly the same principles apply to vertical alignment:
The absolute position moves the element's left side to the centre of the screen, then the transform moves the element's centre left by half it's width, which lines up the centre of the element with the centre of the container.
Visual example (I'm only showing the horizontal movement, to make it easier to understand):
.container {
position: relative;
width: 100vw;
height: 100vh;
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEX/AAAZ4gk3AAAACklEQVR4XmNgAAAAAgAB3p6PvwAAAABJRU5ErkJggg==');
background-position: center;
background-size: 1px 100%;
background-repeat: no-repeat;
}
.content {
position: absolute;
width: 100px;
height: 100px;
top: 50%;
border: 1px solid #F00;
animation-name: demo;
animation-duration: 8s;
animation-fill-mode: forwards;
}
#keyframes demo {
0% {
left: 0%;
transform: translate(0%, -50%);
}
50% {
left: 50%;
transform: translate(0%, -50%);
}
100% {
left: 50%;
transform: translate(-50%, -50%);
}
}
<div class="container">
<div class="content"></div>
</div>
The top and left property pushed away the .header-box from the top and left side of .header. 50% value means 50 percent of height and width of .header
while the translate(-50%, -50%) makes the .header-box to pull back itself by half of the size of itself.
When you use percentage in top, left, right, bottom property, it uses the size of closest positioned ancestor element, while the transform uses the size of itself.

Controlling the origin of rotation in a CSS transform on the right hand side of a div

If I apply this rule to a div (with variable content)
position: absolute;
left: 0;
top: 0;
transform: rotate(90deg) translateY(-100%);
transform-origin: 0 0 0;
It rotates from its top left corner and 'hangs' in the top left corner of its parent. It doesn't move no matter what size the div
How can I do the same in the right hand corner, ie rotate it so it 'hangs' in the right hand corner of its parent and rotates from its top left.
the starting point is
position: absolute;
right: 0;
top: 0;
transform: rotate(90deg);
transform-origin: 100% 0 ;
but it 'sticks up' rather than 'hangs down'.
I can, of course, move it with right and top but those values are different for different size of content.
The answer is, as all are when you know, very simple. Thanks to Sahil for making me mock it up in Codepen, easier to see the issue than when on a live page full of data.
position: absolute;
right: 0;
top: 0;
transform: rotate(90deg) translateX(100%);
transform-origin: 100% 0 ;
ie the addition of translateX(100%); to the transform

Centering an absolutely positioned div over a bootstrap grid

I want to center a div on top of a bootstrap grid and have it remain centered with the responsive layout (regardless of screen size). Here is a bootply of what I'm trying to do. How can I center the .ontop div on the grid?
Oops should have poked around more. I found this works pretty well:
width: 80%;
height: 80%;
left: 50%;
top: 25%;
margin-left: -40%;
margin-right: -40%;
You have to apply the following:
.container .ontop {
position: absolute;
top: 50%;
left: 50%;
-webkit-transform: translate(-50%, -50%);
-moz-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
The top/left properties move the element by 50% of the width of the parrent element horizontally/vertically. The transform: translate() moves the element back by half of its width/height.

Using css translate -50% to centre div doesn't apply to Firefox saved details pop-up

I've used the following css to centre a div on screen (no fixed width or height so can't use defined pixel width and height and negative margins).
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
I've just realised that when you have saved your details for a form in Firefox, and then try to fill in the form within my div, the pop-up Firefox creates that contains your saved details is ignoring the transform, and appearing in the location on screen where the entire div would be if transform: translate wasn't applied.
It's difficult to give an example of this because it requires you to have saved your login details to a site, but if you go to a site where you have saved details, and move the container using transform: translate, you'll see the effect.
Is there a way of forcing Firefox's pop-up to take on the transform? Or will I need to find a different way of centring my div onscreen?
Your CSS should be right, but the position should be fixed on your parent div
w3schools: position: absolute The element is positioned relative to its first positioned (not static) ancestor element
.parent{
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
}
.child{
position: absolute;
top: 50%;
left: 50%;
width: 100px;
height: 100px;
-webkit-transform: translate(-50%, -50%);
-moz-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
-o-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
<div class="parent">
<div class="child"></div>
</div>
What kind of browser support do you need? you can solve this with flexbox!
body (or container-div) {
display: flex;
align-items: center;
justify-content: center;
}
Try this to center div on a page. It is a more elegant approach.
.center{
position: absolute;
top:0;
left:0;
bottom:0;
right:0;
margin:auto;
height:some-height;
width:some-width;
}

Position AFTER transform in CSS?

Consider the following attempt to rotate a paragraph 90 degrees and position it so that the corner that was initially its top-left corner (and which therefore becomes its top-right corner after the rotation) ends up located at the top-right corner of the parent block.
HTML:
<!DOCTYPE html>
<html>
<body>
<div id="outer">
<p id="text">Foo bar</p>
</div>
</body>
</html>
CSS:
#outer {
border: solid 1px red;
width:600px;
height: 600px;
position: relative;
}
#text {
transform: rotate(90deg);
position: absolute;
top: 0;
right: 0;
}
In Firefox 19.0.2 on OS X 10.6.8, it fails. This appears to be because, despite the order in which the CSS properties were given, the transformation is applied after the positioning. In other words, the browser:
places #text such that its top-right corner is located at the top-right corner of the parent block, but only then
rotates it, with the result that what is now its top-right corner is not located at the top-right corner of the parent block.
As a result, the transform-origin property isn't much use here. If, for instance, one used transform-origin: top right; then #text would need to be moved downwards by the width it had before it was rotated.
My question: is there a way to tell the browser to apply the CSS positioning properties after the rotation; and if not, then is there instead a way to move #text downwards (e.g. using top:) by the width it had before it was rotated?
NB. Ideally the solution should not require setting a fixed width: for #text, and must not require JavaScript.
You can apply more than one transform to an element, and the order does matter. This is the simplest solution: http://jsfiddle.net/aNscn/41/
#outer {
border: solid 1px red;
width:600px;
height: 600px;
position: relative;
}
#text {
background: lightBlue;
position: absolute;
top: 0;
left: 0;
right: 0;
transform: translate(100%) rotate(90deg);
transform-origin: left top;
-webkit-transform: translate(100%) rotate(90deg);
-webkit-transform-origin: left top;
}
The transform origin is the point around which a transformation is applied. For example, the transform origin of the rotate() function is the center of rotation - https://developer.mozilla.org/en-US/docs/Web/CSS/transform-origin
Rotating -90deg.
.rotate {
position:absolute;
-webkit-transform-origin: left top;
/* Safari */
-webkit-transform: rotate(-90deg) translateX(-100%);
/* Firefox */
-moz-transform: rotate(-90deg) translateX(-100%);
/* IE */
-ms-transform: rotate(-90deg) translateX(-100%);
/* Opera */
-o-transform: rotate(-90deg) translateX(-100%);
}
Solved: here
This is the code I've added:
left: 100%;
width: 100%;
-webkit-transform-origin: left top;
I've also added some prefixed transform properties so it will be cross browser
-webkit-transform:rotate(90deg);
-moz-transform:rotate(90deg);
-ms-transform:rotate(90deg);
-o-transform:rotate(90deg);
transform:rotate(90deg);
How I did it:
I've found this question and, as the name of the website says, "fiddled" with the code to obtain this behavior. I guess the solution is left: 100%; instead of right: 0;.
(the width: 100%; is there because for some reason it wasn't 100% and the text would overflow to the next line)
You may want to try using CSS3 #keyframes animation. It will allow you to rotate and reposition in any order you like. Here is a tutorial that may help: [CSS-Tricks][1]
.container {
position: relative;
width: 200px;
height: 200px;
border: 1px solid red;
}
p {
border: 1px solid blue;
position: absolute;
top: auto;
right: 0;
display: inline-block;
margin: 0;
animation: 1s rotate 1s both;
}
#keyframes rotate {
0% {
transform-origin: top left;
transform: rotate(0deg);
right:0;
}
50% {
right:0;
}
100% {
transform-origin: top left;
transform: rotate(90deg);
right: -64px;
}
}
<div class="container">
<p>some text</p>
</div>
You might want to play around with the translate option which you can apply as the second transform function after rotate and place your element at the exact position that you want to.
There is no other way I guess to tell the browser to use the position properties after the transform function is used using plain css.
See this demo - http://codepen.io/anon/pen/klImq
Place "!important" at the end of the transform line.

Resources