I followed a tutorial on how to make a table with flex. It works, but I just don't understand why, and it's frustrating me.
This question is in two parts.
PART 1
This is the code:
<style>
ee-row {
display: flex;
flex-direction: row;
flex-wrap: wrap;
width: 100%;
}
ee-cell {
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0;
}
</style>
<ee-table>
<ee-row>
<ee-cell>Header - One .. ... .</ee-cell>
<ee-cell>Header - Two. .. </ee-cell>
<ee-cell>Header - Three</ee-cell>
</ee-row>
<ee-row>
<ee-cell>Row 1 - One. ..... .. ..</ee-cell>
<ee-cell>Row 1 - Two. ... .. .. ... ...... </ee-cell>
<ee-cell>Row 1 - Three..... .. .. . ... .. .. ... ...... </ee-cell>
</ee-row>
<ee-row>
<ee-cell>Row 2 - One</ee-cell>
<ee-cell>Row 2 - Two</ee-cell>
<ee-cell>Row 2 - Three</ee-cell>
</ee-row>
<ee-row>
<ee-cell>Row 3 - One</ee-cell>
<ee-cell>Row 3 - Two</ee-cell>
<ee-cell>Row 3 - Three</ee-cell>
</ee-row>
<ee-table>
Questions:
(1a) Why does that flex-basis: 0
make the columns align nicely? (Try and take it out, and you will get a misaligned table, which is actually what I would expect from flex)
(1b) How do you force the size of a specific column? What if I wanted for example the first column to be as narrow as possible? What if I wanted the third column to be of a specific width?
PART 2
This was actually used to make a responsive table. It actually works quite beautifully. For wide screens, it will show all columns. For medium screens, it will show everything except the "unnecessary" cells. For small screens, it will stack the information without showing the headers.
Here is the shortest way to show it all:
<style>
ee-row {
display: flex;
flex-direction: row;
flex-wrap: wrap;
width: 100%;
}
ee-cell {
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0;
}
@media screen and (max-width: 800px) {
ee-cell {
flex-basis: 100%;
}
ee-cell[header] {
display: none
}
}
@media screen and (max-width: 1200px) {
ee-cell[unnecessary] {
display: none
}
}
</style>
<ee-table>
<ee-row>
<ee-cell header>Header - One .. ... .</ee-cell>
<ee-cell header>Header - Two. .. </ee-cell>
<ee-cell header unnecessary>Header - Three</ee-cell>
</ee-row>
<ee-row>
<ee-cell>Row 1 - One. ..... .. ..</ee-cell>
<ee-cell>Row 1 - Two. ... .. .. ... ...... </ee-cell>
<ee-cell unnecessary>Row 1 - Three..... .. .. . ... .. .. ... ...... </ee-cell>
</ee-row>
<ee-row>
<ee-cell>Row 2 - One</ee-cell>
<ee-cell>Row 2 - Two</ee-cell>
<ee-cell unnecessary>Row 2 - Three</ee-cell>
</ee-row>
<ee-row>
<ee-cell>Row 3 - One</ee-cell>
<ee-cell>Row 3 - Two</ee-cell>
<ee-cell unnecessary>Row 3 - Three</ee-cell>
</ee-row>
<ee-table>
(2a) Is this a good path?
(2b) Is it even possible to convert this to CSS tables and have this "holy grail of table responsiveness" without getting into the flex rabbit hole?
(2c) And in fact, is it a rabbit hole?
I'll do my best to answer your flex questions, but I'd suggest before I start that possibly a more logical and intuitive method to accomplish your goals would be to use grids. Is there a reason you're avoiding those? They layout just like tables and you can control them with much more ease of use.
1a.
Flex-basis indicates the initial size of the flex item (before you starting growing or shrinking to fit the space). If you have flex-basis removed, it will go to the default value which is auto. This means that the initial size of all flex items will be either defined explicitly (ex. 150px) or auto-sized based on the size of its content. By setting it to zero, you're giving all elements the same starting point. So with flex-basis zero, and flex-grow 1, all elements will grow equally to fill the space. Note: flex-grow is just a proportion indicate how much space to fill up when there's leftover space.
1b.
To make the first column as small as possible: (I'm not sure if you have a specific width in mind, if so see the next solution)
/* Leave the rest of the code as is */
ee-cell:nth-child(1) {
flex-basis: auto;
flex-grow: 0;
}
To make the third column a specific width:
/* Leave the rest of the code as is */
ee-cell:nth-child(3) {
width: 100px;
flex-basis:auto;
flex-grow: 0;
}
Both of these solutions set the basis to auto which says the initial size will be specific to this element (either content - in the first example - or specific width - in the second example), then says don't allow this item to grow to help fill the space (flex-grow: 0)
2.
I look at this CSS and my main concern is readability and ease of use (future maintenance). I think you can accomplish your goals with flex, as you've done. But if it were me, I would switch to grids. The code below does the same thing, but also gives you a lot more control (I'll list more options you'll have below) and, in my opinion, makes more sense as you read it:
<style>
ee-table {
display: grid;
grid-template-columns: repeat(3, 1fr);
/* use the line below to accomplish 1b - smallest possible first column, set width last column */
/* grid-template-columns: auto 1fr 100px; */
width: 100%;
}
@media screen and (max-width: 1200px) {
ee-table {
grid-template-columns: 1fr 1fr;
}
ee-cell[unnecessary] {
display: none
}
}
@media screen and (max-width: 800px) {
ee-table {
grid-template-columns: 1fr;
}
ee-cell[header] {
display: none
}
}
</style>
<ee-table>
<ee-cell header>Header - One .. ... .</ee-cell>
<ee-cell header>Header - Two. .. </ee-cell>
<ee-cell header unnecessary>Header - Three</ee-cell>
<ee-cell>Row 1 - One. ..... .. ..</ee-cell>
<ee-cell>Row 1 - Two. ... .. .. ... ...... </ee-cell>
<ee-cell unnecessary>Row 1 - Three..... .. .. . ... .. .. ... ...... </ee-cell>
<ee-cell>Row 2 - One</ee-cell>
<ee-cell>Row 2 - Two</ee-cell>
<ee-cell unnecessary>Row 2 - Three</ee-cell>
<ee-cell>Row 3 - One</ee-cell>
<ee-cell>Row 3 - Two</ee-cell>
<ee-cell unnecessary>Row 3 - Three</ee-cell>
<ee-table>
Additional options with grid