2

I want to replace a table with flexbox elements.

Basically from this:

<table>
  <tr>
    <td>row_1.col_1</td>
    <td>row_1.col_2</td>
  </tr>
  <tr>
    <td>row_2.col_1.with_longer_content</td>
    <td>row_2.col_2</td>
  </tr>
</table>

To this:

<div>
  <div>
    <div>row_1.col_1</div>
    <div>row_1.col_2</div>
  </div>
  <div>
    <div>row_2.col_1.with_longer_content</div>
    <div>row_2.col_2</div>
  </div>
</div>

In the case of the table, the first row's first cell will expand in width so that the second cell row_1.col_2 will align properly with the cell beneath it row_2.col_2

-------------------------------------------------
| row_1.col_1                     | row_1.col_2 |
| row_2.col_1.with_longer_content | row_2.col_2 |
-------------------------------------------------

How can I do the same with divs, using flexbox, so that the first column consumes the least amount of width, but the second column is still aligned?

Is this even possible?

The reason why I want to do this is because I want each row to be a Quasar q-card, but the elements in there should align with the cards above and below, yet still consume the least amount of space and not be width-controlled through the "12-column"-grid-system.

Basically like this, where I need the badges and inputs to be aligned as if it were a table (I cannot use a q-table, and -- due to the use of UMD -- also not a q-markup-table):

<q-card>
  <q-card v-for='element in elements'>
    <q-badge>{{element.badge}}</q-badge>
    <q-input v-model='element.text'></q-input>
  </div>
</div>
pretzelhammer
  • 13,874
  • 15
  • 47
  • 98
Daniel F
  • 13,684
  • 11
  • 87
  • 116
  • if you want divs to behave like a table, why not use display table instead of flex? Also if it is tabular data, any reason to remove the table? – Pete Feb 15 '21 at 13:38
  • Look this https://stackoverflow.com/questions/46824086/how-do-i-get-auto-width-columns-in-bootstrap-4 – Ricardo de Paula Feb 15 '21 at 13:39

3 Answers3

2

Instead of flex, it would probably be better to use display:table

div {
  display: table;
}

div>div {
  display: table-row;
}

div>div>div {
  display: table-cell;
}
<div>
  <div>
    <div>row_1.col_1</div>
    <div>row_1.col_2</div>
  </div>
  <div>
    <div>row_2.col_1.with_longer_content</div>
    <div>row_2.col_2</div>
  </div>
</div>
Pete
  • 57,112
  • 28
  • 117
  • 166
  • I just want to point out that this creates an issue when the "row"-divs should have spacing in between, like when having a `box-shadow` applied to them, which would get covered by the next row. It is possible to wrap the row in a ` – Daniel F Feb 15 '21 at 14:53
  • 1
    @DanielF if you want spacing between rows, you can use `border-spacing: 0 10px;` to add some spacing (this works like old school cell spacing) - see this post: https://stackoverflow.com/questions/1264187/css-how-do-i-create-a-gap-between-rows-in-a-table – Pete Feb 15 '21 at 15:12
1

Using display: flexbox you can do this by organizing the data by column instead of by row. Using display: table you can maintain the structure of the table. Examples:

.flex-table {
  display: flex;
}

.column {
  padding: 4px;
}

.table {
  display: table;
}

.table-row {
  display: table-row;
}

.table-cell {
  display: table-cell;
  padding: 0 4px;
}
<h3>table</h3>

<table>
  <tr>
    <td>row_1.col_1</td>
    <td>row_1.col_2</td>
  </tr>
  <tr>
    <td>row_2.col_1.with_longer_content</td>
    <td>row_2.col_2</td>
  </tr>
</table>

<h3>flexbox table</h3>

<div class="flex-table">
  <div class="column">
    <div>row_1.col_1</div>
    <div>row_2.col_1.with_longer_content</div>
  </div>
  <div class="column">
    <div>row_1.col_2</div>
    <div>row_2.col_2</div>
  </div>
</div>

<h3>display table</h3>

<div class="table">
  <div class="table-row">
    <div class="table-cell">row_1.col_1</div>
    <div class="table-cell">row_1.col_2</div>
    
  </div>
  <div class="table-row">
    <div class="table-cell">row_2.col_1.with_longer_content</div>
    <div class="table-cell">row_2.col_2</div>
  </div>
</div>
pretzelhammer
  • 13,874
  • 15
  • 47
  • 98
  • I did think about this, but this will mess with iterating through each object via `v-for='element in elements'` (but, on a second thought, maybe not that much, since I will only have to iterate on every column.) – Daniel F Feb 15 '21 at 13:45
  • @DanielF I've updated my answer with an alternative solution which maintains the structure of the data in the markup, please take another look. – pretzelhammer Feb 15 '21 at 13:47
  • Thanks. Because my issue with the first approach is that I can't iterate through each column, since each row should be one `q-card` element. – Daniel F Feb 15 '21 at 13:49
1
<style>
    .row {
        display: -ms-flexbox;
        display: flex;
        -ms-flex-wrap: wrap;
        flex-wrap: wrap;
        margin-right: -15px;
        margin-left: -15px;
    }

    .col {
        -ms-flex-preferred-size: 0;
        flex-basis: 0;
        -ms-flex-positive: 1;
        flex-grow: 1;
        max-width: 100%;
        position: relative;
        width: 100%;
        padding-right: 15px;
        padding-left: 15px;
    }

    .text-wrap {
        white-space: normal !important;
    }
</style>

<div>
    <div class="row">
        <div class="col text-wrap">row_1.col_1</div>
        <div class="col text-wrap">row_1.col_2</div>
    </div>
    <div class="row">
        <div class="col text-wrap">row_2.col_1.with_longer_content</div>
        <div class="col text-wrap">row_2.col_2</div>
    </div>
</div>

Try writing like this & if you don't want to use the above styles use the bootstrap css link instead.