Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to center absolutely positioned children of a flex container in Safari?

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/

like image 320
Jake Wilson Avatar asked Jun 07 '17 16:06

Jake Wilson


2 Answers

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>
like image 181
Asons Avatar answered Oct 26 '22 20:10

Asons


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:

  • Center text over an image in flexbox
like image 42
Michael Benjamin Avatar answered Oct 26 '22 21:10

Michael Benjamin