I am trying to understand how CSS grids work. I've tried to make an example of a store item as practice, but I am at a loss.
Here's my how my CSS currently looks. Cut off at the top, weird spacing, and the right side is not coming together at all.
How's how it would ideally look
Here is my current CSS, I hope someone can help explain where I am misunderstanding the use of
CSS grids.
.store-currency {
height: 3vh;
}
.item {
display: flex;
align-items: center;
grid-row: 1 / span 2;
}
.currency {
display: flex;
align-items: center;
}
#num-bought-item0 {
display: flex;
align-items: center;
justify-content: right;
margin-right: 10px;
grid-column: 1 / span 2;
}
.store-item {
height: 15vh;
width: 100%;
display: grid;
grid-template-columns: 2fr;
grid-template-rows: 1fr 1fr;
font-size: 24px;
color: white;
border: 5px white solid;
justify-content: left;
align-items: center;
}
.store-item img {
margin: 10px;
height: 8vh;
}
.store-container {
display: flex;
height: 100%;
width: 30vw;
z-index: 0;
background-color: saddlebrown;
left: 0;
position: absolute;
text-align: center;
}
HTML:
<div class="store-container">
<div class="store-item" id="item0">
<div class ="item">
<img src="dumbell.png" alt="">
<span>Dumbbell</span>
</div>
<div id="num-bought-item0">
<span>Owned</span>
<span id="count-item0">0</span>
</div>
<div class="currency">
<img class="store-currency" src="coin.png" alt="">
<span>100000</span>
</div>
</div>
you did the first steps.
To get started you have to define a container element as a grid with display: grid, set the column and row sizes with grid-template-columns and grid-template-rows, and then place its child elements into the grid with grid-column and grid-row.
.store-container {
display: grid | inline-grid;
}
grid – generates a block-level grid
inline-grid – generates an inline-level grid
With grid-template-columns you can define how many columns will appear in your layout.
P.S Fr unit is a fractional unit and 1fr is for 1 part of the available space. In this example each column would take ~ 25% from the available space.
.container {
grid-template-columns: 1fr 1fr 1fr 1fr;
}
For your task, you can use grid-template-areas feature.
The grid-template-areas CSS property specifies named grid areas,
establishing the cells in the grid and assigning them names.
For example:
.item-a {
grid-area: header;
}
.item-b {
grid-area: main;
}
.item-c {
grid-area: sidebar;
}
.item-d {
grid-area: footer;
}
.container {
display: grid;
grid-template-columns: 50px 50px 50px 50px;
grid-template-rows: auto;
grid-template-areas:
"header header header header"
"main main . sidebar"
"footer footer footer footer";
}
This will generates something like that in modern browsers:
If you need more examples, take a look here:
https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-areas
https://css-tricks.com/snippets/css/complete-guide-grid/
Some of the examples are taken from the second site.
It looks like you are mixing flex and grid properties. grid-row and grid-column are only avalaible for a grid display (2D), not a flex display (1D).
You can try to play around with flex (worse choice since it is drawing a 1D layout) , you can use grid , which is made for this kind of layout.
Here a couple example with flex and grid
/* GRID make it simple*/
.grid {display:grid;}
#num-bought-item2 {grid-row:1/3;grid-column:2;}
#num-bought-item2 {display:grid;margin:auto;text-align:center}
/* layout done */
/* some reset for the demo*/
*{box-sizing:border-box;}
.store-container {display:grid;justify-content:center;}
.store-item {border:solid;}
.store-item>div {padding:0.5em;}
img{vertical-align:middle;}
[src="https://dummyimage.com/25/ff0"]{border-radius:50%}
big{color:darkgreen;background:lightyellow;}
/* FLEX make it a mess */
.flex {display:flex}
.column {flex-flow:column wrap;height:120px;}/* here an height is to be set so it wraps*/
/* since it is not made for this, we need to mess around */
.flex #num-bought-item1{order:2}/* reorder item */
.flex .item {height:0;min-height:60%;}/* hide it, then show it */
.flex .currency {height:0;min-height:40%;}/* hide it, then show it */
.flex #num-bought-item1{display:flex;flex-direction:column;justify-content:center;text-align:center;margin:auto;}
/* and flex did not do it */
<p>Let's try via flex</p>
<div class="store-container">
<div class="store-item flex column" id="item1">
<div class="item">
<img src="https://dummyimage.com/50" alt="">
<span>Dumbbell</span>
</div>
<div id="num-bought-item1" >
<span>Owned</span>
<span id="count-item1">0</span>
</div>
<div class="currency">
<img class="store-currency" src="https://dummyimage.com/25/ff0" alt="">
<span>100000</span>
</div>
</div>
</div>
<p>And via <big>grid</big> </p>
<div class="store-container">
<div class="store-item grid" id="item2">
<div class="item">
<img src="https://dummyimage.com/50" alt="">
<span>Dumbbell</span>
</div>
<div id="num-bought-item2" >
<span>Owned</span>
<span id="count-item1">0</span>
</div>
<div class="currency">
<img class="store-currency" src="https://dummyimage.com/25/ff0" alt="">
<span>100000</span>
</div>
</div>
</div>
Related
The div container is breaking my page. It's overriding a container used elsewhere. Is there any other alternative I can use to still have the same effect i.e the div columns sit next to each but at different screen resolutions, they stack on top of each other, and both retain equal width and length as they shrink?
How do I create two responsive divs that sit next to each other and stack on top of each other at different screen sizes? The dimensions are specific (each div is 350 x 217 px).
One div will have a text centred horizontally within the div but also left aligned and the other will be an image.
Below is the ideal end result. I'm a newbie to dev and this is for an assignment that's overdue. I've been fiddling around for the past couple of days and I keep going round in circles.
Responsive view on smaller screens:
* {
box-sizing: border-box;
}
.column {
flex: 1;
}
.left {
background-color: #e0e620;
}
.center {
margin: auto;
border: 3px solid green;
padding: 50px 50px;
}
.right {
background-color: #E5E5E5;
}
.row {
display: flex;
}
img {
width: 100%;
display: block;
}
#media screen and (max-width: 600px) {
.row {
width: 100vw;
display: block;
}
<div class="row">
<div class="column left">
<div class="center">The Info.<br />
<a class="link-button-green" href="" title="Info
guide">Download now</a>
</div>
</div>
<div class="column right">
<img src="https://via.placeholder.com/350x217.jpg">
</div>
</div>
The image is 350 x 217. Here is the ideal look below:
The below screen is what I would like to achieve without changing the existing width and height of yellow div? How do I go about achieving that?
add display: grid to the parent element .row;
add grid-template-columns: 1fr 1fr to the parent element (.row) to have a 2-column layout.
For screens at 600px or below you change the grid-template-columns to 1fr for the element .row to get a 1-column layout. To have both elements have the same height, you can use grid-auto-rows: 1fr on the parent element.
To maintain the normal block-level-behavior you add display: flex; flex-direction: column to the .left column. Flexbox will allow you do vertical center the text.
To vertical center the text you have to align it to the main-axis (flex-direction: column) with justify-content: center
* {
box-sizing: border-box;
}
.row {
display: grid;
grid-template-columns: 1fr 1fr;
}
#media only screen
and (max-width: 600px) {
.row {
grid-template-columns: 1fr;
grid-auto-rows: 1fr;
}
}
.left {
background-color: yellow;
display: flex;
flex-direction: column;
justify-content: center;
}
img {
width: 100%;
display: block;
object-fit: contain;
}
<div class="row">
<div class="column left">
<div class="center">The Info.<br />
<a class="link-button-green" href="" title="Info
guide">Download now</a>
</div>
</div>
<div class="column right">
<img src="https://via.placeholder.com/350x217.jpg">
</div>
</div>
Your question needs work.
You want the specific div widths to be 350px x 217px, but when you get to a min-width of 600px, that width of 350px isn't going to work anymore. You will struggle to have a responsive page if you set explicit heights and widths. You need to let elements fill their spaces naturally.
That said, I've created a solution that I think would work best based on the images you've provided.
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
img {
max-width: 100%;
height: auto;
}
.container {
display: flex;
flex-direction: column;
}
#media screen and (min-width: 600px) {
.container {
flex-direction: row;
min-height: 217px;
}
}
.inner {
background-color: #E0E61F;
display: flex;
justify-content: center;
align-items: flex-start;
flex-direction: column;
width: 100%;
min-height: 217px;
}
.inner span {
padding-left: 1rem;
min-height: unset;
}
.inner img {
min-height: 217px;
object-fit: cover;
}
<div class="container">
<div class="inner">
<span>The Info</span>
<span>Download Now</span>
</div>
<div class="inner">
<img src="https://placekitten.com/1600/900" alt="">
</div>
</div>
Like mentioned above i would start with mobile view. You can create a parent div around your two boxes called container with the following css properties
display:flex
flex-direction: column
Then add a media query set at the width you would like this divs to be side by side and change the flex direction on your container div to row
flex-direction: row
I have grid with 3 elements like this:
Now I want to replace blue elements with images (could be just dummy images).**
.grid-container {
display: grid;
grid-template-columns: 1fr 1fr;
grid-auto-rows: minmax(30em, auto);
justify-items: stretch;
align-items: stretch;
}
.grid-item-1 {
background: url("https://editzstock.com/wp-content/uploads/2022/04/broken-text-300x300.png");
background-size: cover;
overflow: hidden;
}
.grid-item-2 {}
.grid-item-3 {
grid-column: span 2;
grid-row: span 1;
}
.grid-item {
position: relative;
font-size: 25px;
padding: 20px;
padding-top: 50px;
background-color: #379AD6;
color: #222;
border: 1px solid white;
}
<div class="grid-container">
<div class="grid-item grid-item-1">
</div>
<div class="grid-item grid-item-2">
</div>
<div class="grid-item grid-item-3"></div>
</div>
Speaking just from experience over the past 7 years, images as grid / flex items often glitch in one way or another.
The glitch is almost always resolved by nesting the image in a container, making the container the grid / flex item.
Although images are valid as grid / flex items, until the various browsers make some more progress on this issue, I would suggest you use a container (thus keeping the images in a block formatting context).
I have a CSS grid, but I'm finding that the grid rows are not all fitting onto the page - instead, they're causing an overflow. How can I resize the grid rows so that they don't overflow the page? I thought the 1fr value was supposed to do this, but it doesn't seem to be working in my code.
I've had a look at Prevent content from expanding grid items and tried the suggested answers there (such as changing grid-template-rows: repeat(5, 1fr) to grid-template-rows: repeat(5, minmax(0, 1fr)); but to no avail.
I've tried adding height: 100% to the grid and it's container, but it is still overflowing.
JsFiddle https://jsfiddle.net/4g9b2qkL/
body,
html {
margin: 0;
height: 100%;
}
#container {
display: grid;
grid-template-columns: 1fr 5fr;
height: 100%;
}
#left {
grid-column: 1 / 2;
background: lightblue;
height: 100%;
}
#right {
grid-column: 2 / 3;
height: 100%;
}
#results {
display: grid;
grid-template-rows: repeat(5, 1fr);
height: 100%;
}
img {
max-height: 100%;
max-width: 100%;
}
<div id="container">
<div id="left">
<p>
Some stuff on the left....
</p>
</div>
<div id="right">
<h1>
Title
</h1>
<div id="results">
<div class="result">
<img src="https://upload.wikimedia.org/wikipedia/commons/6/62/Paracas_National_Reserve%2C_Ica%2C_Peru-3April2011.jpg" />
</div>
<div class="result">
Result 2
</div>
<div class="result">
Result 3
</div>
</div>
</div>
</div>
A few things to consider:
missing height reference
Using a percentage value to set the height of the img is problematic because there is no defined height on the container. Generally speaking, percentage heights should have a height reference on the parent for reliable rendering. Your declarations may or may not be ignored / misinterpreted.
See: Working with the CSS height property and percentage values
height: 100%
Setting the #results element to height: 100% is problematic, if you want to prevent a vertical overflow, because it doesn't factor in the height of the sibling (the h1).
height: 100% + height of h1 title > height of container (resulting in an overflow)
use a flexible height instead
Instead of using a percentage height, set a more flexible height, such as flex-grow. This tells the container to simply consume remaining space.
override the minimum height default
Grid and flex items are set by default to stop shrinking at the size of their content. Override that setting with min-height: 0.
See: Why don't flex items shrink past content size?
cross browser compatibility
Chrome can do the layout with less code (than posted below). It makes more assumptions about an author's intentions. Firefox, Edge and Safari assume less, so require more rules.
#container {
display: grid;
grid-template-columns: 1fr 5fr;
height: 100vh;
}
#left {
background: lightblue;
}
#right {
display: flex;
flex-direction: column;
height: 100vh;
}
#results {
flex-grow: 1;
min-height: 0;
display: grid;
grid-template-rows: repeat(5, 1fr);
}
.result {
min-height: 0;
}
img {
max-width: 100%;
max-height: 100%;
}
body {
margin: 0;
}
<div id="container">
<div id="left">
<p>Some stuff on the left....</p>
</div>
<div id="right">
<h1>Title</h1>
<div id="results">
<div class="result">
<img src="https://upload.wikimedia.org/wikipedia/commons/6/62/Paracas_National_Reserve%2C_Ica%2C_Peru-3April2011.jpg" />
</div>
<div class="result">Result 2</div>
<div class="result">Result 3</div>
</div>
</div>
</div>
You need to consider min-height:0 in different places and make some adjustment like below:
body,
html {
margin: 0;
height: 100%;
}
#container {
display: grid;
grid-template-columns: 1fr 5fr;
height: 100%;
}
#left {
grid-column: 1 / 2;
background: lightblue;
/*height: 100%; removed */
}
#right {
grid-column: 2 / 3;
/*height: 100%; removed */
min-height:0; /* here */
/* added */
display:flex;
flex-direction:column;
/**/
}
#results {
display: grid;
grid-template-rows: repeat(5, 1fr);
/*height: 100%; removed */
flex-grow:1; /* added */
min-height:0 /* here */
}
.result {
min-height:0 /* here */
}
img {
max-height: 100%;
max-width: 100%;
}
<div id="container">
<div id="left">
<p>
Some stuff on the left....
</p>
</div>
<div id="right">
<h1>
Title
</h1>
<div id="results">
<div class="result">
<img src="https://upload.wikimedia.org/wikipedia/commons/6/62/Paracas_National_Reserve%2C_Ica%2C_Peru-3April2011.jpg" />
</div>
<div class="result">
Result 2
</div>
<div class="result">
Result 3
</div>
</div>
</div>
</div>
I'm having a problem with vertical alignment with my text lines. I have two text lines, <p>, and I want to put the second one in the bottom of my <div> so I tried to do vertical-align: bottom and text-bottom and the top and bottom ones in my <p> and that didn't work.
.header {
grid-area: header;
background-color: red;
display: grid;
grid-template-areas: 'headerLeft rest headerRight';
grid-template-columns: 10% 1fr 30%;
padding: 5px;
}
.header p {
margin: 0px;
}
.headerRight {
grid-area: headerRight;
}
.headerRight p {
float: right;
}
<div class="layout">
<div class="header">
<div class="headerRight">
<p style="margin: 0px 0px 0px 1px;"><img src="https://i.imgur.com/V2aWxOK.png" style="height: 13vh" /></p>
<p><img src="https://i.imgur.com/V2aWxOK.png" style="height: 13vh" /></p>
<p style="margin: 0px 5px 0px 0px">Ola</p>
<br />
<p style="margin: 0px 5px 0px 0px">Ola</p>
</div>
</div>
</div>
I'd suggest the following, which involves some minor updates to your HTML; explanations are in the comments to the code itself:
.header {
grid-area: header;
background-color: red;
display: grid;
grid-template-areas: 'headerLeft rest headerRight';
grid-template-columns: 10% 1fr 30%;
padding: 5px;
}
.header p {
margin: 0px;
}
.headerRight {
grid-area: headerRight;
/* here we specify the use of CSS Grid layout: */
display: grid;
/* define the top-and-bottom (0) and left-and-right (5px) grid
gap gutters: */
grid-gap: 0 5px;
/* define the named areas of the grid: */
grid-template-areas:
". paragraphAreaOne imageOne imageTwo"
". . imageOne imageTwo"
". paragraphAreaTwo imageOne imageTwo";
/* define the sizing of the columns; here we have the first column
taking up one fractional unit (1fr), with the other columns sized,
using the repeat() function, at min-content in order to have those
grid-columns sized to the minimum necessary to contain their content: */
grid-template-columns: 1fr repeat(3, min-content);
/* here we have three rows each sized, using the repeat() function,
to size each row to min-content: */
grid-template-rows: repeat(3, min-content);
}
/* positioning the various elements into the appropriate grid areas: */
.headerRight p:first-of-type {
grid-area: paragraphAreaOne;
}
.headerRight p:nth-of-type(2) {
grid-area: paragraphAreaTwo;
}
.headerRight img:first-of-type {
grid-area: imageOne;
}
.headerRight img:nth-of-type(2) {
grid-area: imageTwo;
}
<div class="layout">
<div class="header">
<div class="headerRight">
<!-- your img elements were wrapped in <p> elements, which were removed,
partially for semantic reasons, and partially because they were
simply unnecessary -->
<img src="https://i.imgur.com/V2aWxOK.png" style="height: 13vh" />
<img src="https://i.imgur.com/V2aWxOK.png" style="height: 13vh" />
<p>Ola</p>
<!-- there was a <br> element here which, when using a Grid layout
serves no purpose, so was removed -->
<p>Ola</p>
</div>
</div>
</div>
JS Fiddle demo.
References:
gap/ grid-gap
grid-template-areas.
grid-template-columns.
grid-template-rows.
min-content.
repeat().
you are using grid so u can use align-items:end to the header and it will align your elements to the bottom here take a look at it https://developer.mozilla.org/en-US/docs/Web/CSS/align-items
If I have a 3 column grid and I want the content to appear in the 2 column: am I understanding correctly that the content HAS to go in the 2nd column in the HTML, and I have to create an empty div in the HTML?
In the grid below I want the title to appear in the middle column so I've created an empty div before this.
There's no way of getting the title to appear in the middle one of the 3 columns whilst only using one div is there?
** Note I haven't included a div for the 3rd column because I don't need to.
Codepen: https://codepen.io/emilychews/pen/rEoKPg
Code snippet also included below.
body {
margin: 0;
padding: 0;
display: flex;
height: 100vh;
width: 100%;
justify-content: center;
align-items: center;
}
.row {
width: 50%;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-gap: 1rem;
}
.grid {
background: #f1f1f1;
padding: 1rem;
}
<div class="row">
<div class="grid grid-item-1"></div>
<div class="grid grid-item-2">The Title</div>
</div>
You don't have to create an empty div if you use grid-column-start, but you will need to specify the column number.
<div class="row">
<div class="grid grid-item-2">The Title</div>
</div>
body {
margin: 0;
padding: 0;
display: flex;
height: 100vh;
width: 100%;
justify-content: center;
align-items: center;
}
.row {
width: 50%;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-gap: 1rem;
}
.grid {
background: #f1f1f1;
padding: 1rem;
}
.grid-item-2 {
grid-column-start: 2;
}
Yes, you can. Remove the first div then add this to your css code:
.grid-item-2 {
grid-column-start: 2;
}
Check this article on CSS Tricks with a quick cheatsheet on CSS Grids: A Complete Guide to Grid | CSS Tricks
The MDN reference is very good also: CSS Grid Layout | MDN