htmlcssimagebackgroundalignment

Seamless alignment of background images?


I would like to highlight some cells in a table by underlying them with hatching patterns.

If two cells with the same pattern are next to each other, the pattern should cover both cells seamlessly.

table.demo {
  border: 1px solid blue;
  border-collapse: separate;
  border-spacing: 0;
  table-layout: fixed;
  text-align: center;
  width: 100%;
}

table.demo td {
  height: 100px;
}

table.demo td.stripes {
  /* Using  background-attachment: fixed;  is _not_ the desired solution, because the background no longer scrolls alogn with the table. */
  /* background-attachment: fixed; */

  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAFCAYAAABmWJ3mAAAAIElEQVQImWNggIKOjo7/HR0d/xmQAbIAnI2hCocYYQAATEQPi+UvdB4AAAAASUVORK5CYII=);
}

table.demo td.B { background-color: #ffe; }
table.demo td.C { background-color: #efe; }
table.demo td.E { background-color: #eef; }
table.demo td.F { background-color: #fee; }
<table class="demo">
  <tr>
    <td class="stripes A">A</td>
    <td class="stripes B">B</td>
    <td class="stripes C">C</td>
  </tr>
  <tr>
    <td class="stripes D">D</td>
    <td class="stripes E">E</td>
    <td class="stripes F">F</td>
  </tr>
  <tr>
    <td class="stripes G">G</td>
    <td>H</td>
    <td class="stripes I">I</td>
  </tr>
</table>

The details depend on the size of the preview area, so you may have to make the browser window larger or smaller to see the problem. Here is an enlarged screenshot of a place where four cells meet, demonstrating the problem:

mismatched background image where four cells meet

The desired result and goal of this question is:

enter image description here

Already tried:

Thus, the question is how the same seamless alignment can be achieved but keep the origin fixed to the <body>, the <table> element or anything else so that the hatches scroll along with the rest of the page contents.


Solution

  • You can simulate a fixed background attachment to only the table element by using pseudo-element that you position relatively to the whole table then using clip-path on the table cell to hide the overflowing part

    table.demo {
      border: 1px solid blue;
      border-collapse: separate;
      border-spacing: 0;
      table-layout: fixed;
      text-align: center;
      width: 100%;
      position: relative; /* relative here */
      z-index: 0;
    }
    
    table.demo td {
      height: 100px;
      clip-path: inset(0); /* this is important */
    }
    
    /* the background */
    table.demo td.stripes:before {
      content:"";
      position: absolute;
      z-index: -1;
      inset: 0; 
      background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAFCAYAAABmWJ3mAAAAIElEQVQImWNggIKOjo7/HR0d/xmQAbIAnI2hCocYYQAATEQPi+UvdB4AAAAASUVORK5CYII=);
    }
    /**/
    
    table.demo td.B { background-color: #ffe; }
    table.demo td.C { background-color: #efe; }
    table.demo td.E { background-color: #eef; }
    table.demo td.F { background-color: #fee; }
    <table class="demo">
      <tr>
        <td class="stripes A">A</td>
        <td class="stripes B">B</td>
        <td class="stripes C">C</td>
      </tr>
      <tr>
        <td class="stripes D">D</td>
        <td class="stripes E">E</td>
        <td class="stripes F">F</td>
      </tr>
      <tr>
        <td class="stripes G">G</td>
        <td>H</td>
        <td class="stripes I">I</td>
      </tr>
    </table>