Flexbox in table cell appears in the vertical middle - html

I am using flexbox in a table.
The table has 2 columns, each with one cell.
The left cell is very big, and has a height of maybe 189%.
My CSS is as follows:
#openemail {
display: flex;
flex-flow: column;
height: 100%;
}
#openemail>#header {
flex: 0 1 auto;
}
#openemail>#body {
flex: 1 1 auto;
}
<table id="app">
<tr>
<td>
<div id="emailslist"><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/></div>
</td>
<td>
<div id="openemail">
<div id="header">SSS</div>
<div id="body">more SSS</div>
</div>
</td>
</tr>
</table>
As you can see, the flex container ends up in the middle, and is hard to find. My question is: how can I change my CSS so that the flex container is at the top of my table cell?

Would adding vertical-align: top to the table cell do what you want it to do? Like this:
<table id="app">
<tr>
<td>
<div id="emailslist"><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/></div>
</td>
<td style="vertical-align: top;">
<div id="openemail"><div id="header">SSS</div><div id="body">more SSS</div></div>
</td>
</tr>
</table>

RECOMMENDED:
Applying vertical-align: top to <td> seems to be the optimal solution in 2018, which is fully supported in CSS3 and HTML5. Here's a working sample:
table, th, td {
border: 1px solid black;
}
#openemail {
display: flex;
flex-flow: column;
height: 100%;
}
#openemail>#header {
flex: 0 1 auto;
}
#openemail>#body {
flex: 1 1 auto;
}
<table id="app">
<tr>
<td>
<div id="emailslist">
placeholder<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
</div>
</td>
<td style="vertical-align: top">
<div id="openemail"><div id="header">SSS</div><div id="body">more SSS</div></div>
</td>
</tr>
</table>
To learn more about the vertical-align style: https://www.w3schools.com/cssref/pr_pos_vertical-align.asp
NOT RECOMMENDED:
The following solution could also work if you are using older versions of HTML: setting the valign attribute of <td> to be top. It looks something like this:
table, th, td {
border: 1px solid black;
}
#openemail {
display: flex;
flex-flow: column;
height: 100%;
}
#openemail>#header {
flex: 0 1 auto;
}
#openemail>#body {
flex: 1 1 auto;
}
<table id="app">
<tr>
<td>
<div id="emailslist">
placeholder<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
</div>
</td>
<td valign="top">
<div id="openemail"><div id="header">SSS</div><div id="body">more SSS</div></div>
</td>
</tr>
</table>
To learn more about the valign attribute: https://www.w3schools.com/tags/att_td_valign.asp
Hope this helps!

Since you're dealing with table cells, the vertical-align property comes into play. This property applies to inline-level and table-cell elements only.
The default value of the vertical-align property, according to the spec, is baseline. However, major browsers tend to use the middle value instead.
In any case, the content of your table cell is vertically centered.
You can override this setting with vertical-align: top.
More details: Default value of vertical-align for table cells

Related

Make HTML Table behave like `justify-content: space-between`

is there a way to make table columns behave like the justify-content: space-between from flexbox.
I want the first and the last column be at the end and the start and the rest should be fitted in the middle of these two.
You can achieve this behavior using a combination of CSS and HTML
<table class="table">
<tr>
<td class="first">First Column</td>
<td class="middle">Middle Column 1</td>
<td class="middle">Middle Column 2</td>
<td class="last">Last Column</td>
</tr>
</table>
.table {
width: 100%;
table-layout: fixed;
}
.first {
text-align: left;
}
.last {
text-align: right;
}
.middle {
text-align: center;
width: 25%;
}

Gridbox: Shrink contents of grid row to make two equal height rows

