CSS Grids - Padding causes child element to overflow - html

Here's my code:
.media {
display: grid;
box-sizing: border-box;
padding: 10rem;
border: 1px solid red;
grid-template-columns: repeat(auto-fit, minmax(50rem, 1fr));
}
.big-pic {
width: 100%;
height: 10rem;
border: 1px solid blue;
}
.small-pic {
display: inline-block;
margin-right: -.5rem;
width: 50%;
height: 10rem;
border: 1px solid blue;
}
<div class="media">
<div class="column">
<h2>On TV</h2>
<div class="big-pic">
Main Pic
</div>
<div class="small-pic">
Pic 1
</div>
<div class="small-pic">
Pic 2
</div>
</div>
<div class="column">
<h2>In Theaters </h2>
<div class="small-pic">
Pic 1
</div>
<div class="small-pic">
Pic 2
</div>
<div class="big-pic">
Main Pic
</div>
</div>
When you lower the screen size of the browser, the child elements will overflow out of the container. Why is not the column (a wrapper <div> with a class of column) width not filling the parent's width?
I used grid-template-columns: repeat(auto-fit, minmax(50rem, 1fr)); So 1fr should fill up the parent's width. When you add the padding, it overflows. Without the padding, it fills up the parent's width. Not sure what's happening.
Adding box-sizing: border-box doesn't fix the issue either. Any ideas on how to fix it?

Related

Grid container not expanding to fit children

I'm creating a 3-column grid.
Each cell uses clamp(Xem, 33.33%, Xem) so there is a min size for big screens as well as a max size for small screens. If the screen is too small, the idea is that the grid's container will support that by becoming horizontally scrollable.
The page itself has left and right margins of 1em. To make the experience nice, the horizontally scrollable grid container uses negative margins and equal padding on the left and right so that it feels that the entirety of the width of the screen is visible and scrollable.
See the demo below where I've simulated the grid's behaviour in different screen sizes by manipulating the min and max of the clamp. You can see in the big size and perfect size screens it works nicely. The padding on both sides is visible.
However, for small screens, when it becomes scrollable, you scroll to the right and the right side padding is not there. This seems to be because the grid div itself is not stretching to accomodate its children, and so its parent's padding isn't "reaching" the right side (yet somehow, the grid's horizontal scroll container is aware that its content stretches - not sure how that works but that's a different topic I think).
The grid div is outlined in red. You can inspect it, along with the horizontal container, and see that the right padding ends halfway through the grid horizontally rather than at the end of the grid where one would expect it to be.
.background {
background-color:#f003;
overflow: hidden;
display: flex;
justify-content: center;
}
.scrollcontainer {
background-color:#ff03;
width: 300px;
height: 400px;
padding-left: 1em;
overflow: scroll;
padding-right: 1em;
}
.scrollGrid {
margin-left: -1em;
margin-right: -1em;
padding-left: 1em;
padding-right: 1em;
width: 100%;
background-color: #00f3;
overflow-y: scroll
}
.grid {
display:grid;
width: fit-content;
min-width: 100%;
background-color: #f0f3;
outline: 1px solid red;
}
.grid.perfect {
grid-template-columns: repeat(3, clamp(2em, 33.33%, 30em));
}
.grid.small {
grid-template-columns: repeat(3, clamp(9em, 33.33%, 10em));
font-size: 1.5em;
}
.grid.big {
font-size: 0.5em;
grid-template-columns: repeat(3, clamp(2em, 33.33%, 5em));
}
.grid > div {
height: 50px;
border: 1px solid black;
padding: 1em;
}
<div class="background">
Background
<div class="scrollcontainer">
<h2>Scrollable section of stuff here</h2>
<p>simulated perfect screen</p>
<div class="scrollGrid">
<div class="grid perfect">
<div>Cell 1</div>
<div>Cell 2</div>
<div>Cell 3</div>
</div>
</div>
<p>simulated small screen (this is where the problem is, scroll hroizontally and notice there is no padding on the right side, the grid container ends where the blue ends)</p>
<div class="scrollGrid">
<div class="grid small">
<div>Cell 1</div>
<div>Cell 2</div>
<div>Cell 3</div>
</div>
</div>
<p>simulated big screen (works as desired)</p>
<div class="scrollGrid">
<div class="grid big">
<div>Cell 1</div>
<div>Cell 2</div>
<div>Cell 3</div>
</div>
</div>
<p>more text to show that this is scrollable</p>
</div>
</div>
Thank you to anyone who sheds light on this.
Using minmax instead of clamp fixed the issue for me. Not sure why. minmax(2em, min(33.33%, 30em)). The problem also still seems to happen when using minmax(max(2em, 33.33%, 30em)), so I'm not sure why it only works for the former.
.background {
background-color:#f003;
overflow: hidden;
display: flex;
justify-content: center;
}
.scrollcontainer {
background-color:#ff03;
width: 300px;
height: 400px;
padding-left: 1em;
overflow: scroll;
padding-right: 1em;
}
.scrollGrid {
margin-left: -1em;
margin-right: -1em;
padding-left: 1em;
padding-right: 1em;
width: 100%;
background-color: #00f3;
overflow-y: scroll
}
.grid {
display:grid;
width: fit-content;
min-width: 100%;
background-color: #f0f3;
outline: 1px solid red;
}
.grid.perfect {
grid-template-columns: repeat(3, minmax(2em, min(33.33%, 30em)));
}
.grid.small {
grid-template-columns: repeat(3, minmax(9em, min(33.33%, 10em)));
font-size: 1.5em;
}
.grid.big {
font-size: 0.5em;
grid-template-columns: repeat(3, clamp(2em, 33.33%, 5em));
}
.grid > div {
height: 50px;
border: 1px solid black;
padding: 1em;
}
<div class="background">
Background
<div class="scrollcontainer">
<h2>Scrollable section of stuff here</h2>
<p>simulated perfect screen</p>
<div class="scrollGrid">
<div class="grid perfect">
<div>Cell 1</div>
<div>Cell 2</div>
<div>Cell 3</div>
</div>
</div>
<p>simulated small screen (this is where the problem was, not scrolling to the side reveals the grid element stretched all the way to the end and the appropriate padding)</p>
<div class="scrollGrid">
<div class="grid small">
<div>Cell 1</div>
<div>Cell 2</div>
<div>Cell 3</div>
</div>
</div>
<p>simulated big screen (works as desired)</p>
<div class="scrollGrid">
<div class="grid big">
<div>Cell 1</div>
<div>Cell 2</div>
<div>Cell 3</div>
</div>
</div>
<p>more text to show that this is scrollable</p>
</div>
</div>

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

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)

