Search code examples
htmlcsssafari

Why is Safari distorting background-size calculation with CSS grid layout?


I'm encountering an issue with the background-size calculation in Safari when using CSS grid layout. I have a grid container with a background image set using background-image, and I'm trying to size it using background-size with a calculation based on the viewport size and the number of grid columns and rows.

Here's a simplified version of my code:

index.html:

<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Background Size Issue</title>
  <style>
    body {
      margin: 0;
      padding: 0;
    }

    .grid-container {
      width: 100vw;
      height: 100vh;
      display: grid;
      grid-template-columns: repeat(22, minmax(0, 1fr));
      grid-template-rows: repeat(12, minmax(0, 1fr));
      background-image: url('./rectangle.svg');
      background-size: calc(100vw / 22) calc(100vh / 12);
      background-repeat: repeat;
    }
    .child-1 {
      grid-column: span 9 / span 9;
      background-color: rgba(255, 0, 0, 0.5);
    }

    .child-2 {
      grid-column: span 1 / span 1;
      background-color: rgba(134, 82, 48, 0.5);
    }

    .child-3 {
      grid-column: span 1 / span 1;
      background-color: rgba(48, 72, 134, 0.5);
    }

    .child-4 {
      grid-column: span 1 / span 1;
      background-color: rgba(134, 48, 48, 0.5);
    }

    .child-5 {
      grid-column: span 9 / span 9;
      background-color: rgba(0, 255, 0, 0.5);
    }

    .child-6 {
      grid-column: span 1 / span 1;
      background-color: rgba(251, 255, 0, 0.5);
    }


  </style>
</head>
<body>
  <div class="grid-container">
    <!-- Grid items here -->
  </div>
</body>
</html>

rectangle.svg:

<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100" style="border: 1px solid black">
</svg>

In most browsers, including Chrome and Firefox, the background-size calculation seems to work as expected. However, in Safari, the background image appears distorted or doesn't cover the grid container properly.

I've tried adjusting the calculation, experimenting with different units, and checking for any known issues with Safari's rendering of background-size, but haven't found a solution yet.

Browser Version: Safari 17

Expected Behavior: The background image should cover the grid container without distortion, with the size of each repeating image segment calculated based on the viewport size and the grid layout.

Actual Behavior: In Safari, the background image appears distorted or doesn't cover the grid container properly.

Any insights or suggestions on how to resolve this issue would be greatly appreciated. Thank you!

Chrome: chrome Safari: safari


Solution

  • It looks like you can use a repeating-linear-gradient to do the gridlines instead of a SVG. This resolved the missalignment in Safari. It's still not a smooth as Chrome, but it doesn't look broken.

    body {
        margin: 0;
        padding: 0;
    }
    
    .grid-container {
        width: 100vw;
        height: 100vh;
        display: grid;
        background-attachment: fixed;
        grid-template-columns: repeat(22, minmax(0, 1fr));
        grid-template-rows: repeat(12, minmax(0, 1fr));
        background: repeating-linear-gradient(
                to right,
                #000000,
                #000000 1px,
                transparent 1px,
                transparent calc((100 / 22) * 1vw)
            ),
            repeating-linear-gradient(
                to bottom,
                #000000,
                #000000 1px,
                transparent 1px,
                transparent calc((100 / 12) * 1vh)
            );
    }
    .child-1 {
        grid-column: span 9 / span 9;
        background-color: rgba(255, 0, 0, 0.5);
    }
    
    .child-2 {
        grid-column: span 1 / span 1;
        background-color: rgba(134, 82, 48, 0.5);
    }
    
    .child-3 {
        grid-column: span 1 / span 1;
        background-color: rgba(48, 72, 134, 0.5);
    }
    
    .child-4 {
        grid-column: span 1 / span 1;
        background-color: rgba(134, 48, 48, 0.5);
    }
    
    .child-5 {
        grid-column: span 9 / span 9;
        background-color: rgba(0, 255, 0, 0.5);
    }
    
    .child-6 {
        grid-column: span 1 / span 1;
        background-color: rgba(251, 255, 0, 0.5);
    }
    <div class="grid-container">
        <!-- Grid items here -->
        <div class="child-1"></div>
        <div class="child-2"></div>
        <div class="child-3"></div>
        <div class="child-4"></div>
        <div class="child-5"></div>
        <div class="child-6"></div>
        <div class="child-7"></div>
        <div class="child-8"></div>
        <div class="child-9"></div>
    </div>