Assume I have a gridbox with 4 columns and 1 row. Parent container 1 & 2 are children of this gridbox. Parent container1 has a colspan of 3 and container2 has a colspan of 1 column. Both container have multiple child components, that are responsive and change size on window resize. Child 5 components has a table inside, that contains over 250+ records. The goal is to make this table scrollable, with perfectly equal content height of gridbox and without knowing any dimensions of parent or child containers.
So parent container2 has to be same height as parent container1, therefore something has to be done with child5
JSFiddle example
Expected layout: (Same row height and scrollable table)
Current layout: (Unequal content height, table is not scrollable)
I tried implementing flexbox for this scenario, but it seemed to make things harder. I also tried adding display: flex and flex: flex-shrink to the child5 container but with no results whatsoever.
I know I can programmatically take the height of container1 and calculate the needed height of child5 but I feel like there's more elegant solution using CSS + I don't wanna add too much event listeners on window resize.
Would love to take a look at your suggestions.
It is possible to apply display: flex for your .container1 class and use flex property:
*, html, body {
box-sizing: border-box;
margin: 0;
}
body {
font-family: sans-serif;
font-weight: 600;
}
.grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-gap: 5px;
border: 1px solid black;
padding: 5px;
}
.container1 {
grid-column: 1/4;
background: blue;
display: flex;
flex-direction: column;
height: 100%;
flex: 1;
}
.container1 div {
flex: 1;
}
.container2 {
background: red;
}
.child, .child1, .child3, .child5 {
border: 1px solid black;
padding: 15px;
background: gray
}
.container1, .container2 {
border: 1px solid black;
padding: 5px;
}
.table, th, td {
border: 1px solid black;
width: 100%;
}
.child1, .child3 {
padding: 40px 15px 40px 15px;
}
.child5 {
overflow-Y: scroll;
}
<div class="grid">
<div class="container1">
parent container 1
<div class="child1">
child 1
</div>
<div class="child">
child 2
</div>
<div class="child3">
child 3
</div>
</div>
<div class="container2">
parent container 2
<div class="child">
child 4
</div>
<div class="child5">
child 5
<table>
<tr>
<th>prop</th>
<th>value</th>
</tr>
<tr>
<th>prop</th>
<th>value</th>
</tr>
<tr>
<th>prop</th>
<th>value</th>
</tr>
<tr>
<th>prop</th>
<th>value</th>
</tr>
<tr>
<th>prop</th>
<th>value</th>
</tr>
<tr>
<th>prop</th>
<th>value</th>
</tr>
<tr>
<th>prop</th>
<th>value</th>
</tr>
<tr>
<th>prop</th>
<th>value</th>
</tr>
<tr>
<th>prop</th>
<th>value</th>
</tr>
<tr>
<th>prop</th>
<th>value</th>
</tr>
<tr>
<th>prop</th>
<th>value</th>
</tr>
<tr>
<th>prop</th>
<th>value</th>
</tr>
</table>
</div>
</div>
</div>

Re-position image and then shrink it while screen gets smaller, no media queries

So, basically I have a table row with 2 cells, with the first cell (on the left) containing text, and the right one containing an image. While the screen gets smaller and smaller, I want the image to eventually move under the text. After some research I finally found and understood how the display and flex property works and have solved that issue.
In the table row properties I have inserted
display: flex;
flex-wrap: wrap;
and for each cell you put flex: 1 1 10ch; for example. I have found this here, which certainly explains more and better.
So, now what I want is when the image is repositioned under the text, to shrink when the screen gets smaller than the image itself. The image's size is fixed because with percentage is just gets smaller and does not reposition. I have also tried max-width but it doesn't change anything I think.
<div>
<table style="width: 100%;">
<tbody>
<tr style="display: flex; flex-wrap: wrap;">
<td style="text-align: left; vertical-align: middle; padding: 0 3% 0 0; flex: 3 1 50ch;">
<p>Some random text. Normally, the text is much more.</p>
</td>
<td align="justify" style="padding: 0.5%; flex: 1 1 10ch;"><img src="https://hatrabbits.com/wp-content/uploads/2017/01/random.jpg" width="500" /></td>
</tr>
</tbody>
</table>
</div>
I also lose the vertical alignment for the text. Is there any way to align it to the middle again?
You can apply the object-fit property on the image,
this will resize the image to fit the container:
img{
object-fit: cover;
width: 100%;
height: 100%;
}
Don't use ch as units here. It can be misleading, and doesn't work reliably with variable width fonts. With images, it can be even worse. Stick to em, rem, or even px. I used the latter.
Flex is more flexible than the example had shown you. See the comments in the code.
.tbl {
width: 100%;
}
.row {
display: flex;
flex-wrap: wrap;
}
.first {
text-align: left;
vertical-align: middle;
padding: 0 3% 0 0;
flex: 3 1 auto; /*don't care about the basis of this element as it always grows and shrinks as required*/
}
.second {
padding: 0.5%;
flex: 0 1 500px; /* never grow, only shrink when required, 500px basis (from your example) */
}
.second img {
width: 100%; /*The image should always be as wide as its parent allows to be.*/
}
<div>
<table class="tbl">
<tbody>
<tr class="row">
<td class="first">
<p>Some random text. Normally, the text is much more.</p>
</td>
<td align="justify" class="second"><img src="https://hatrabbits.com/wp-content/uploads/2017/01/random.jpg" /></td>
</tr>
</tbody>
</table>
</div>

