61

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%);
 }
norkuy
  • 693
  • 1
  • 5
  • 7

2 Answers2

79

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>
Michael Coker
  • 52,626
  • 5
  • 64
  • 64
  • also depends on `direction` rtl or ltr – Banzay Feb 08 '17 at 18:55
  • 3
    @Banzay feel free to leave your own answer clarifying the role of `direction` on this type of positioning. When using `left` or `right` it shouldn't matter what the `direction` of the document is, since you're specifying `right` or `left` http://codepen.io/anon/pen/PWdrBG – Michael Coker Feb 08 '17 at 19:07
  • that was more question, than a note. thanx :) – Banzay Feb 08 '17 at 19:28
  • I'm more curious on how to make the cool red target line to show the center... still wrap my head around `body:after` `body:before`. Anyone could shed a light? (On some tries I feel like css of :after or :before can be swapped), doesn't matter which one stays before or after – aanhlle Apr 06 '22 at 13:19
  • @aanhlle, `::before` and `::after` are pseudo elements - https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements. They're somewhat interchangeable, but it's worth noting that `::after` will stack with a higher `z-index` than `::before` by default since `::after` comes "after" `::before` :) – Michael Coker Apr 07 '22 at 14:23
6

From what I understand, top: and left: really 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.

Michael M.
  • 10,486
  • 9
  • 18
  • 34
Alaska
  • 341
  • 2
  • 9