CSS Grid with Angular | Don't distribute grid items equally on width - html

I have a app which has rows and columns. I can dynamically remove rows. When I remove them then the other items distribute themself equaly over the width of the grid.
Now I want to have something like flex, but with grid. The grid items should have a margin to the next item beside them. Like that. And not distribute themself over the width.
CSS
.column {
padding: 10px;
margin: 10px 0;
display: grid;
grid-auto-flow: column;
.row-item {
text-align: center;
display: grid;
grid-auto-rows: 25px;
grid-row-gap: 10px;
width: 9vw;
}
}
HTML
<div class="column">
<ng-container *ngFor="let jS of journeyStepDisplay">
<div *ngIf="jS.display" class="row-item">
<div class="column-item header">
<p>{{ jS.name }}</p>
</div>
</div>
</ng-container>
</div>

If you have a minimum and/or a max width of the grid items that are to be distributed, you can use a combination of different grid properties to get the desired outcome, like
grid-template-columns: repeat(auto-fit, minmax(100px, 100px));
In the example below, we have a grid where the items will be distributed evenly with a min/max width of 100px. If they can't fit into the row a new row will be inserted.
.container {
height: 200px;
width: 600px;
gap: 5px;
border: 2px solid red;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(100px, 100px));
grid-template-rows: auto;
padding: 10px;
}
.box {
border: 2px solid blue;
}
<div class="container">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>