How to create multiple columns in a page that continues the previus colum content. - HTML, CSS

First, sorry for any grammatical mistakes, I'm not an expert in English.
So, what I need is to separate my page in three colums that suport one table, when this table reachs to a, for example, height: 1000px in a colum it will go to the other colum.
I tried to do an quick example in Paint:
Everything that I tried just separate the page in three columns but they don't interact with each other as I want. There's any way to do that?
P.S: This table is created from my database, so it's not a fixed table.
I feel at some point when it's a standard, this would be a decent use-case for CSS Grid Layout, or at least it might be more semantic that way. But for now you can definitely apply flexbox styling to a <table>:
table {
/* forces the table to be full width
even without enough content */
display: block;
}
tbody {
border: 1px solid black;
/* display flex will reflow child elements
once they hit a limit in their parent */
display: flex;
/* flex-flow sets the direction to flow child elements,
and if they should wrap when hitting
the end of their parent */
flex-flow: column wrap;
max-height: 80px;
width: 100%;
}
tr {
border: 1px solid #bad;
/* the 33% (the flex basis) is how i'm
getting 3 columns, adjusting this will adjust
your number of columns, it's not the most general solution,
but it'll work for you case */
flex: 0 0 33%;
}
td {
border: 1px solid #ace;
}
<table>
<tbody>
<tr>
<td>row data</td>
</tr>
<tr>
<td>row data</td>
</tr>
<tr>
<td>row data</td>
</tr>
<tr>
<td>row data</td>
</tr>
<tr>
<td>row data</td>
</tr>
</tbody>
</table>
I think it is possible with flexbox. You set a height for the parent element and add flex-direction: column and flex-direction: wrap
<div class="wrapper">
<div class="element">
</div>
<div class="element">
</div>
<div class="element">
</div>
</div>
.wrapper {
height: 100vh;
width: 450px;
display: flex;
flex-direction: column;
flex-wrap: wrap;
}
.wrapper .element {
background: red;
margin: 10px;
height: 45vh;
width: 100px;
}
http://jsfiddle.net/fyj1htwk/

how to align the td on top/bottom with css

I have the following table (it contains 2 tds, one with a form and the other with a div):
<tr>
<td class='center-column'>
<form>
A Form
</form>
</td>
<td class='right-column'>
<div id='groupWrapper'>
Some Stuff
</div>
</td>
</tr>
When I make the screen smaller (using #media query) I wanted the two td's to be one on top of the other. I managed this successfully with writing in the css:
.center-column{
display:inline;
}
.right-column{
display:inline;
}
Question is: the right-column comes out on bottom. How do I CHANGE THE CSS so that it is on top and the center-column is on bottom?
I need an answer with ONLY CHANGING THE CSS. (I tried to float them right/left but didn't work)
Thanks
Use flex,
Give flex-direction: column-reverse; to tr to achieve this. Resize the window to see the effect.
.center-column {
flex: 1;
}
.right-column {
flex: 1;
}
#media only screen and (max-width: 768px) {
tr {
display: flex;
flex-direction: column-reverse;
}
}
<table>
<tr>
<td class='center-column'>
<form>
A Form
</form>
</td>
<td class='right-column'>
<div id='groupWrapper'>
Some Stuff
</div>
</td>
</tr>
</table>