11

I have a container that contains both an image, and some text. I want the text to be vertically and horizontally centered in the middle of the image.

It seems that the easiest, forward-thinking method is to use Flexbox and absolute positioning of the text:

.container {
  display: flex;
  justify-content: center;
  align-items: center;
  position: relative;
}

.text {
  position: absolute;
}
<div class='container'>
  <div class='text'>
    This should be centered
  </div>
  <img src="https://placehold.it/250x250" />
</div>

The text is centered in both axes. This seems to work in all modern browsers..... except Safari.

Safari appear to not center the text at all. It's just sitting at the top/left of the container like a normal absolutely positioned element would be in a non-flexbox layout.

Safari (wrong):

enter image description here

All other browsers (correct):

enter image description here

I thought Flexbox was really ready for primetime, but this seems like a deal-breaker considering how many people using Safari on iOS. Centering content horizontally and vertically is something Flexbox should be great at.

My only real alternative here is to not use Flexbox and then use:

.text {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%,-50%);
}

But I would much rather be using Flexbox for progressive reasons.

Is there anything I'm missing here? As much as I hate to ask for it, is there some of Safari-only work-around here? Is there any solution to this besides just "not using flexbox" because if that is the answer in mid-2017 that is going to be disappointing.

JSFiddle for reference: https://jsfiddle.net/z7kh5Laz/4/

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
Jake Wilson
  • 88,616
  • 93
  • 252
  • 370
  • Do you try display: -webkit-box ? -webkit-justify-content: ? -webkit-align-items: ? –  Jun 07 '17 at 16:33
  • 1
    You need what you have, `transform: translate`, when to position absolute positioned elements, and Flexbox can't do that – Asons Jun 07 '17 at 16:33
  • @LGSon How come it works fine on all browsers except Safari then? Are you saying every browser is doing it wrong except for Safari? – Jake Wilson Jun 07 '17 at 16:39
  • Would this be an option: https://jsfiddle.net/z7kh5Laz/5/ – Asons Jun 07 '17 at 16:42
  • If not, then just keep using Flexbox and `transform: translate`...and when time comes, you simply drop the `transform` part – Asons Jun 07 '17 at 16:48
  • 1
    @LGSon Ah I did not realize that I could just leave in the old `transform` stuff along with the Flexbox code at the same time. I was assuming that it would throw off the browsers who are using Flexbox correctly but it appears to have no effect there. Thank you! Feel free to actually answer below if you want credit. – Jake Wilson Jun 07 '17 at 16:52

2 Answers2

31

When it comes to Flexbox and absolute positioning, there is a few do's and don't's, and in this case, Safari won't center an absolute positioned element the other browsers does.

You can combine Flexbox and transform: translate, as the latter does not impact the former, and when times comes, where they all behave the same with Flexbox alone, you can just drop the transform/left/top part.

.container {
  display: flex;
  justify-content: center;
  align-items: center;
  position: relative;
}

.text {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%,-50%);
}
<div class='container'>
  <div class='text'>
    This should be centered
  </div>
  <img src="https://placehold.it/250x250"/>
</div>
Asons
  • 84,923
  • 12
  • 110
  • 165
11

Respectfully, there are a few wrong assumptions in your question:

  • "Safari (wrong): [image]" - Safari is not necessarily wrong.
  • "All other browsers (correct): [image]" - The other browsers are not necessarily correct.
  • "I thought Flexbox was really ready for primetime.." - It is. 98% of browsers support flexbox.
  • "Centering content horizontally and vertically is something Flexbox should be great at." - It is.

Is there anything I'm missing here?

Yes, the part in the spec where it says that absolutely-positioned flex items ignore flex properties.

4.1. Absolutely-Positioned Flex Children

An absolutely-positioned child of a flex container does not participate in flex layout.

If some browsers choose to apply flex properties to absolutely-positioned flex items, that's their choice. But if a browser ignores flex properties on such elements, that doesn't necessarily mean they are in violation of the spec.

In reading the entire section in the spec, there doesn't appear to be a clear right or wrong.

For a more stable and reliable solution, don't use flex properties to position out-of-flow elements. Use CSS positioning properties instead:

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
  • 2
    I did not see that note about the Absolute positioned elements. I assumed since all browsers but Safari were doing it that Safari was wrong. Lesson learned. Thanks! – Jake Wilson Jun 07 '17 at 18:45
  • 1
    Plus 1 for the (almost :) always well described answer – Asons Jun 07 '17 at 19:22