Utkarsh Barsaiyan
Utkarsh Barsaiyan

Reputation: 335

Absolutely positioned div inside table not aligning correctly

I have a table that is centered.

I want to draw a line inside the table, but the line shows up on the left side of the table.

table {
  height: 450px;
  width: 450px;
  left: 50%;
  transform: translateX(-50%);
  text-align: center;
  table-layout: fixed;
  position: relative;
}
#winLine {
  height: 100%;
  width: 0px;
  border: 4px solid blue;
  border-radius: 10px;
  left: 50px;
  position: absolute;
}
<table>
  <div id="winLine"></div>
  <tr>
    <td id="0"></td>
    <td id="1"></td>
    <td id="2"></td>
  </tr>
  <tr>
    <td id="3"></td>
    <td id="4"></td>
    <td id="5"></td>
  </tr>
  <tr>
    <td id="6"></td>
    <td id="7"></td>
    <td id="8"></td>
  </tr>
</table>

Upvotes: 2

Views: 355

Answers (2)

Michael Benjamin
Michael Benjamin

Reputation: 371013

A div element cannot be a child of a table element. It is invalid HTML.

In terms of allowable content of a table element, here's the relevant language from the spec:

In this order: optionally a caption element, followed by zero or more colgroup elements, followed optionally by a thead element, followed optionally by a tfoot element, followed by either zero or more tbody elements or one or more tr elements, followed optionally by a tfoot element (but there can only be one tfoot element child in total), optionally intermixed with one or more script-supporting elements.

source: https://www.w3.org/TR/html5/tabular-data.html#the-table-element

So, no divs allowed. As a result, the browser forces the table element to start after the div.

Here's what's happening in Chrome (via dev tools):

enter image description here

The absolutely positioned div is now positioned relative to the initial containing block (html element), and is offset 50px from the left edge of the viewport.

Instead, consider a pseudo-element to make your line:

table {
  height: 450px;
  width: 450px;
  left: 50%;
  transform: translateX(-50%);
  text-align: center;
  table-layout: fixed;
  position: relative;
  border: 2px dashed red;
}
table::before {
  height: 100%;
  width: 0px;
  border: 4px solid blue;
  border-radius: 10px;
  left: 50px;
  position: absolute;
  content: "";
}
<table>
  <tr>
    <td id="0"></td>
    <td id="1"></td>
    <td id="2"></td>
  </tr>
  <tr>
    <td id="3"></td>
    <td id="4"></td>
    <td id="5"></td>
  </tr>
  <tr>
    <td id="6"></td>
    <td id="7"></td>
    <td id="8"></td>
  </tr>
</table>

Upvotes: 1

Ori Drori
Ori Drori

Reputation: 191936

You can't put a <div> inside a <table>, and use it as the context of positioning. Create a wrapper <div>, and use it to position the line:

.wrapper {
  position: relative; 
  height: 450px;
  width: 450px;
  margin: 0 auto;
}

table {
  height: 100%;
  width: 100%;
  text-align: center;
  table-layout: fixed;
  position: relative;
  border: 1px solid black;
}
#winLine {
  height: 100%;
  width: 0px;
  border: 4px solid blue;
  border-radius: 10px;
  left: 50px;
  position: absolute;
}
<div class="wrapper">
  <div id="winLine"></div>
  <table>
    <tr>
      <td id="0"></td>
      <td id="1"></td>
      <td id="2"></td>
    </tr>
    <tr>
      <td id="3"></td>
      <td id="4"></td>
      <td id="5"></td>
    </tr>
    <tr>
      <td id="6"></td>
      <td id="7"></td>
      <td id="8"></td>
    </tr>
  </table>
</div>

Upvotes: 1

Related Questions