You have to declare width for each item.
<div class="column">
<div class="row-item">
<div class="column-item header">
<p>ciao</p>
</div>
</div>
<div class="row-item">
<div class="column-item header">
<p>ciao2</p>
</div>
</div>
<div class="row-item">
<div class="column-item header">
<p>ciao3</p>
</div>
</div>
</div>
.column {
width: 100%;
display: grid;
grid-template-columns: 150px 150px 150px 150px;
grid-template-rows: auto;
}
.row-item {
text-align: center;
}
here a useful guide.
(I didn't use directive from angular, but you can add it)

Related

Having problems with fitting content in div with css grid

I'm playing around with Css Grid and having problems with fitting overlaying content.
There is a top level container defined as css grid (class="container"), then content grid (class="content") which splits into 3 rows (header, label, rows).
Header is just a header, label contains labels for rows and rows is a content of "table".
Here is what it looks like:
When I resize window I got scroll bar on the right but it's for the whole page. Instead I would like to scroll only rows not the whole page.
Here is the the StackBlitz working example:
https://stackblitz.com/edit/angular-ivy-ayujp5
I guess it's simple but having problems with understanding how height is calculated and where and how overflow properties should be defined.
p {
font-family: Lato;
}
.container {
display: grid;
grid-template-columns: 30px 1fr 30px;
grid-template-rows: 30px 1fr 30px;
grid-template-areas: '. . .' '. content .' '. . .';
}
.content {
grid-area: content;
display: grid;
grid-template-rows: 50px 30px 1fr;
grid-template-areas: 'header' 'label' 'rows';
}
.header {
grid-area: header;
}
.label {
grid-area: label;
display: grid;
grid-template-rows: 1fr;
grid-template-columns: repeat(3, 4fr);
align-items: center;
}
.rows {
grid-area: rows;
height: 100%;
}
.row {
background-color: pink;
margin: 5px 0px;
border-width: 1px;
border-radius: 10px;
padding: 25px;
color: black;
}
<div class="container">
<div class="content">
<div class="header">Header</div>
<div class="label">
<div>Name</div>
<div>From</div>
<div>To</div>
</div>
<div class="rows">
<div class="row">
<div class="label">
<div>1</div>
<div>1999/01/01</div>
<div>1999/12/01</div>
</div>
</div>
<div class="row">
<div class="label">
<div>2</div>
<div>1999/01/01</div>
<div>1999/12/01</div>
</div>
</div>
<div class="row">
<div class="label">
<div>2</div>
<div>1999/01/01</div>
<div>1999/12/01</div>
</div>
</div>
<div class="row">
<div class="label">
<div>3</div>
<div>1999/01/01</div>
<div>1999/12/01</div>
</div>
</div>
<div class="row">
<div class="label">
<div>4</div>
<div>1999/01/01</div>
<div>1999/12/01</div>
</div>
</div>
</div>
I go with height calculation .pin-table { height: calc(100vh - 125px); overflow: auto; } but if anyone has better idea feel free to write.

How to write Instagram explore layout with flexbox?

I tried to write this similar layout to Instagram explore with CSS Flexbox:
and it's my code:
section {
display: flex;
flex-flow: row wrap;
width: 330px;
}
.box {
width: 100px;
height: 100px;
margin: 5px;
background-color: orange;
}
.bigger {
width: 210px;
height: 210px;
}
<section>
<div class="box bigger"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</section>
As you can see in this code, the next element does not fill the empty space in front of the big element.
What is the solution?
We can use .bigger:after to display a container. Give it position: absolute and determine where to position it, which in this case was left: 233px.
section {
display: flex;
flex-flow: row wrap;
width: 330px;
}
.box {
width: 100px;
height: 100px;
margin: 5px;
background-color: orange;
align-self: flex-end;
}
.bigger {
width: 210px;
height: 210px;
}
.bigger:after {
content: "";
position: absolute;
width: 100px;
height: 100px;
left: 233px;
background-color: orange;
}
<section>
<div class="box bigger"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</section>
This answers your question of 'is it possible?', but this isn't something you should build on. The best way would be to either have a container with small divs in column layout beside the bigger div, or simply use grid.
What you want is a masonry layout: something that CSS flexbox can't handle using the DOM structure you have. CSS grid can do that. You can use the dense keyword in grid-auto-flow to ensure that CSS grid attempts to pack its children as densely as possible.
And of course, you need to use the relevant CSS grid properties to make things work:
grid-gap: 10px is used to replace the margin: 5px
grid-auto-flow: row dense is used to pack cells as densely as possible from one row to another
grid-template-columns: 1fr 1fr 1fr simply defines 3 equal-width columns. If you want to be explicit, you can also use grid-template-columns: repeat(3, 100px);, which allows you to leave out an explicit width on the parent
grid-auto-rows: 100px; informs CSS grid that each row should be 100px tall
section {
display: grid;
grid-gap: 10px;
grid-auto-flow: row dense;
grid-template-columns: repeat(3, 100px);
grid-auto-rows: 100px;
}
.box {
width: 100%;
height: 100%;
background-color: orange;
}
.bigger {
grid-area: 1 / 1 / span 2 / span 2;
}
<section>
<div class="box bigger"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</section>

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

CSS Grid responsive layout with auto-fit and minmax for even number of items

What I am trying to accomplish:
There are 4 grid items. At the a widest screen size, I would like the items to be lined up in a row:
item_1 item_2 item_3 item_4
As the screen width shrinks, I would like the items to wrap to the next row like this:
item_1 item_2
item_3 item_4
Then finally at the narrowest, I would like the times to be a single columns
item_1
item_2
item_3
item_4
I found an example which does this but by only wrapping the next item when it can – https://labs.jensimmons.com/2017/03-009.html
Building off of that I tried using nested grid containers based on the example's model:
grid-template-columns: repeat(auto-fit, minmax(600px, 1fr));
HTML
.outer_grid {
display:grid;
grid-template-columns: repeat(auto-fit, minmax(600px, 1fr));
grid-template-row:1fr 1fr;
grid-gap:1em;
border:5px solid blue;
}
.grid {
display:grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
grid-template-row:1fr 1fr;
grid-gap:1em;
border:5px solid green;
height:200px;
}
.item {
border:2px solid red;
}
<div class="outer_grid">
<div class="grid">
<div class="item">item 1</div>
<div class="item">item 2</div>
</div>
<div class="grid">
<div class="item">item 3</div>
<div class="item">item 4</div>
</div>
</div>
It is nearly working (codepen below) but I'm not sure if this is the right approach or if there is a better way to accomplish this. I have tried using Flexbox too but chose CSS Grid because of the grid-gap feature. Also, I know it can be done but I am trying to do this without media queries.
https://codepen.io/anon/pen/LMqWEr?editors=1100
I tried the below fix for this question and hope it works
https://codepen.io/ronsummer/pen/eYOKRzg
<div class="wrapper">
<div class="box a">A</div>
<div class="box b">B</div>
<div class="box c">C</div>
<div class="box d">D</div>
<div class="box e">E</div>
<div class="box f">F</div>
</div>
body {
margin: 40px;
}
.wrapper {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
grid-gap: 10px;
background-color: #fff;
color: #444;
}
.box {
background-color: #444;
color: #fff;
border-radius: 5px;
padding: 20px;
font-size: 150%;
}
So from my understanding, you are actually looking for a row of items to be transformed into a column or multiple columns of items when shrinking, without using media queries.
Taking this into consideration, the best approach would be to use Flexbox since it's 1 dimensional.
CSS Grid is also powerful but only when you want to make use of 2-dimensional layout (so both rows & columns).
Also is good to know that Flexbox is content-first opposed to CSS Grid which is layout-first.
Codepen
.flex-container {
display: flex;
width: 100%;
flex-wrap: wrap;
justify-content: center;
}
.flex-container .flex-item {
display: flex;
min-width: 10rem;
width: calc((100% - 1rem * 8 * 2) / 8);
height: 10rem;
padding: 1rem;
margin: 1rem;
align-items: center;
justify-content: center;
background: #1d1d1d;
color: #fff;
font-size: 2rem;
font-weight: 500;
text-align: center;
}
<div class="flex-container">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
<div class="flex-item">4</div>
<div class="flex-item">5</div>
<div class="flex-item">6</div>
<div class="flex-item">7</div>
<div class="flex-item">8</div>
</div>

grid items don't fully occupy grid container

I have created a site design and everything is okay except that I am having problem in getting the grid items to occupy all the space available to them.
I have added the site in codepen here.
.container{
border-radius: 8px;
width:90%;
height: 90vh;
margin: 0 auto;
background: #ecf0f1;
display: flex;
flex-direction: column;
}
main{
display: grid;
grid-template-columns: 300px 1fr;
flex-grow: 1;
}
.data-box{
padding-top:1rem;
background: #e74c3c;
color: #fff;
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 3rem 2.5rem 2.5rem auto;
justify-items: center;
align-items: center;
}
.display-box{
padding: 2em;
background: #2c3e50;
display: grid;
grid-template-columns: repeat(auto-fit,minmax(6em,1fr));
grid-gap:1.5rem;
align-items: center;
justify-items: center;
}
HTML:
<div class="container">
<div class="main-text">
<h1>Smart Parking System UI</h1>
<p>Currently viewing: <span class="lot-id">Beta</span></p>
</div>
<main>
<div class="data-box">
<p class="m-para">Parking Status</p>
<p class="total-para">Total Seats:</p><span class="total-data">15</span>
<p class="avail-para">Available: </p><span class="avail-data">12</span>
<div class="location">
<p>Your Location:</p><i class="fas fa-map-marker-alt"></i><p>Asgard</p>
</div>
</div>
<div class="display-box">
<div class="lot-box inactive">1</div>
<div class="lot-box">2</div>
<div class="lot-box">3</div>
<div class="lot-box">4</div>
<div class="lot-box">5</div>
<div class="lot-box">6</div>
<div class="lot-box">7</div>
<div class="lot-box">8</div>
<div class="lot-box">9</div>
<div class="lot-box inactive">10</div>
<div class="lot-box inactive">11</div>
<div class="lot-box">12</div>
<div class="lot-box">13</div>
<div class="lot-box">14</div>
<div class="lot-box">15</div>
</div>
</main>
</div>
The problem can be noticed in full page view. The container div is a flexbox and contains the main-text div with flex-grow 0 and main tag with flex-grow 1. The main tag is a grid container with two grid items display-box and data-box. I am having difficulty in making them occupy all the space available to them in main tag as seen by the white blankspace.
The main element actually is stretching the full height of the container. In other words, flex-grow: 1 is working. (You may know this already.) The child elements (data-box and display-box) are not stretching the full height of the parent because they simply don't have enough content in them yet.
You also have data-box set to:
grid-template-rows: 3rem 2.5rem 2.5rem auto;
That creates four rows of a defined or content-based height. Using fr units covers available space.
grid-template-rows: 3fr 2fr 1fr auto;
revised codepen