Table with CSS Grid - html

My CSS Grid table doesn't have same width on its columns, I want to replicate the table structure but with CSS Grid.
I'm using grid-auto-flow: column; because in my app, the cells are dynamically generated and will be different in number.
An image to show the issue:
The code:
https://jsfiddle.net/w8sdvnr7/1/
div {
display: grid;
grid-auto-flow: column;
}
p {
border: 1px solid red;
margin: 0;
}
table {
border-collapse: collapse;
}
td {
border: solid 2px red;
}
<h3>Not working: CSS Grid: The cells in the rows have different size.</h3>
<div>
<p>ABC</p>
<p>A</p>
<p>ABCDEFGHIJKLMNOP</p>
</div>
<div>
<p>ABCDEFGHIJKLMNOP</p>
<p>A</p>
<p>AB</p>
</div>
<hr>
<br>
<hr>
<h3>What I want: CSS Table: The cells in the rows have same size.</h3>
<table>
<tr>
<td>ABC</td>
<td>A</td>
<td>ABCDEFGHIJKLMNOP</td>
</tr>
<tr>
<td>ABCDEFGHIJKLMNOP</td>
<td>A</td>
<td>AB</td>
</tr>
</table>

There is a solutions for your question
.wrapper {
display: grid;
grid-template-columns: repeat(3, auto);
background-color: #fff;
color: #444;
max-width: 800px;
}
.box {
background-color: #444;
color: #fff;
border-radius: 5px;
padding: 10px;
font-size: 150%;
}
.row {
display: contents;
}
<div class="wrapper">
<div class="box a">col 1</div>
<div class="box b">col 2</div>
<div class="box c">col 3</div>
<!-- Table Row -->
<div class="row">
<div class="box d">short data</div>
<div class="box e">a really long piece of dataa really long piece of data</div>
<div class="box f">short data</div>
</div>
<!-- Table Row -->
<div class="row">
<div class="box d">short data</div>
<div class="box e">a really long piece of data</div>
<div class="box f">short data</div>
</div>
</div>

You might want to use the grid-template-columns property to set the number of columns, however, you should also update the HTML structure for that to work:
div {
display:grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
}
here's the updated fiddle: https://jsfiddle.net/dk9epf57/9/
div {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
}
p {
border: 1px solid red;
margin: 0;
}
table {
border-collapse: collapse;
}
td {
border: solid 2px red;
}
<h3>Not working: CSS Grid: The cells in the rows have different size.</h3>
<div>
<p>ABC</p>
<p>A</p>
<p>ABCDEFGHIJKLMNOP</p>
<p>ABCDEFGHIJKLMNOP</p>
<p>A</p>
<p>AB</p>
</div>
<hr>
<br>
<hr>
<h3>What I want: CSS Table: The cells in the rows have same size.</h3>
<table>
<tr>
<td>ABC</td>
<td>A</td>
<td>ABCDEFGHIJKLMNOP</td>
</tr>
<tr>
<td>ABCDEFGHIJKLMNOP</td>
<td>A</td>
<td>AB</td>
</tr>
</table>

