5

In my html/css app, I have a notion of button, which is, in essence, class .button with a bunch of appropriate attributes. Here's a simplified example:

.button {
  width: 120px;
  height: 30px;
  line-height: 30px;
  background: yellow;
  text-align: center;
}
<div class="button">
  <div class="button-text">
    Button text
  </div>
</div>

In a small number of places, the text that needs to be displayed is rather long, yet it still needs to fit fully. As font-stretch property isn't support, I use transform: scale, which does what I need - kind of... In addition to the above, I have:

.button {
  width: 120px;
  height: 30px;
  line-height: 30px;
  background: yellow;
  text-align: center;
}
.button-text {
  line-height: 30px;
  transform: scale(0.7, 1);
  white-space: nowrap;
}
<div class="button">
  <div class="button-text">
    Very long button text
  </div>
</div>

The text now fits, but it's not centred, because the position of centered content within the div is calculated before the transform is applied - see example in this jsfiddle: https://jsfiddle.net/1xz1g634/1/

I can "make" it centred by applying negative left margin to the .button-text, however that's a hack and the margin would have to be different in different browsers.

How can I universally centre that text? Ideally, without resorting to javascript, but, if everything else fails, I can use javascript/jquery.

Jesse Kernaghan
  • 4,544
  • 2
  • 18
  • 25
Aleks G
  • 56,435
  • 29
  • 168
  • 265
  • do you really need transformed text? is ellipsing an option? – Joum Jan 14 '16 at 17:02
  • @Joum No, ellipsising is not an option. Requirement is for the text to be displayed in full. – Aleks G Jan 14 '16 at 17:03
  • can the button be resized? if you wrapped the text in a `block` element you could probably use `left` and `margin` attributes to position it correctly, should the text have a maximum width, for example. – Joum Jan 14 '16 at 17:04
  • 1
    I'm just wondering because if your text, for some reason you can't control, becomes bigger, it wil be impossible to read – Joum Jan 14 '16 at 17:05
  • @Joum The texts are all fixed as are button sizes. These are two specific buttons in the whole application. The scaling factor is 0.85 in real application, which is fully acceptable. – Aleks G Jan 14 '16 at 17:06
  • @AleksG I think this is what you want - https://jsfiddle.net/so84w5f1/ ? – Anonymous Jan 14 '16 at 17:08
  • 2
    I'm a bit confused. If you can style the button explicitly to have the transform, why not just change the font-size to something smaller instead? – Jesse Kernaghan Jan 14 '16 at 17:11
  • @Anonymous Thanks, but wouldn't the number 25% depend on how much the text overflows? This number is different on different devices. – Aleks G Jan 14 '16 at 17:11
  • 1
    @JesseKernaghan The button in question appears in a line of buttons (toolbar). Smaller font will mean smaller vertical size, which doesn't look good. I want to maintain the same vertical size of font as for other buttons - only "squish" the text horizontally. – Aleks G Jan 14 '16 at 17:12
  • @AleksG I'm not sure about it's different on different devices but you can control the transform origin with that – Anonymous Jan 14 '16 at 17:13
  • Is this related?: http://stackoverflow.com/questions/3401136/resize-font-to-fit-in-a-div-on-one-line – Joum Jan 14 '16 at 17:15
  • @Anonymous I checked - in my case the number ranges from 20 to 25% depending on device (20% on iPad, 25% on Chrome on Linux, about somewhere round 23% for FF on OSX) – Aleks G Jan 14 '16 at 17:15
  • @Joun no, as that decreases the font size – Aleks G Jan 14 '16 at 17:16
  • @Anonymous I tested that and if you check this fiddle, you'll see it won't work for a shorter text, https://jsfiddle.net/LGSon/so84w5f1/2/, which makes it unreliable. – Asons Jan 15 '16 at 10:16

4 Answers4

4

If you set the container to display:flex + justify-content:center that centers it correctly.

.button {
  width: 120px;
  height: 30px;
  background: yellow;
  display: flex;
  justify-content: center;
}
.button-text {
  line-height: 30px;
  transform: scale(0.7, 1);
  white-space: nowrap;
}
<div class="button">
  <div class="button-text">
    Very long button text
  </div>
</div>
Stickers
  • 75,527
  • 23
  • 147
  • 186
2

Unfortunately, the reason why the long text isn't centered is because it overflows normally and so text-align:center is ineffective.

Scaling the text (although smaller font-size {Codepen Demo} would probably be more appropriate I feel) will not override the text-centering because transforms are visual only.

I think the optimum solution (other than font-sizing) would be to absolutely position the inner text element and center that using the usual methods.

.button {
  width: 120px;
  height: 30px;
  line-height: 30px;
  background: yellow;
  text-align: center;
  position: relative;
  margin: 1em auto;
}
.button-text {
  position: absolute;
  top: 50%;
  left: 50%;
  line-height: 30px;
  transform: translate(-50%, -50%);
  white-space: nowrap;
  ;
}
.button-text.scaled {
  transform: translate(-50%, -50%) scale(0.7, 1);
}
<div class="button">
  <div class="button-text">
    Very Long Button Text
  </div>
</div>

<div class="button">
  <div class="button-text scaled">
    Very Long Button Text
  </div>
</div>
Paulie_D
  • 107,962
  • 13
  • 142
  • 161
  • this is elegant and quite straightforward, but I think it might fail with the proposed text OP mentioned... – Joum Jan 14 '16 at 17:19
1

You can do this with display: table as well ... works down to IE9.

Well actually down to IE8 using filter: progid:DXImageTransform.Microsoft.Matrix to scale.

.button {
  width: 120px;
  height: 30px;
  background: yellow;
  display: table;
  text-align: center;
}
.button-text {
  display: table-cell;
  line-height: 30px;
  transform: scale(0.7, 1);
  white-space: nowrap;
}
<div class="button">
  <div class="button-text">
    Very long button text
  </div>
</div>
Asons
  • 84,923
  • 12
  • 110
  • 165
0

Fixed it for you. Text will auto center and the button will auto scale.

CSS:

.button {
  display: inline-block;
  padding: 10px 20px;
  background: yellow;
  text-align: center;
}

.button-text {
  line-height: 30px;
  transform: scale(0.7, 1);
  white-space: nowrap;
}

HTML:

<div class="button">
  <div class="button-text">
    Very long button text
  </div>
</div>

https://jsfiddle.net/m7Lgmpn6/

Korgrue
  • 3,430
  • 1
  • 13
  • 20
  • Rather than play spot the difference, I would point out that the `.button` class has been set as `inline-block` from its default display property. – Martin Jan 14 '16 at 17:06
  • this isn't a solution. My buttons MUST be fixed size and I cannot rely on explicit pixel values, as they will be different for different devices. Simply setting `display: inline-block` does nothing - see for yourself: https://jsfiddle.net/g6nL456a/1/ – Aleks G Jan 14 '16 at 17:09
  • the default for – Korgrue Jan 14 '16 at 17:16
  • Aleks G, I did more than just change the display type. Look closely. It is not possible to both center the text in a button of varying text length AND not vary the button width if you plan to center the text via CSS alone. You would have to load the DOM, then run a script to grab the width of the text, subtract it from the button width, divide that amount by 2 and then relatively position the text to the left by that calculated amount. – Korgrue Jan 14 '16 at 17:17
  • @Korgrue Apparently, it's possible - have a look at the accepted answer. – Aleks G Jan 14 '16 at 17:22
  • Glad you found the answer you were looking for. Good luck on your project! – Korgrue Jan 14 '16 at 17:27