Search code examples
htmlcsshtml-tablecss-tables

Center text in an HTML table across group of cells


I would like to, once having an HTML table, be able to take a group of cells and write a text (in this case, a single character) centered both vertically and horizontally across that group of cells, just as in the image below.

HTML table centered text

I have explored the possibility of writing the text in the first (top-left) td and then use the overflow CSS property over that td element in order for the text to go over the limits of the td. However, this would not work for centering the text vertically (across tr).

Is there any way to do this just using a simple HTML table and CSS, or should I consider using a canvas in order to overlap a text over the table?


Solution

  • Solution 1:
    Use rowspan and colspan, together with valign and align (which are specific <table> centering attributes):

    td {
      border: 1px solid #eee;
      padding: 1rem;
    }
    td[rowspan] {
      background-color: rgba(255,0,0,.07);
      border: 1px solid red;
    }
    <table>
       <tr>
         <td rowspan="2" colspan="2" valign="center" align="center">
         A
         </td>
         <td>x</td>
       </tr>
       <tr>
        <td>x</td>
      </tr>
      <tr>
        <td>x</td>
        <td>x</td>
        <td>x</td>
      </tr>

    Solution 2:
    The hacky way I was describing in the comment:

    td {
      border: 1px solid #eee;
      padding: 1rem;
    }
    .hacky-td {
      position: relative;
      overflow: visible;
    }
    .hacky-content {
      font-size: 3rem;
      position: absolute;
      transform: translate(-50%,-50%);
      border: 1px solid red;
      padding: 1rem;
      background-color: rgba(255,0,0,.07);
      left: -1px; /* should be 0, it's 1 because of the border */
      top: -1px; /* should be 0, it's 1 because of the border */
    }
    <table>
       <tr>
         <td></td>
         <td></td>
         <td>x</td>
       </tr>
       <tr>
         <td></td>
         <td class="hacky-td"><div class="hacky-content">A</div></td>
         <td>Lorem<br>ipsum,<br>dolor<br>sit<br>amet</td>
      </tr>
      <tr>
        <td>x</td>
        <td>Lorem ipsum, dolor sit amet</td>
        <td>x</td>
      </tr>

    You'll notice the A will remain centered on the junction regardless of the size of each of the 4 cells.


    Solution 3: - CSS Grid
    If you want to center across the entire area, you'll have to use CSS grid, which makes it kind of trivial:

    .grid {
      display: grid;
      grid-template: 
        "a b c" auto
        "d e f" auto
        "g h i" auto
        /1fr 2fr 1fr;
        grid-gap: 2px;
    }
    .grid > *:not(.overlay) {
      padding: 1rem;
      content: 'x';
      display: flex;
      align-items: center;
      justify-content: center;
      border: 1px solid #eee;
    }
    .a { grid-area: a;}
    .b { grid-area: b;}
    .c { grid-area: c;}
    .d { grid-area: d;}
    .e { grid-area: e;}
    .f { grid-area: f;}
    .g { grid-area: g;}
    .h { grid-area: h;}
    .i { grid-area: i;}
    .overlay {
      grid-area: 1/1/3/3;
      display: flex;
      align-items: center;
      justify-content: center;
      padding: .5rem;
    }
    .overlay span {
      border: 1px solid red;
      font-size: 3rem;
      font-weight: bold;
      background-color: rgba(255,0,0,.07);
      width: 100%;
      height: 100%;
      display: flex;
      align-items: center;
      justify-content: center;
    }
    <div class="grid">
      <div class="a">x</div>
      <div class="b">Lorem<br>ipsum<br>dolor<br>sit<br>amet</div>
      <div class="c">x</div>
      <div class="d">x</div>
      <div class="e">x</div>
      <div class="f">x</div>
      <div class="g">x</div>
      <div class="h">Amet sit door ipsum lorem, ipsum dolor sit amet.</div>
      <div class="i">x</div>
      <div class="overlay"><span>A</span></div>
    </div>


    Solution 4: - Centering across the entire table

    This one's a general centering method and it works with anything (you could put any other element instead of the <table>):

    .relative {
      position: relative;
      display: inline-block;
    }
    .overlay {
      position: absolute;
      top: 0.5rem;
      bottom: 0.5rem;
      left: 0.5rem;
      right: 0.5rem;
      display: flex;
      align-items: center;
      justify-content: center;
      background-color: rgba(255,0,0,.07);
      font-size: 2.4rem;
      border: 1px solid red;
    }
    td {
      padding: 1rem;
      border: 1px solid #eee;
    }
    <div class="relative">
      <table>
        <tr>
          <td>x</td>
          <td>x</td>
          <td>x</td>
        </tr>
        <tr>
          <td>x</td>
          <td>x</td>
          <td>x</td>
        </tr>
        <tr>
          <td>x</td>
          <td>x</td>
          <td>x</td>
        </tr>
      </table>
      <div class="overlay">
        A
      </div>
    </div>