You had a few answers, this one is to complete my earlier comment with examples to help you sort out what you want and decide to dig further into grid tutorials like https://css-tricks.com/snippets/css/complete-guide-grid/ or ressource alike https://gridbyexample.com/
display:table and display:grid may look similar somehow but are not.
about max-content used in the examples, you also can see How do min-content and max-content work?
div {
display: grid;
grid-template-columns: repeat(3, auto);
justify-content: start;
}
p {
border: 1px solid red;
margin: 0;
}
table {
border-collapse: collapse;
}
td {
border: solid 2px red;
}
div.bc {
background: red;
border: red 1px solid;
background: red;
gap: 1px;
width: max-content;
}
div.bc>* {
background: white;
border: none;
}
div.bnc {
width: max-content;
border: solid 1px red;
gap: 2px;
padding: 2px;
}
div.bnc p {
padding:0.5em;
}
<h3>CSS grid layout dispatching children into 3 columns</h3>
<b>border-collapse not avalaible;<b><br><br>
<div>
<p>ABC</p>
<p>A</p>
<p>ABCDEFGHIJKLMNOP</p>
<!--</div>
<div>-->
<p>ABCDEFGHIJKLMNOP</p>
<p>A</p>
<p>AB</p>
</div>
<hr>
<br>
<hr>
<h3>HTML table-layout</h3>
<table>
<tr>
<td>ABC</td>
<td>A</td>
<td>ABCDEFGHIJKLMNOP</td>
</tr>
<tr>
<td>ABCDEFGHIJKLMNOP</td>
<td>A</td>
<td>AB</td>
</tr>
</table>
<br>
<hr>
<br>
<h3>CSS grid layout faking table-layout </h3>
<b> table-layout and border-collapse faked through gap and background and width<b><br><br>
<div class="bc">
<p>ABC</p>
<p>A</p>
<p>ABCDEFGHIJKLMNOP</p>
<!--</div>
<div>-->
<p>ABCDEFGHIJKLMNOP</p>
<p>A</p>
<p>AB</p>
</div>
<br>
<hr>
<br>
<h3>CSS grid layout faking table-layout </h3>
<b> table-layout without border-collapse faked width<b><br><br>
<div class="bnc">
<p>ABC</p>
<p>A</p>
<p>ABCDEFGHIJKLMNOP</p>
<!--</div>
<div>-->
<p>ABCDEFGHIJKLMNOP</p>
<p>A</p>
<p>AB</p>
</div>

Related

Convert template to pure css grid

I am trying to build a minor template, more specific this is what I am trying to do in css grid layout:
I am not convinced that my way is the modern approach, and would like to know if there is a pure way of doing this in only css grid, instead of mixing it with hights?
This is my fiddle of what I have tried:
https://jsfiddle.net/uwbsd2g6/
.wrapper {
display: grid;
grid-template-columns: 50% 50%;
}
.wrapper .col {
border: 1px solid blue;
min-height: 500px;
}
.wrapper .col-v-1 {
height: 50%;
}
.wrapper .col-v-2 {
height: 50%;
color: #fff;
background-color: blue;
}
<div class="wrapper">
<div class="col">
<div class="col-v-1">Here is some text</div>
<div class="col-v-2">Heres is another text</div>
</div>
<div class="col">
This is a third text
</div>
</div>
You can do this purely with css grid (assuming that you have an element with 100% height of the container as the parent) by using grid-template-column and grid-template-row as seen below
<style>
.wrapper {
height:100vh;
}
.outline{
outline: 1px red solid;
}
.grid {
display:grid
}
.grid-cols-2 {
grid-template-columns: 1fr 1fr;
}
.grid-rows-2 {
grid-template-rows: 1fr 1fr;
}
</style>
<div class="wrapper outline grid grid-cols-2">
<div class="grid grid-rows-2 outline">
<div class="outline">Here is some text</div>
<div class="outline">Heres is another text</div>
</div>
<div class="outline">
This is a third text
</div>
</div>
You can do it with grid template column and row

Is it possible to create this mobile vs desktop layout in HTML/CSS?

