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>
Related
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.
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)
In the code below, I am trying to implement a grid made of 2 rows of 3 images in the bottom right corner only. The grid should not be bigger than the other quarters. In other words, I would like each quarter to be of the same size, but the bottom right one should have these 2 rows of 3 images.
My key objective is to have a method which collapses into a single column on small screens, with the images on top of each other. So on small screens, there shouldn't be any more grids, but just a column of images below the 3 quarters:
On normal screen:
| Hello World | 2 |
| | |
| 3 | img img img |
| | img img img |
On small screens:
Hello World
2
3
img
img
img
img
img
img
Here is my code, which does not work...
<!DOCTYPE html>
<html>
<head>
<style>
.box.md {
grid-column: span 2;
grid-row: span 2;
}
.box.lg {
grid-column: span 2;
grid-row: span 2;
}
.container {
padding: 20px;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
grid-auto-rows: 240px;
grid-auto-flow: dense;
grid-gap: 8px;
}
.box {
background: yellow;
display: flex;
justify-content: center;
align-items: center;
font-size: 48px;
font-weight: bold;
}
.grid-container {
display: grid;
grid-template-columns: auto auto auto;
}
.item1 {
grid-row-start: 1;
grid-row-end: 3;
}
</style>
</head>
<body>
<h1>Test:</h1>
<div class="container">
<div class="box md">
<p> Hello World </p>
</div>
<div class="box md">2</div>
</div>
<div class="container">
<div class="box md">3</div>
<div class="container">
<div class="row" >
<div class="grid-container">
<div class="item1">
<a><img src="AI.jpg"></a>
</div>
<div class="item2">
<a><img src="AI.jpg"></a>
</div>
<div class="item3">
<a><img src="AI.jpg"></a>
</div>
<div class="item4">
<a><img src="AI.jpg"></a>
</div>
<div class="item5">
<a><img src="AI.jpg"></a>
</div>
<div class="item6">
<a><img src="AI.jpg"></a>
</div>
</div>
</div>
</div>
</div>
.box.md {
grid-column: span 2;
grid-row: span 2;
}
.box.lg {
grid-column: span 2;
grid-row: span 2;
}
.container {
padding: 20px;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
grid-auto-rows: 240px;
grid-auto-flow: dense;
grid-gap: 8px;
}
.box {
background: yellow;
display: flex;
justify-content: center;
align-items: center;
font-size: 48px;
font-weight: bold;
}
.grid-container {
display: grid;
grid-template-columns: auto auto auto;
}
.item1 {
grid-row-start: 1;
grid-row-end: 3;
}
<h1>Test:</h1>
<div class="container">
<div class="box md">
<p> Hello World </p>
</div>
<div class="box md">2</div>
</div>
<div class="container">
<div class="box md">3</div>
<div class="container">
<div class="row">
<div class="grid-container">
<div class="item1">
<a><img src="AI.jpg"></a>
</div>
<div class="item2">
<a><img src="AI.jpg"></a>
</div>
<div class="item3">
<a><img src="AI.jpg"></a>
</div>
<div class="item4">
<a><img src="AI.jpg"></a>
</div>
<div class="item5">
<a><img src="AI.jpg"></a>
</div>
<div class="item6">
<a><img src="AI.jpg"></a>
</div>
</div>
</div>
</div>
</div>
Could anyone help me solve this problem?
Kind regards,
-Pierre.
Using flex with wrap to layout your main "grid". Using grid with auto-fit columns to layout the pictures.
I did that because I suppose you are after a fluid layout. It would be much easier to adapt to any screen using media queries...
You should try the snippet in full-screen and test with various windows sizes. Pictures layout can be suited to your requirements by changing the pixel size in minmax(240px, 1fr) for .grid-container.
.container {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.container > * {
flex: 1;
min-width: 300px;
min-height: 250px;
}
.box {
background: yellow;
display: flex;
justify-content: center;
align-items: center;
font-size: 48px;
font-weight: bold;
}
.grid-container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
grid-auto-rows: minmax(120px, max-content);
gap: .5rem;
padding: .5rem;
}
.grid-container a {
display: flex;
align-items: center;
justify-content: center;
max-height: 100%;
max-width: 100%;
}
.grid-container img {
display: block;
max-width: 100%;
max-height: 100%;
}
<h1>Test:</h1>
<div class="container">
<div class="box md">
<p> Hello World </p>
</div>
<div class="box md">2</div>
</div>
<div class="container">
<div class="box md">3</div>
<div class="container">
<div class="row">
<div class="grid-container">
<div class="item1">
<a><img src="https://picsum.photos/seed/pic1/300/200"></a>
</div>
<div class="item2">
<a><img src="https://picsum.photos/seed/pic2/300/200"></a>
</div>
<div class="item3">
<a><img src="https://picsum.photos/seed/pic3/300/200"></a>
</div>
<div class="item4">
<a><img src="https://picsum.photos/seed/pic4/300/200"></a>
</div>
<div class="item5">
<a><img src="https://picsum.photos/seed/pic5/300/200"></a>
</div>
<div class="item6">
<a><img src="https://picsum.photos/seed/pic6/300/200"></a>
</div>
</div>
</div>
</div>
</div>
You coumd try something with calc() and clamp() to give a minmax() value to your columns dependind on a set px value to init calc(clamp()) ; and the unknown value that is 100vw. Playing around with those, it allows you to set a min and max-width while the calc() function updates with the viewport's width. It can give a failing value (if calculation turns out to be less than 0).
Once you understood how it worked, you can use your own values to reset your breakpoints without a mediaquerie but auto-fit.
Example setting every items as direct child of the container and using nested grid with different calc(clamp()) setting :
* {box-sizing:border-box;}
.container {
display:grid;
grid-template-columns: repeat(auto-fit,minmax(clamp(calc(((200px + 50vw ) * 2 ) - 100vw ), 40vw, 100% ) ,1fr));
gap:1em;
width:100%;
}
.box.md {
max-width:100%;
border:solid;
color:red;
justify-content:space-around;
}
.box.md.img {
width: 100%;
grid-template-columns: repeat(auto-fit,minmax(calc(((140px + 25vw) * 2) - 50vw) ,1fr));
}
.box.md.img img {
width:100%;
}
<h1>Test: grid layout</h1>
<div class="container">
<div class="box md">
<p> Hello World </p>
</div>
<div class="box md">2</div>
<div class="box md">3</div>
<div class="box md img container">
<div class="item1 box img ">
<a><img src="https://dummyimage.com/200x100/&text=AI.jpg"></a>
</div>
<div class="item2 box img">
<a><img src="https://dummyimage.com/200x100/&text=AI.jpg"></a>
</div>
<div class="item3 box img">
<a><img src="https://dummyimage.com/200x100/&text=AI.jpg"></a>
</div>
<div class="item4 box img">
<a><img src="https://dummyimage.com/200x100/&text=AI.jpg"></a>
</div>
<div class="item5 box img">
<a><img src="https://dummyimage.com/200x100/&text=AI.jpg"></a>
</div>
<div class="item6 box img">
<a><img src="https://dummyimage.com/200x100/&text=AI.jpg"></a>
</div>
</div>
</div>
Pen to play with : https://codepen.io/gc-nomade/pen/PopPNoJ
See if this helps with the images grid
.container {
display: grid;
grid: auto auto/ 1fr 1fr 1fr;
}
#media (max-width: 450px) {
.container {
grid: auto / auto;
grid-auto-flow: row;
}
}
<div class="container">
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
</div>
}
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
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>