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.
Related
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)
I have made this simple example of my current grid setup:
document.querySelectorAll(".element").forEach(box =>
box.addEventListener("click", () => box.classList.toggle("compressed"))
)
.container{
display:grid;
grid-template-columns: repeat(3, min-content);
grid-template-rows:repeat(3, min-content);
grid-auto-flow:column;
gap:1rem;
}
.element{
background-color:brown;
border:1px solid black;
width:10rem;
height:10rem;
text-align:center;
color:white;
line-height:10rem;
font-size:2rem;
}
.elementBig{
grid-row-end: span 2;
height:21rem;
}
.compressed{
height:2rem;
}
<div class="container">
<div class="element elementBig">big</div>
<div class="element">1</div>
<div class="element">2</div>
<div class="element">3</div>
<div class="element">4</div>
<div class="element">5</div>
<div class="element">6</div>
<div class="element">7</div>
<div class="element">8</div>
<div class="element">9</div>
<div class="element">10</div>
</div>
when you click on a cell it's reduced but the next one does not rise up: let's say I click on "big" element, I want that "1" to rise up
in addiction i want rows and columns number to be dynamic so in the real grid i'am using this setup:
--n-colonne: 3; //per impostare massimo numero di colonne a 3 su grandi display
display: grid;
$larghezza-senza-spazi: calc(100% - (var(--n-colonne) - 1) * 1rem);
grid-template-columns: repeat(auto-fill, minmax(max(45rem, ($larghezza-senza-spazi)/var(--n-colonne)), 1fr));
grid-template-rows: repeat(12, min-content);
grid-gap: 1rem;
that will need some fix if "grid-auto-flow:column" is to be used
The problem you're facing: A grid has rows and rows have a certain height (in your case: min-content, which is 10rem as long as at least one box in the row is not compressed). In addition to that, your big box is supposed to always take up two rows as per your definition (grid-row-end: span 2;), so resizing the content of the grid-cell won't change anything.
Not sure if grid is the way to go here, there might be a solution in the new masonry addition in CSS3. Maybe give this a read: https://www.smashingmagazine.com/native-css-masonry-layout-css-grid/
However: If you can settle on a number of cols (or calculate this somehow by using js), just place your boxes accordingly in cols and it works just fine.
document.querySelectorAll(".element").forEach(box =>
box.addEventListener("click", () => box.classList.toggle("compressed"))
)
.container {
display: grid;
grid-template-columns: repeat(3, min-content);
grid-auto-flow: column;
gap: 1em;
}
.element {
background-color: brown;
border: 1px solid black;
width: 10rem;
height: 10rem;
text-align: center;
color: white;
line-height: 10rem;
font-size: 2rem;
margin-bottom: 0.5em;
}
.elementBig {
grid-row-end: span 2;
height: 21rem;
}
.compressed {
height: 2rem;
overflow: hidden;
}
<div class="container">
<div class="col1">
<div class="element elementBig">big</div>
<div class="element">1</div>
</div>
<div class="col2">
<div class="element">2</div>
<div class="element">3</div>
<div class="element">4</div>
</div>
<div class="col3">
<div class="element">5</div>
<div class="element">6</div>
<div class="element">7</div>
</div>
<div class="col4">
<div class="element">8</div>
<div class="element">9</div>
<div class="element">10</div>
</div>
</div>
If thats not an option, you can always use flexbox, but it comes with its own challenges:
document.querySelectorAll(".element").forEach(box =>
box.addEventListener("click", () => box.classList.toggle("compressed"))
)
.container {
display: flex;
flex-flow: column wrap;
width: 100%;
max-height: 800px;
gap: 1rem;
}
.element {
background-color: brown;
border: 1px solid black;
width: 200px;
height: 200px;
text-align: center;
color: white;
line-height: 10rem;
font-size: 2rem;
}
.elementBig {
height: 21rem;
}
.compressed {
height: 2rem;
}
<div class="container">
<div class="element elementBig">big</div>
<div class="element">1</div>
<div class="element">2</div>
<div class="element">3</div>
<div class="element">4</div>
<div class="element">5</div>
<div class="element">6</div>
<div class="element">7</div>
<div class="element">8</div>
<div class="element">9</div>
<div class="element">10</div>
</div>
I understand that fr is calculated based on available space in the grid container. I have a situation where I have a grid container that I want to split into 5 columns. The children however, are dynamically generated and depending on the situation, it could be 3 children or 4 or 5. I still want to keep the 5-column grid intact with the specified grid-column-gap, but I want the grid to start populating the elements from the right. Please see my code below: https://codepen.io/skepticacid/pen/dyGxaJb
<html>
<body>
<div class = "grid-container">
<div class = "grid-child">1</div>
<div class = "grid-child">2</div>
<div class = "grid-child">3</div>
<div class = "grid-child">4</div>
<div class = "grid-child">5</div>
</div>
<div class = "grid-container">
<div class = "grid-child">1</div>
<div class = "grid-child">2</div>
<div class = "grid-child">3</div>
<div class = "grid-child">4</div>
</div>
<div class = "grid-container">
<div class = "grid-child">1</div>
<div class = "grid-child">2</div>
<div class = "grid-child">3</div>
</div>
</body>
</html>
html{
font-size: 16px;
}
.grid-container {
background-color: coral;
display: grid;
grid-template-columns: repeat(5, 1fr);
grid-column-gap: 1rem;
justify-content: end;
align-items: center;
padding: 1rem;
margin-bottom: 2rem;
}
.grid-child{
background-color: saddlebrown;
color: white;
padding: 1rem;
}
5 elements is the happy path. However, when it comes down to 4 or 3 elements, I want them to be aligned similar to a justify-content: end or flex-end (so in the 4-column example, I want div number 4 to align with div number 5 above). Also, I also want to retain the width of the column to match the ones in the 5-column width.
Is this possible through CSS grid? Apologies, if I'm missing something glaringly obvious.
There is no such property to reverse the flow in CSS-Grid.
One solution (which does not scale nicely) is to use nth-last-child in this situation to designate which column is required.
html{
font-size: 16px;
}
.grid-container {
background-color: coral;
display: grid;
grid-template-columns: repeat(5, 1fr);
grid-gap: .25rem;
padding: 1rem;
}
.grid-child{
background-color: saddlebrown;
color: white;
padding: 1rem;
}
.grid-child:nth-last-child(1) {
grid-column:5;
}
.grid-child:nth-last-child(2) {
grid-column:4;
}
.grid-child:nth-last-child(3) {
grid-column:3;
}
.grid-child:nth-last-child(4) {
grid-column:2;
}
.grid-child:nth-last-child(5) {
grid-column:1;
}
<html>
<body>
<div class="grid-container">
<div class="grid-child">1</div>
<div class="grid-child">2</div>
<div class="grid-child">3</div>
<div class="grid-child">4</div>
<div class="grid-child">5</div>
</div>
<div class="grid-container">
<div class="grid-child">1</div>
<div class="grid-child">2</div>
<div class="grid-child">3</div>
<div class="grid-child">4</div>
</div>
<div class="grid-container">
<div class="grid-child">1</div>
<div class="grid-child">2</div>
<div class="grid-child">3</div>
</div>
</body>
</html>
If that you want it this way
direction: rtl;
if issue with direction hope it solve it.
last answer:
justify-items: center;
Doesn't matter.
We can make use of auto-fit Which only creates columns when needed unlike auto-fill and the current setup which creates columns even when not needed.
This will work if we know the maximum number of columns we're going to have we'll go with 5.
Our grid-template-columns becomes like this:
grid-template-columns: repeat(auto-fit, minmax(0px,calc((100% - ( .25rem * 4)) / 5)));
Instead of the predefined 5 columns we calculate 5 columns from the width of the parent, Subtracting the grid-gap
And finally we apply justify-content: flex-end;
.grid-container {
background-color: coral;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(0,calc((100% - ( .25rem * 4)) / 5)));
grid-gap: .25rem;
padding: 1rem;
justify-content: flex-end;
}
.grid-child {
background-color: saddlebrown;
color: white;
padding: 1rem;
}
<div class="grid-container">
<div class="grid-child">1</div>
<div class="grid-child">2</div>
<div class="grid-child">3</div>
<div class="grid-child">4</div>
<div class="grid-child">5</div>
</div>
<div class="grid-container">
<div class="grid-child">1</div>
<div class="grid-child">2</div>
<div class="grid-child">3</div>
<div class="grid-child">4</div>
</div>
<div class="grid-container">
<div class="grid-child">1</div>
<div class="grid-child">2</div>
<div class="grid-child">3</div>
</div>
I would like to align horizontally on a single line a bunch of divs of class a within a container div.
Why is the below css code not working ?
.a {
border: 1px solid black;
}
#container {
display:grid;
grid-auto-columns: minmax(10px, 35px);
grid-template-rows:1fr;
}
I have created a jsFiddle for it. I was expecting the divs 1 to 6 there to all be on the same line but I get the following result :
You need to change the default flow ref to column:
.a {
border: 1px solid black;
}
#container {
display: grid;
grid-auto-columns: minmax(10px, 35px);
grid-template-rows: 1fr;
grid-auto-flow:column; /* added */
}
<div id="container">
<div class="a">
1
</div>
<div class="a">
2
</div>
<div class="a">
3
</div>
<div class="a">
4
</div>
<div class="a">
5
</div>
<div class="a">
6
</div>
</div>
Or define a template column like below:
.a {
border: 1px solid black;
}
#container {
display: grid;
grid-template-columns:repeat(auto-fill, minmax(10px, 35px));
grid-template-rows: 1fr;
}
<div id="container">
<div class="a">
1
</div>
<div class="a">
2
</div>
<div class="a">
3
</div>
<div class="a">
4
</div>
<div class="a">
5
</div>
<div class="a">
6
</div>
</div>
Try below code:
CSS:
#container {
display: grid;
grid-template-rows: 1fr;
grid-template-columns: repeat(auto-fill, minmax(75px, 1fr));
grid-gap: 1rem;
}
Note: Its align horizontally on a single line.
I'm trying to make a grid with items/pizza toppings to order, and I would like an "Add to cart" button under each item in the grid. How would I go about doing that?
So far I've tried simply putting a button with a line break under an element but as assumed, that didn't work.
Here is the relevant code I have in the body:
.wrapper {
width: 90%;
margin: 0 auto;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
grid-auto-rows: 200px;
grid-row-gap: 30px;
grid-column-gap: 10px;
}
.item {
background: firebrick;
color: white;
padding: 10px;
}
.item:nth-child(even) {
background: rgb(139, 19, 19);
}
.add {
margin-bottom: 100px;
}
button {
margin-bottom: 100px;
}
#container {
background-color: maroon;
width: 1500px;
height: 1200px;
margin-left: auto;
margin-right: auto;
border-color: black;
border-width: 10px;
border-style: double;
}
<div id="container">
<div id="header">
<h1> Pizza Planet </h1>
<script src="index.js"></script>
</div>
<div id="content">
<h2>Select your items:</h2>
<div class="wrapper">
<div class="item">1</div>
<div class="add"><button>Add To Cart</button></div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
<div class="item">7</div>
<div class="item">8</div>
<div class="item">9</div>
</div>
</div>
</div>
All that does is make a huge gap for another cell on the grid with a tiny add to cart button on there. Any help would be appreciated, thank you.
One approach might be to use CSS grid to achieve what you require. A simple grid layout for what you describe above could be done like this:
.item img {
width:100%;
/* Causes the button to sit below the img */
display:block;
}
.item button {
width:100%;
}
.grid {
/* Specifies css grid to be used */
display:grid;
/* Specifies the number of columns and sizes in the grid */
grid-template-columns: 1fr 1fr;
/* Specifies spacing between grid cells */
grid-gap:1rem;
}
<div class="grid">
<div class="item">
<img src="http://wallpapersdsc.net/wp-content/uploads/2015/11/Pizza_Images12.jpg" />
<button>Order</button>
</div>
<div class="item">
<img src="http://wallpapersdsc.net/wp-content/uploads/2015/11/Pizza_Images12.jpg" />
<button>Order</button>
</div>
<div class="item">
<img src="http://wallpapersdsc.net/wp-content/uploads/2015/11/Pizza_Images12.jpg" />
<button>Order</button>
</div>
<div class="item">
<img src="http://wallpapersdsc.net/wp-content/uploads/2015/11/Pizza_Images12.jpg" />
<button>Order</button>
</div>
</div>