I have a bit of a dilemma where I want to create different layouts for web versus mobile. It will use the same sections of the page but just in different order for web versus mobile. Here is what I mean. Do you think this is possible to create?
Desktop Version:
<table>
<tr>
<td>A</td>
<td>B</td>
</tr>
<tr>
<td>E</td>
<td>C</td>
</tr>
<tr>
<td>F</td>
<td>D</td>
</tr>
</table>
Mobile Version:
<table>
<tr>
<td>A</td>
</tr>
<tr>
<td>B</td>
</tr>
<tr>
<td>C</td>
</tr>
<tr>
<td>D</td>
</tr>
<tr>
<td>E</td>
</tr>
<tr>
<td>F</td>
</tr>
</table>
Notice how left column in desktop version has A but the right column has B C D.
Is this possible?
UPDATE: Apologies, I didn't mean to use a table but just to show the content of my question. The two answers provided below are on the right step but I forgot to mention how would this work with dynamic content that isn't the same height? For example, let's see C was some text that was short for some pages while long for other pages. How would I go about using grid-template-areas for dynamic content that varied in height?
Well as already mentioned you can do this the easiest way with a CSS-Grid. I assume, that you already know how to apply media queries. The 2 snippets below have the evry same code. Just the templates for the CSS-Grid (body) changed slightly.
Desktop:
body {
margin: 0;
padding: 5px;
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-auto-rows: auto;
grid-gap: 5px;
grid-template-areas:
"A B"
"E C"
"F D";
}
div {
border: 1px solid black;
padding: 5px;
min-height: 50px;
}
#A {
grid-area: A;
}
#B {
grid-area: B;
}
#C {
grid-area: C;
}
#D {
grid-area: D;
}
#E {
grid-area: E;
}
#F {
grid-area: F;
}
<body>
<div id="A">A</div>
<div id="B">B</div>
<div id="C">C</div>
<div id="D">D</div>
<div id="E">E</div>
<div id="F">F</div>
</body>
Mobile:
body {
margin: 0;
padding: 5px;
display: grid;
grid-template-columns: repeat(1, 1fr);
grid-auto-rows: auto;
grid-gap: 5px;
grid-template-areas:
"A"
"B"
"C"
"D"
"E"
"F";
}
div {
border: 1px solid black;
padding: 5px;
min-height: 50px;
}
#A {
grid-area: A;
}
#B {
grid-area: B;
}
#C {
grid-area: C;
}
#D {
grid-area: D;
}
#E {
grid-area: E;
}
#F {
grid-area: F;
}
<body>
<div id="A">A</div>
<div id="B">B</div>
<div id="C">C</div>
<div id="D">D</div>
<div id="E">E</div>
<div id="F">F</div>
</body>
you can use grid or Flex (order) as well...
Flex Example:
.wrap{
width: 50px;
display: flex;
flex-wrap: wrap;
}
.wrap div{
flex: 0 0 50%;
}
<div class="wrap">
<div id="A">A</div>
<div id="B">B</div>
<div id="E">E</div>
<div id="C">C</div>
<div id="F">F</div>
<div id="D">D</div>
</div>
and for Mobile View:
.wrap{
width: 50px;
display: flex;
flex-wrap: wrap;
}
.wrap div{
flex: 0 0 100%;
}
#A{order: 1;}
#B{order: 2;}
#C{order: 3;}
#D{order: 4;}
#E{order: 5;}
#F{order: 6;}
<div class="wrap">
<div id="A">A</div>
<div id="B">B</div>
<div id="E">E</div>
<div id="C">C</div>
<div id="F">F</div>
<div id="D">D</div>
</div>

Set same height of independent div's with same class name using CSS [duplicate]

This question already has an answer here:
Maintain same height in elements inside columns located side by side with CSS
(1 answer)
Closed 2 years ago.
I want to set the same height of independent div's that have the same class name(i.e 'description', 'features', 'rules') and height should be w.r.t div that have max-content.
Note: Content is dynamic and HTML structure must be the same as below.
.products {
display: inline-flex;
width: 300px;
}
.products .product {
width: 50%;
border: 1px solid black;
}
.products .product div {
border-bottom: 1px solid black;
}
<div class="products">
<div class="product">
<div class="description">product 1 description description description description description</div>
<div class="features">product 1 features</div>
<div class="rules">product 1 rules rules rules rules rules rules rules rules</div>
</div>
<div class="product">
<div class="description">product 2 description</div>
<div class="features">product 1 features features features features features</div>
<div class="rules">product 1 rules</div>
</div>
</div>
Looking for only CSS solution!
Consider using grid layout https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout
View the example below with aligned rows using a nested grid layout.
.products {
display: grid;
grid-template-columns: 1fr 1fr;
border: 3px solid blue;
}
.products .product {
display: grid;
grid-template-rows: 1fr 1fr 1fr;
border: 3px solid green;
}
.product .description {
grid-column: 1;
grid-row: 1;
border-bottom: 1px solid yellow;
}
.product .features {
grid-column: 1;
grid-row: 2;
border-bottom: 1px solid red;
}
.product .rules{
grid-column: 1;
grid-row: 3;
}
<div class="products">
<div class="product">
<div class="description">product 1 description description description description description</div>
<div class="features">product 1 features</div>
<div class="rules">product 1 rules rules rules rules rules rules rules rules</div>
</div>
<div class="product">
<div class="description">product 2 description</div>
<div class="features">product 2 features features features features features</div>
<div class="rules">product 2 rules</div>
</div>
</div>
Another good resource if you don't want to nest grids
https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-areas#html
For your case, I prefer to use an HTML table:
.products {
border: 1px solid black;
border-collapse: collapse;
}
table td {
width: 50%;
border: 1px solid black;
}
<table class="products">
<tr>
<td>product 1 description description description description description</td>
<td>product 2 description</td>
</tr>
<tr>
<td>product 1 features</td>
<td>product 1 features features features features features</td>
</tr>
<tr>
<td>product 1 rules rules rules rules rules rules rules rules</td>
<td>product 1 rules</td>
</tr>
</table>
Maybe it is far from your HTML but possible it could be an answer.

