Search code examples
htmlcsshtml-tablecss-positionz-index

z-index is not working inside table


Why z-index is not working inside table? I have a table with 4 column that one column is positioned outside of table, so that it seem as tabs, but I cannot hidden right side of tabs under table.

Please see this code snippet:

div {
  position: relative;
  z-index: 5;
  width: 70%;
  margin: auto;
  height: 500px;
  background-color: red;
}

table {
  border: none;
  border-spacing: 0 11px;
  width: 100%;
  table-layout: fixed;
}

td.tab {
  background-color: white;
  padding: 15px;
  width: 20%;
  position: absolute;
  z-index: -15;
  right: 90%;
}

td.plan {
  padding: 15px;
  width: 33.3%;
  text-align: center;
}
<div class="bottom">
  <table>
    <tbody>
      <tr>
        <td class="tab">test</td>
        <td class="plan">test</td>
        <td class="plan">test</td>
        <td class="plan">test</td>
      </tr>
      <tr>
        <td class="tab">test</td>
        <td class="plan">test</td>
        <td class="plan">test</td>
        <td class="plan">test</td>
      </tr>
      <tr>
        <td class="tab">test</td>
        <td class="plan">test</td>
        <td class="plan">test</td>
        <td class="plan">test</td>
      </tr>
    </tbody>
  </table>
</div>

fiddle code


EDIT: I no want tabs, I will add our plans to site. I update fiddle, I want remove this shadow on right side of tabs.

enter image description here


Solution

  • Your td tabs are positioned absolutely but relative to the div.bottom.

    Easiest is to remove the z-index on the parent.

    Fiddle: https://jsfiddle.net/abhitalks/bxzomqct/7/

    Snippet:

    div {
      position: relative;
      width: 70%;
      margin: auto;
      height: 500px;
      background-color: red;
    }
    
    table {
      border: none;
      border-spacing: 0 11px;
      width: 100%;
      table-layout: fixed;
    }
    
    td.tab {
      background-color: #eee;
      padding: 15px;
      width: 20%;
      position: absolute;
      z-index: -15;
      right: 90%;
    }
    
    td.plan {
      padding: 15px;
      width: 33.3%;
      text-align: center;
    }
    <div class="bottom">
      <table>
        <tbody>
          <tr>
            <td class="tab">test</td>
            <td class="plan">test</td>
            <td class="plan">test</td>
            <td class="plan">test</td>
          </tr>
          <tr>
            <td class="tab">test</td>
            <td class="plan">test</td>
            <td class="plan">test</td>
            <td class="plan">test</td>
          </tr>
          <tr>
            <td class="tab">test</td>
            <td class="plan">test</td>
            <td class="plan">test</td>
            <td class="plan">test</td>
          </tr>
        </tbody>
      </table>
    </div>


    Better still, to avoid confusions, Just wrap your entire construct in another div and position the tabs relative that outer div.

    div.top {
      position: relative;
      width: 70%;
      margin: auto;
    }
    div.bottom {
      background-color: red; z-index: 50; height: 500px;
    }
    
    table {
      border: none;
      border-spacing: 0 11px;
      width: 100%;
      table-layout: fixed;
    }
    
    td.tab {
      background-color: #eee;
      padding: 15px;
      width: 20%;
      position: absolute;
      z-index: -150;
      right: 90%;
    }
    
    td.plan {
      padding: 15px;
      width: 33.3%;
      text-align: center;
    }
    <div class="top">
    <div class="bottom">
      <table>
        <tbody>
          <tr>
            <td class="tab">test</td>
            <td class="plan">test</td>
            <td class="plan">test</td>
            <td class="plan">test</td>
          </tr>
          <tr>
            <td class="tab">test</td>
            <td class="plan">test</td>
            <td class="plan">test</td>
            <td class="plan">test</td>
          </tr>
          <tr>
            <td class="tab">test</td>
            <td class="plan">test</td>
            <td class="plan">test</td>
            <td class="plan">test</td>
          </tr>
        </tbody>
      </table>
    </div>
    
    </div>

    Your Fiddle: https://jsfiddle.net/abhitalks/bxzomqct/6/


    Why this happens:

    This is because of the stacking context that is generated by the positioned elements. Although, the stacking order within a stacking context specifies the negative z-index values to be painted first, it is however limited to that same stacking context.

    Reference: https://www.w3.org/TR/CSS2/zindex.html

    Reading: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context

    So, with a negative z-index, your tabs should appear behind its parents (div.bottom in this case). And it will, as it is in same stacking context.

    However, as soon as you give a z-index value to the div.bottom, it creates a new stacking context which confines all of its child elements to a particular place in the stacking order. This causes it not to appear in front of the tabs irrespective of the z-index of tabs.

    Note that the specs do not explain this verbatim, and has to be referred to with other references and docs to develop an understanding. It's tricky.

    Here is a good article you can refer to: https://philipwalton.com/articles/what-no-one-told-you-about-z-index/