How can I avoid a “Flash of Unstyled Content” using fixed-width cells in CSS Tables?

前端 未结 4 2098
感动是毒
感动是毒 2021-02-14 07:32

My web GUI\'s layout is partially driven by CSS tables. This is mainly because I want the \"cells\" to have the same height under all situations without any massive headaches su

相关标签:
4条回答
  • 2021-02-14 08:25

    would this be a reasonable fix?

    #tbl      { display: table; width: 200px; border: 1px solid black; }
    #tbl-row  { display: flex;  }
    #tbl-col1,
    #tbl-spc,
    #tbl-col2 {
       flex:0;
       overflow:hidden
    }
    
    #tbl-col1 { flex-basis: 50px;  background-color: red; }
    #tbl-col2 { flex-basis: 150px; background-color: blue; }
    <div id="tbl">
        <div id="tbl-row">
            <div id="tbl-col1">LHS-LHS-LHS-LHS</div>
            <div id="tbl-spc"></div>
            <div id="tbl-col2">RHS</div>
        </div>
    </div>

    EDIT:

    here's a fiddle with prefixes and fallback

    0 讨论(0)
  • 2021-02-14 08:30

    Wanna try this - JS Fiddle

    .tbl{display:table;}
    .fixed{width: 200px; border: 1px solid black; }
    .tblRow { display: table-row; }
    .tblCol{ display: table-cell; }
    .col1 .tbl { width: 50px;  background-color: red; }
    .col2 .tbl { width: 150px; background-color: blue; display:none; }
    

    As I said in my comment, Play with the table width. So here it is. Remove display:none from style line .col2 .tbl { width: 150px; background-color: blue; display:none; } and all you can see. this is perhaps what you want.

    0 讨论(0)
  • 2021-02-14 08:34

    What I like to do in similar cases (for example html emails) is to pre-define column widths using empty cells this way:

    .tbl {
        display: table;
        width: 200px;
        border: 1px solid black;
        color: #fff;
    }
    .tbl-row {
        display: table-row;
    }
    .tbl-cell {
        display: table-cell;
    }
    .tbl-col1 {
        width: 50px;
        background-color: red;
    }
    .tbl-col2 {
        background-color: blue;
    }
    <h3>Pre-define columns width by adding additional row</h3>
    
    <div class="tbl">
        <div class="tbl-row tbl-format">
            <div class="tbl-cell tbl-col1"></div>
            <div class="tbl-cell tbl-col2"></div>
        </div>
        <div class="tbl-row">
            <div class="tbl-cell tbl-col1">LHS</div>
            <div class="tbl-cell tbl-col2">RHS</div>
        </div>
    </div>

    That formatting column is invisible if there is no content inside cells, but still it tells browser the way table should be formatted.

    0 讨论(0)
  • 2021-02-14 08:37

    That's because, by default, tables use the automatic table layout.

    The CSS 2.1 spec doesn't define that layout mode, but suggests a (non-normative) algorithm, which reflects the behavior of several popular HTML user agents.

    According to that algorithm,

    If the used width is greater than MIN, the extra width should be distributed over the columns.

    However, it doesn't explain how it should be distributed. In fact, your attempt of inserting a "spacer" element works perfectly on Firefox, but not on Chrome.

    Instead, you may want to try the fixed table mode, which is properly defined in the spec (and thus more reliable), is usually faster, and solves the problem too:

    In the fixed table layout algorithm, the width of each column is determined as follows:

    1. A column element with a value other than auto for the width property sets the width for that column.
    2. Otherwise, a cell in the first row with a value other than auto for the width property determines the width for that column. If the cell spans more than one column, the width is divided over the columns.
    3. Any remaining columns equally divide the remaining horizontal table space (minus borders or cell spacing).

    According to the 3rd point, the spacer element will receive the remaining 150px before the last cell has been loaded. And will receive the remaining 0px once loaded.

    So you need

    #tbl { table-layout: fixed; }
    

    .tbl {
      display: table;
      table-layout: fixed;
      width: 200px;
      border: 1px solid black;
    }
    .tbl-row {
      display: table-row;
    }
    .tbl-col1,
    .tbl-spc,
    .tbl-col2 {
      display: table-cell;
    }
    .tbl-col1 {
      width: 50px;
      background-color: red;
    }
    .tbl-col2 {
      width: 150px;
      background-color: blue;
    }
    .hide {
      display: none;
    }
    While parsing the first cell:
    <div class="tbl">
      <div class="tbl-row">
        <div class="tbl-col1">LHS</div>
        <div class="tbl-spc hide"></div>
        <div class="tbl-col2 hide">RHS</div>
      </div>
    </div>
    
    While parsing the spacer:
    <div class="tbl">
      <div class="tbl-row">
        <div class="tbl-col1">LHS</div>
        <div class="tbl-spc"></div>
        <div class="tbl-col2 hide">RHS</div>
      </div>
    </div>
    
    While parsing the second cell:
    <div class="tbl">
      <div class="tbl-row">
        <div class="tbl-col1">LHS</div>
        <div class="tbl-spc"></div>
        <div class="tbl-col2">RHS</div>
      </div>
    </div>

    However, there is still a problem: the spacer won't be displayed until the first cell has been parsed completely.

    That means the spacer must be loaded first, but must not be the first to be displayed. Sadly, the CSS table layout does not allow to reorder the cells. But it can be achieved by removing the non-semantic spacer from the HTML and using an ::after pseudo-element instead:

    #tbl-row:after {
      content: '';
      display: table-cell;
    }
    

    .tbl {
      display: table;
      table-layout: fixed;
      width: 200px;
      border: 1px solid black;
    }
    .tbl-row {
      display: table-row;
    }
    .tbl-row:after {
      content: '';
      display: table-cell;
    }
    .tbl-col1,
    .tbl-col2 {
      display: table-cell;
    }
    .tbl-col1 {
      width: 50px;
      background-color: red;
    }
    .tbl-col2 {
      width: 150px;
      background-color: blue;
    }
    .hide {
      display: none;
    }
    While parsing the first cell:
    <div class="tbl">
      <div class="tbl-row">
        <div class="tbl-col1">LHS</div>
        <div class="tbl-col2 hide">RHS</div>
      </div>
    </div>
    
    While parsing the second cell:
    <div class="tbl">
      <div class="tbl-row">
        <div class="tbl-col1">LHS</div>
        <div class="tbl-col2">RHS</div>
      </div>
    </div>

    0 讨论(0)
提交回复
热议问题