I have the below grid and I want to transform it into code.
I searched about grids like this and the only reference was about the masonry library but didn't help me.
Another approach was with css only but I couldn't understand the logic behind this.
Any help for a good start to continue with will be appreciated!
You can set a CSS grid with the adequate number of rows and columns, and the distribute the elements as the design:
.container {
display: grid;
grid-template-columns: repeat(6, 1fr);
grid-template-rows: repeat(3, 1fr);
grid-column-gap: 10px;
grid-row-gap: 10px;
grid-auto-flow: column dense;
width: 95vw;
height: 95vh;
}
.vertical {
grid-row: span 2;
background-color: tomato;
}
.horizontal {
grid-column: span 2;
background-color: lightgreen;
}
.square {
background-color: lightblue;
}
#v2 {
grid-column-start: 3;
}
#v3 {
grid-column-start: 6;
}
#v4 {
grid-column-start: 2;
grid-row: 2 / 4;
}
#v5 {
grid-column-start: 5;
grid-row: 2 / 4;
}
<div class="container">
<div class="vertical" id="v1">V1</div>
<div class="vertical" id="v2">V2</div>
<div class="vertical" id="v3">V3</div>
<div class="vertical" id="v4">V4</div>
<div class="vertical" id="v5">V5</div>
<div class="horizontal" id="h1">H</div>
<div class="horizontal" id="h2">H</div>
<div class="square">S</div>
<div class="square">S</div>
<div class="square">S</div>
<div class="square">S</div>
</div>
I would recommend using Unite Gallary. It is completely free and very easy to use. Try reading their documentation and it will be easy to use. Below is a screenshot.
Unite Gallary
I know this is a very old technique and is generally frowned upon, but you could just use a <table> if you have to support IE, as you specified in a comment to this answer.
table {
table-layout: fixed;
height: 200px;
width: 100%;
}
td {
text-align: center;
vertical-align: bottom;
background-color: blue;
}
<table>
<tr>
<td rowspan="2">Corina</td>
<td>Lydia</td>
<td rowspan="2">Reinas</td>
<td colspan="2">Elise</td>
<td rowspan="2">Vegerra</td>
</tr>
<tr>
<td rowspan="2">Agapi</td>
<td>Amira</td>
<td rowspan="2">Filipa</td>
</tr>
<tr>
<td>Daisy</td>
<td colspan="2">Josephine</td>
<td>Amarylis</td>
</tr>
</table>
Be advised that the table does not react to height as one may expect when using percentages (at least in Firefox 61.0).
table {
table-layout: fixed;
height: 100%;
width: 100%;
}
td {
text-align: center;
vertical-align: bottom;
background-color: blue;
}
<table>
<tr>
<td rowspan="2">Corina</td>
<td>Lydia</td>
<td rowspan="2">Reinas</td>
<td colspan="2">Elise</td>
<td rowspan="2">Vegerra</td>
</tr>
<tr>
<td rowspan="2">Agapi</td>
<td>Amira</td>
<td rowspan="2">Filipa</td>
</tr>
<tr>
<td>Daisy</td>
<td colspan="2">Josephine</td>
<td>Amarylis</td>
</tr>
</table>
BTW: After writing this table I can see why this kind of layout would not be preferred to use because it is very irritating that in some rows there are just columns missing.
Related
Here is the image of the HTML table design. Please help me out to convert this outline into HTML markup.
NOTE: Unfortunately, this must include a table layout.
Here is my markup:
<!DOCTYPE html>
<html>
<head>
<style>
table, th, td {
border: 1px solid black;
border-collapse: collapse;
text-align: center;
font-weight: 100;
}
</style>
</head>
<body>
<table style=" width: 400px;">
<tr>
<th colspan= "3">1</th>
</tr>
<tr>
<th colspan= "2">2</th>
<th rowspan= "2">3</th>
</tr>
<tr>
<th rowspan= "3">4</th>
<th colspan= "1">5</th>
</tr>
<tr>
<td>6</td>
<td>7</td>
</tr>
<tr>
<td>8</td>
<td>9</td>
</tr>
</table>
</body>
</html>
I want to do this exactly like the image which I've attached above.
display: grid
Using display: grid, you use your parent element to set your width and height, then define your grid-template-column and grid-template-rows in fractions and layout the children elements using the grid-template-areas rule in the parents css.
Then in your child elements, you define their grid-area as their class selectors. This is also dynamic because it fills the parents width and height using the unit of measure you choose.
In my example I use 1fr. So in the case of the columns, we have 5 measurements which each take up one fraction => 1fr, as it is 90vw in width, this means the 5 sections split the 90vw equally, basically 20%, 20%, 20%, 20%, 20% of 90vw gives us the overall width and each child will be 20% width of the parents 90vw. This works using the same principle for rows.
So using this method we can write the CSS to display a grid 5 fractions wide (columns) and 5 fractions high (rows) then set our grid-template-areas in the same pattern they will be displayed on the page.
grid-template-areas:
"one one one one one"
"two two two three three"
"four five five three three"
"four eight nine three three"
"four eight nine six seven";
Setting up the children of the display grid in that pattern, again we must define the childrens selectors grid-area rule using their selector.
.one {
grid-area: one;
}
.cont {
display: grid;
width: 90vw;
height: 90vh;
grid-template-columns: 1fr 1fr 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr 1fr 1fr;
gap: 0px 0px;
grid-template-areas:
"one one one one one"
"two two two three three"
"four five five three three"
"four eight nine three three"
"four eight nine six seven";
}
.one {
grid-area: one;
}
.two {
grid-area: two;
}
.three {
grid-area: three;
}
.four {
grid-area: four;
}
.five {
grid-area: five;
}
.six {
grid-area: six;
}
.seven {
grid-area: seven;
}
.eight {
grid-area: eight;
}
.nine {
grid-area: nine;
}
.divs {
display: flex;
justify-content: center;
align-items: center;
border: 1px solid black;
}
#main {
display: flex;
justify-content: center;
align-items: center;
}
<div id="main">
<div class="cont">
<div class="one divs">1</div>
<div class="two divs">2</div>
<div class="three divs">3</div>
<div class="four divs">4</div>
<div class="five divs">5</div>
<div class="six divs">6</div>
<div class="seven divs">7</div>
<div class="eight divs">8</div>
<div class="nine divs">9</div>
</div>
</div>
Using a Table:
So without setting your height rule for your tr's you will get a weird layout that does not look like you have five rows.
Once you set your height for your rows, it will parse the table correctly provided you have your colspan and rowspan set up properly
table, th, td {
border: 1px solid black;
border-collapse: collapse;
text-align: center;
font-weight: 100;
}
tr {
height: 10vh;
width: 20vw;
}
<table style=" width: 400px;">
<tr>
<th colspan="5">1</th>
</tr>
<tr>
<th colspan="3">2</th>
<th colspan="2" rowspan="3">3</th>
</tr>
<tr>
<th rowspan="3">4</th>
<th colspan="2">5</th>
</tr>
<tr>
<td rowspan="2">8</td>
<td rowspan="2">9</td>
</tr>
<tr>
<td>6</td>
<td>7</td>
</tr>
</table>
this is the code down below... then to remove the extra boarder around it add this border-collapse: collapse; to your table style:
<!DOCTYPE html>
<html>
<head>
<style>
table, th, td {
border: 1px solid black;
text-align: center;
font-weight: 100;
}
</style>
</head>
<body>
<table style=" width: 400px;">
<tr>
<th colspan= "5">1</th>
</tr>
<tr>
<th colspan= "3">2</th>
<th colspan= "2" rowspan= "3">3</th>
</tr>
<tr>
<th rowspan= "3">4</th>
<th colspan= "2">5</th>
</tr>
<tr>
<th rowspan= "2">8</th>
<th rowspan= "2">9</th>
</tr>
<tr>
<th rowspan= "2">6</th>
<th rowspan= "2">7</th>
</tr>
</table>
</body>
</html>
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>
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>
I have the following pattern, and it is quite responsive, no matter how I zoom in or change the width of the page squares stays the same size, the only way these squares change in size is by changing the height of the page. and that's what I want.
I achieved this by making the width and height proportional to the height of the page, using vh units, and adding these squares to a CSS grid.
The problem is the squares in the middle of the image appear to have a border, whereas I don't want a border. This is what I want, instead:
I tried padding the squares to the right or making a white border around them, but both approaches affected the responsiveness of the squares.
How can I blend those squares with the white background without affecting the responsiveness?
Is there a way I can reduce the amount of code required for the '.rect:nth-child' section?
body {
background-color: black;
height: 100vh;
display: grid;
grid-template-columns: 1fr 1fr;
}
.left{
display: grid;
grid-template-columns: 1fr 45vh;
height:100vh;
}
.design{
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(9, 1fr);
}
.rect{
background-color: white;
width: calc(100vh / 9);
height: calc(100vh / 9);
}
.rect:nth-child(1){
grid-column-start: 1;
grid-row-start: 1;
}
.rect:nth-child(2){
grid-column-start: 2;
grid-row-start: 2;
}
.rect:nth-child(3){
grid-column-start: 3;
grid-row-start: 1;
}
.rect:nth-child(4){
grid-column-start: 4;
grid-row-start: 2;
}
.rect:nth-child(5){
grid-column-start: 3;
grid-row-start: 3;
}
.rect:nth-child(6){
grid-column-start: 4;
grid-row-start: 4;
}
.rect:nth-child(7){
grid-column-start: 4;
grid-row-start: 6;
}
.rect:nth-child(8){
grid-column-start: 3;
grid-row-start: 7;
}
.rect:nth-child(9){
grid-column-start: 2;
grid-row-start: 8;
}
.rect:nth-child(10){
grid-column-start: 4;
grid-row-start: 8;
}
.rect:nth-child(11){
grid-column-start: 1;
grid-row-start: 9;
}
.rect:nth-child(12){
grid-column-start: 3;
grid-row-start: 9;
}
<body>
<div class="left">
<div class='design'>
<div class="rect"></div>
<div class="rect"></div>
<div class="rect"></div>
<div class="rect"></div>
<div class="rect"></div>
<div class="rect"></div>
<div class="rect"></div>
<div class="rect"></div>
<div class="rect"></div>
<div class="rect"></div>
<div class="rect"></div>
<div class="rect"></div>
</div>
</div>
<div class="right"></div>
</body>
Problems
"How can I blend those squares with the white background without affecting the responsiveness?"
"Is there a way I can reduce the amount of code required for the '.rect:nth-child' section?"
In order to cleanly resolve all issues, one must consider that the most direct and simplest solutions will most likely yield the best results as well as provide a stable base to which one can expand upon in the future. Using CSS grid for a simple design is over complicated, unnecessary, and will become problematic (it appears it already is -- hence this post).
Having said that, the pattern can be duplicated using:
1 <table>, 1 <tbody>, 9 <tr>, and 36 <td>
or
tags assigned: display: table;, table-row-group;, table-row;, and table-cell;
Reply to the first question: Tables have two ways to eliminate or blend all borders on and within itself:
table { border-collapse: collapse; }
or
table { border-collapse: separate;⃰ border-spacing: 0; }
table, td { border: 0; }
The second option is for more granular control like using border-radius or narrowing cells by negative border-spacing values, etc. Applying border: 0; to any other type of tag does not guarantee a seamless design (table behavior and style has been perfected and honed for 25+ years).
⃰ Default that can be omitted under normal circumstances.
Reply to the second question: Use a table design -- refer to previous information concerning tables.
OP's CSS.....: 16 rulesets / 35 properties
VS
Answer's CSS: 6 rulesets / 15 properties (less code)
Update
"... i I am trying to keep the design within the view port viewport without any scrolling."
Solution to the first requirement: Focus on how the parent tag occupies the viewport. Which would be difficult considering the OP's layout (ie .design). But with a table layout we can define dimensions by content:
table { table-layout: fixed; ... }
td { width: 11vh; height: 11vh; padding: 0 ... }
table-layout: fixed will force the table's width to conform to the width of each column. So here we have the dimensions of 44vh x 99vh which is well within the confines of the viewport. Note that 100vh is not used yet it is apparent in the demo that everything is edge to edge. It's never going to be precise from browser to browser, device to device, etc. -- hence 11vh will suffice rather than a length that actually exceeds the borders of visibility (ie calc(100vh / 9))
Solution to the second requirement: A complete and efficient way to eliminate scrolling is:
body { overflow: hidden; }
Demo
The following demo is 100% responsive vertically. It has no scrollbars and it is perfectly edge to edge. Also the color pattern is how it is posted in OP's screenshot without any unseemly borders. Moreover, it will not lose its structural integrity at extreme dimensions (ex. OP's code will separate and loose group cohesiveness as viewport height decreases).
:root,
body {
width: 100%;
height: 100%;
font: 700 2vh/1 Consolas;
}
body {
overflow: hidden;
}
main {
width: 99vh;
height: 99vh;
background: white;
}
table {
table-layout: fixed;
border-collapse: collapse;
margin: -8px 0 auto 0;
}
td {
width: 11vh;
height: 11vh;
padding: 0;
background: white;
}
.b {
background: black;
}
<main>
<table>
<tbody>
<tr>
<td></td>
<td class='b'></td>
<td></td>
<td class='b'></td>
</tr>
<tr>
<td class='b'></td>
<td></td>
<td class='b'></td>
<td></td>
</tr>
<tr>
<td class='b'></td>
<td class='b'></td>
<td></td>
<td class='b'></td>
</tr>
<tr>
<td class='b'></td>
<td class='b'></td>
<td class='b'></td>
<td></td>
</tr>
<tr>
<td class='b'></td>
<td class='b'></td>
<td class='b'></td>
<td class='b'></td>
</tr>
<tr>
<td class='b'></td>
<td class='b'></td>
<td class='b'></td>
<td></td>
</tr>
<tr>
<td class='b'></td>
<td class='b'></td>
<td></td>
<td class='b'></td>
</tr>
<tr>
<td class='b'></td>
<td></td>
<td class='b'></td>
<td></td>
</tr>
<tr>
<td></td>
<td class='b'></td>
<td></td>
<td class='b'></td>
</tr>
</tbody>
</table>
</main>
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.