Vertically center text in a grid layout with grid and items 100% height [duplicate]

This question already has answers here:
How to vertically align text inside a flexbox?
(13 answers)
Closed last year.
Here's an SO question about exactly this, and I've found several others. Many of them have a dozen answers, using many (many!) combinations of align and justify styles, transforms, margins, references to table cells, etc.
I've tried maybe 200 combinations of ideas from references. Is it possible to center the text vertically? Is it possible to do it while maintaining 100% height without adding divs around or inside the boxes?
My main finding after all this is that height: 100% thwarts every other style that can succeed. For example, margin-top and margin-bottom set to auto works, but not with 100% height.
section {
height: 400px;
}
#boxes {
background-color: green;
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 1fr);
gap: 6px;
height: 100%;
min-height: 10em;
min-width: 12em;
}
#boxes>div {
background-color: #8ca0ff;
text-align: center;
border: 1px solid red;
height: 100%;
}
<section>
<div id="boxes">
<div id="00">I'm not</div>
<div id="01">vertically</div>
<div id="02">centered.</div>
<div id="10">I</div>
<div id="11">am not</div>
<div id="12">either!</div>
<div id="20">Was CSS designed</div>
<div id="21">by a psychopath?</div>
<div id="22">Seems like it!</div>
</div>
</section>
I am astonished at how non-simple this simple-seeming thing is.
Put flex on the boxes, just like in an answer on the post you linked.
https://css-tricks.com/snippets/css/a-guide-to-flexbox
section {
height: 400px;
}
#boxes {
background-color: green;
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 1fr);
gap: 6px;
height: 100%;
min-height: 10em;
min-width: 12em;
}
#boxes>div {
background-color: #8ca0ff;
text-align: center;
border: 1px solid red;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
}
<section>
<div id="boxes">
<div id="00">I'm not</div>
<div id="01">vertically</div>
<div id="02">centered.</div>
<div id="10">I</div>
<div id="11">am not</div>
<div id="12">either!</div>
<div id="20">Was CSS designed</div>
<div id="21">by a psychopath?</div>
<div id="22">Seems like it!</div>
</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

How to left-align items with each other in a grid that used justify-items: center

I am using grid. I centered my items but i want left position to be same on cross axis.
.box {
display: grid;
grid-template-columns: 1fr;
padding: 10px;
border: 1px solid blue;
gap: 1rem;
justify-items: center;
}
img {
width: 200px;
}
<div class="box">
<img src="img/featured.jpg">
<div class="item2">Item 2 Lorem</div>
</div>
Note : i want solution in only grid. There is many temporary fixes for that but i don't want that because i am looking for a perfect standard grid alignment solution for it.
You can do it a few ways:
1. Fixed Width Text (Not Responsive)
Based on the information you gave in your question. you can simply set the width of the item2 div to be the same as the image, e.g.:
.box {
display: grid;
grid-template-columns: 1fr;
padding: 10px;
border: 1px solid blue;
gap: 1rem;
justify-items: center;
}
.item2,
img {
width: 200px;
}
<div class="box">
<img src="https://via.placeholder.com/200x150">
<div class="item2">Item 2 Lorem</div>
</div>
2. The Responsive Way
This will allow us to responsively set up the 2 separate alignments you require: centre the container element, and left-align its contents, e.g.
<div class="box">
<div class="boxcontent">
Content here...
</div>
</div>
CSS: .boxcontent { text-align: left; }
Why this works:
You must have a defined relationship between the image and text, otherwise there is no way to tell the grid that these 2 individual elements must be positioned in relation to each other. You can do this by putting them in a container.
If you think about it, you are trying to do 2 separate alignments here:
make the image and text be centred in relation to the grid but also
make them be in alignment with each other so they are left aligned.
Putting them in a container achieves both of these objectives by creating a relationship between the image and text so that:
they act as a single unit in relation to the grid and also
allow them to be positioned in relation to each other regardless of the grid
Working Example:
.box {
display: grid;
grid-template-columns: 1fr;
padding: 10px;
border: 1px solid blue;
gap: 1rem;
justify-items: center;
}
.boxcontent {
text-align: left;
}
img {
width: 200px;
}
<div class="box">
<div class="boxcontent">
<img src="https://via.placeholder.com/200x150">
<div class="item2">Item 2 Lorem</div>
</div>
</div>
.box {
display: block;
margin: 0 auto;
width: max-content;
padding: 10px;
border: 1px solid blue;
}
img {
width: 200px;
}
.item2 {
margin-top: 1rem;
}
<div class="box">
<img src="pic_trulli.jpg" alt="Hi dear">
<div class="item2">Item 2 Lorem</div>
</div>