80

I have the following HTML:

<div class="outer">
    <div class="inner rotate">Centered?</div>
</div>

div.outer is a narrow vertical strip. div.inner is rotated 90 degrees. I would like the text "Centered?" to appear centered in its container div. I do not know the size of either div in advance.

This comes close: http://jsfiddle.net/CCMyf/2/. You can see from the jsfiddle that the text is vertically centered before the transform: rotate(-90deg) style is applied, but is somewhat offset after. This is particularly noticeable when div.outer is short.

Is it possible to center this text vertically without knowing any of the sizes in advance? I haven't found any values of transform-origin that solve this problem.

danvk
  • 13,227
  • 3
  • 51
  • 86
  • Are you opposed to setting `display: table` on the elements? Because the 'standard' way to vertically align dynamic divs should work with the transform without issue: http://stackoverflow.com/a/6182661/188221 – DigTheDoug Feb 28 '13 at 15:13
  • I'm not opposed to ```display: table```. This fiddle shows that the table solution has the same issues as the one above: http://jsfiddle.net/4d384/ – danvk Feb 28 '13 at 18:19
  • Try putting the `rotate` class on the middle element. That should do it, but it looks like it messes up the width of the item. Might have to play around with the padding or width or height props, but it should be do-able: http://jsfiddle.net/digthedoug/jWYuq/ – DigTheDoug Feb 28 '13 at 19:16
  • Fixing the width issue is significantly harder than you'd expect. Putting ```min-width: 16px; width: 16px``` on ```.outer``` results in the exact same non-centering as in the original question. – danvk Mar 01 '13 at 01:48

7 Answers7

155

The key is to set position top and left to 50% and then transformX and transformY to -50%.

.inner {
    position: absolute;
    top: 50%;
    left: 50%;
}

.rotate {  
    transform:  translateX(-50%) translateY(-50%) rotate(-90deg);
}

see: http://jsfiddle.net/CCMyf/79/

bjnsn
  • 2,200
  • 2
  • 11
  • 12
  • 2
    Working with text elements instead of divs I had to add `margin: 0` on the inner element to make the text center perfectly. – kapoko Apr 25 '16 at 12:33
  • 1
    Thank you so much. I was not so far. I don't know why but if I set the rotate rule first like this: `transform: rotate(-90deg) translateX(-50%) translateY(-50%);` it doesn't work, and if I put it last as your example shows, it works: `translateX(-50%) translateY(-50%) rotate(-90deg);`. – Maxime Lafarie Jan 01 '18 at 16:04
  • 1
    @MaximeLafarie Damn me too! Just learned that transform have an execution order – Warface Feb 13 '21 at 15:11
6

It may be a bit late for answering that question, but I stumbled on the same issue and found some way of achieving it, by adding another div in the way.

<div class="outer">
    <div class='middle'><span class="inner rotate">Centered?</span></div>
</div>

and applying a text-align: center on that middle element, along with some positioning stuff:

.middle {
    margin-left: -200px;
    width: 400px;
    text-align: center;
    position: relative;
    left: 7px;
    top: 50%;
    line-height: 37px;
}

The .inner also gets a display: inline-block; to enable both rotate and text-align properties.

Here is the corresponding fiddle : http://jsfiddle.net/CCMyf/47/

Pascal M
  • 71
  • 1
  • 1
2

Can you add margin: 0 auto; to your "rotate" class to center the text.

.rotate {
  -webkit-transform: rotate(-90deg);
  -ff-transform: rotate(-90deg);
  transform: rotate(-90deg);
  width: 16px;  /* transform: rotate() does not rotate the bounding box. */
  margin: 0 auto;
}
97ldave
  • 5,039
  • 3
  • 23
  • 37
  • This does not work. Here's the fiddle updated with "margin: 0 auto": http://jsfiddle.net/CCMyf/3/. You can see that the "?" in "Centering?" is much closer to the top than the "C" is to the bottom. – danvk Feb 28 '13 at 18:00
2

The answer from 'bjnsn' is good but not perfect as it fails when the text contains space in it. For example he used 'Centered?' as text but if we changed the text to let suppose 'Centered? or not' then it will not work fine and will take the next line after space. Ther is not width or height defined for the inner div block.

.inner {
  font-size: 13px;
  font-color: #878787;
  position: absolute;
  top: 50%;
  left: 50%;
  background: #DDD;
}

https://jsfiddle.net/touqeer_shakeel/f1gfy1yy/ But we can make the whole text centered align properly, by setting the inner div width equal to height of the outer div, line-height of inner div equal to the width of the outer div and setting the display flex property for inner div with align-items:center and justify-content:center properties.

.inner {
  font-size: 13px;
  font-color: #878787;
  position: absolute;
  top: 50%;
  left: 50%;
  display: flex;
  justify-content:center;
  align-items:center;
  line-height:40px;
}
$('#height').on('change', function(e) {
  $('.outer').css('height', $('#height').val() + 'px');
  $('.inner').css('width', $('#height').val() + 'px');
});

updated fiddle https://jsfiddle.net/touqeer_shakeel/cjL21of5/

2

The another option to rotate text 90 degree and center on axis Y is:

.rotate-centered {
    top: 50%;
    right: 50%;
    position: absolute;
    transform: scale(-1) translate(-50%, 50%);
    writing-mode: vertical-lr;
 }
<span class="rotate-centered">Text<span>

Example: https://codepen.io/wwwebman/pen/KKwqErL

But because of bad support in IE/EDGE writing-mode does NOT work there: https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode

wwwebman
  • 261
  • 5
  • 13
0

Removing : margin-top: -7px; from .inner made the vertically rotated text centered for me. It also made the horizontal text not centered.

Just remove the above code?

Michael
  • 6,591
  • 2
  • 23
  • 39
  • This may make it closer to being centered, but it still isn't properly centered. You can see this clearly in this version of the fiddle: http://jsfiddle.net/CCMyf/4/ – danvk Feb 28 '13 at 18:02
0

You could add this:

$('.inner').css('margin-top', $(this).parent().height() - 2*$(this).height());

To your .on('change') function, as you can see here: http://jsfiddle.net/darkajax/hVhbp/

DarkAjax
  • 15,175
  • 11
  • 52
  • 65