Safari does not display SVG when using flexbox to center it

Viewed 614

I’ve got an issue with Safari, SVG, and flexbox

The goal is to have a responsive SVG, that keeps the aspect ratio (16:9). Moreover, the SVG should always sit in the vertical and horizontal center of the screen. The following code works well for all browsers except for Safari... I tried different vendor prefixes, but I have no clue why the SVG is not showing up... Any ideas?

You can test the flawed behavior in the code snippet below. Safari will show a blank page. Other browsers will show a 16:9, always centered teal rectangle.

* {
  margin: 0;
  padding: 0;
  overflow: hidden;
}

body {
  height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
}

svg {
  background-color: teal;
  max-height: 100vh;
}
<svg viewBox="0 0 1920 1080">
</svg>

Update

Just some clarification. Depending on the aspect ratio of the viewport, the SVG is either in horizontal center or vertical center. Only when the screen aspect ratio is exactly 16:9 it matches the SVS’s viewBox (see viewBox="0 0 1920 1080"), and it would show without any borders (letterboxes). That is my goal, and solution should work in all browsers—no matter how it is done.

enter image description here

3 Answers

Here is a vanilla CSS example ...

It is done in modern styling technique using CSS functions min(...) and var(...). As the styling is done for a fullsize viewscreen the sizings can be calculated based on aspect-ratio of the svg/image and actual vW and vHunits. Modern centering is done by using flexbox as well.

It should run in all modern browsers.

Please check the example:

* {
  margin: 0;
  padding: 0;
  overflow: hidden;
}

body {
  height: 100vH;
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-pack: center;
      -ms-flex-pack: center;
          justify-content: center;
  -webkit-box-align: center;
      -ms-flex-align: center;
          align-items: center;
}

svg {
  --aspectRatio: 1.7777777;
  width: min(100vW, (100vH * var(--aspectRatio)));
  height: min(100vH, (100vW / var(--aspectRatio)));
  background-color: teal;
}
<svg viewBox="0 0 1920 1080"></svg>

Here is javascript based solution:

const svg = document.querySelector("svg");
const wByH = 16 / 9;

function computeSVGDimen() {
  const width = window.innerWidth;
  const height = window.innerHeight;

  const currentRatio = width / height;

  const computedWidth = height * wByH;
  const computedHeight = width * (1 / wByH);

  if (currentRatio < wByH) {
    svg.style.width = `${width}px`;
    svg.style.height = `${computedHeight}px`;
  } else {
    svg.style.width = `${computedWidth}px`;
    svg.style.height = `${height}px`;
  }
}

computeSVGDimen();
window.onresize = computeSVGDimen;
* {
  margin: 0;
  padding: 0;
  overflow: hidden;
}

body {
  height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
}

svg {
  background-color: teal;
}
<svg viewBox="0 0 1920 1080"></svg>

use this in .css file

@supports (-webkit-touch-callout: none) {svg {background-color: teal;}}
Related