Stretch table to vertically fit TD

I am placing a table inside a td. By setting width:100%, I can get the table to stretch horizontally, but I have not been able to do the same vertically. No matter what I've tried, the table will have the minimum height necessary to contain its contents.
Below is the structure of the table
table {
border-collapse: collapse;
border-spacing: 2px;
border-color: black;
}
td {
border: 1px solid #ddd;
background: #f2f5f7;
}
<table >
<tbody>
<tr>
<td rowspan="2" style="background-color:#ff0000"/>
<table>
<tr>
<td>A</td>
<td>B</td>
</tr>
<tr>
<td>C</td>
<td>D</td>
</tr>
</table>
<td><br>Extra<br></td>
</tr>
<tr>
<td>Space<br><br></td>
</tr>
</table>
I am trying to get rid of the red areas above and below the ABCD table. I've tried solutions from dozens of various questions, and I thought this would be straightfoward, but nothing has worked.
I have tried (in various permutations):
height:100% on any and all componentns
display:flex or display:block on the nested table and/or parent td
explicitly setting padding:0px !important on all components
None of these have affected the height of the table.
The most promising result so far: setting the height to a pixel value (like height:100px does change the height of the table. Unfortunately, the necessary height of the table will change based on factors outside of my knowledge/control. I'm looking for a programmatic solution to this issue.
(NOTE: I know how to use JS to grab the height of the neighboring cells and set the height of the trs in the nested table after the page loads. However, I don't have a guarantee that JS will be executable, so this is my last resort.)
Here is a solution that I've created using CSS Grid.
.grid-table {
display: grid;
grid-template-columns: repeat(3, minmax(50px, 1fr));
background-color: #fff;
color: #444;
max-width: 800px;
background-color: #ccc;
}
.grid-table > .row:not(:last-of-type) {
border-bottom: 1px solid #ddd
}
.row {
grid-column: 1 / -1;
display: grid;
grid-template-columns: repeat(3, minmax(50px, 1fr));
align-items: center;
}
.row > .box:not(:last-of-type) {
border-right: 1px solid #ddd;
}
.box {
height: 100%;
display: flex;
align-items: center;
}
.box-item {
padding: 5px;
}
<div class="grid-table">
<!-- Table Row -->
<div class="row">
<div class="box">
<div class="box-item">Column 1</div>
</div>
<div class="box">
<div class="box-item">Column 2</div>
</div>
<div class="box">
<div class="box-item">Column 3</div>
</div>
</div>
<!-- Table Row -->
<div class="row">
<div class="box">
<div class="box-item">A</div>
</div>
<div class="box">
<div class="box-item">B</div>
</div>
<div class="box">
<div class="box-item">Extra<br>Space</div>
</div>
</div>
<!-- Table Row -->
<div class="row">
<div class="box">
<div class="box-item">C</div>
</div>
<div class="box">
<div class="box-item">D</div>
</div>
<div class="box">
<div class="box-item">Extra<br>Space</div>
</div>
</div>
</div>
With this solution, the height of the individual columns will always be the height of the tallest column. You can control whether you want the rows to be centered or not by modifying the align-items attribute within the .box class.
JSFiddle

HTML: CSS: Place element somewhere by class

Say I have 6 elements:
<img src="..." class="a"/>
<img src="..." class="b"/>
<img src="..." class="c"/>
<img src="..." class="d"/>
<img src="..." class="e"/>
<img src="..." class="f"/>
which are not necessarily images like shown above, but can be any element, like some <div>.
Is it possible to create a grid of 3x2 and place each element of these in one container?
Just using classes as you pretend, mixing a lot of elements as you don't know which will be used.
option #1 - using flexbox
body {
margin: 0
}
#flex {
display: flex;
flex-wrap: wrap;
height:100vh
}
.a,
.b,
.c,
.d,
.e,
.f {
flex: 1 0 calc(100% / 3);
height:50%;
background: lightblue;
}
<div id="flex">
<div class="a">div with Class A</div>
<img class="b" src="//lorempixel.com/100/100" />
<span class="c">span with Class C</span>
<article class="d">article with Class D</article>
<div class="e">div with Class E</div>
<section class="f">Div with Class F</section>
</div>
option #2 - using inline-block
body,html {
margin: 0;
height:100%
}
#ib {
font-size: 0;
height:100%
}
.a,
.b,
.c,
.d,
.e,
.f {
display: inline-block;
vertical-align: top;
background:lightblue;
width: calc(100% / 3);
height:50%;
font-size: 16px
}
<div id="ib">
<div class="a">div with Class A</div>
<img class="b" src="//lorempixel.com/100/100" />
<span class="c">span with Class C</span>
<article class="d">article with Class D</article>
<div class="e">div with Class E</div>
<section class="f">Div with Class F</section>
</div>
I just tried using CSS :nth-child() Selector and you can move required elements to next line and form matrix
<div class="a">1</div>
<div class="b">2</div>
<div class="c">3</div>
<div class="d">4</div>
<div class="e">5</div>
<div class="f">6</div>
div {
display: inline;
}
div:nth-child(4) {
display: inline;
}
div:nth-child(3):after {
content: "\a";
white-space: pre;
}
Hope this is helpful for you :)
codepen URL for reference -http://codepen.io/nagasai/pen/BzNmBz
Note the th tag is for headings, tr tag for rows and td tag is where you need to write your data. Hope this helps
<table>
<tr>
<th></th>
<th></th>
<th></th>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
</tr>
</table>
`
The generic approach to this is to use a class for the container in which the items will be laid out, and a class for each item that will be in the container.
This sample mostly takes the form of #dippas' "using flexbox" example, but the CSS styles are not particular to any set of ids or classes ... you can attach the additional class if necessary. <div class="a">...</div> could become <div class="a grid-item">...</div> or omit the class a as I do.
You can see you just attach the grid-item class to any sort of thing you want.
This can also be styled using the inline-block method if that's preferable.
UI frameworks commonly take this approach, where you just attach the appropriate class(es) to your elements to give them the layout / style desired.
.grid-container {
display: flex;
flex-wrap: wrap;
height: 100vh;
}
.grid-item {
flex: 1 0 calc((100% / 3) - 4px);
height: 50%;
background-color: antiquewhite;
border: 1px dotted burlywood;
border-collapse: collapse;
}
<div class="grid-container">
<div class="grid-item">A</div>
<div class="grid-item">B</div>
<span class="grid-item">C</span>
<img class="grid-item" src="//lorempixel.com/100/100" />
<section class="grid-item">Section E</section>
<div class="grid-item">F</div>
</div><!-- grid-container -->
You can even omit the class for the items if everything in the grid-container will be laid out like this...
.grid-container {
display: flex;
flex-wrap: wrap;
height: 100vh;
}
/* select all immediate children of the .grid-container */
.grid-container > * {
flex: 1 0 calc((100% / 3) - 4px);
height: 50%;
background-color: antiquewhite;
border: 1px dotted burlywood;
border-collapse: collapse;
}
<div class="grid-container">
<div>div A</div>
<div>div B</div>
<span>span C</span>
<img src="//lorempixel.com/100/100" />
<section>section E</section>
<div>div F</div>
</div><!-- grid-container -->