CSS-Grid: How to center content without shrinking the item itself? [duplicate] - html

This question already has answers here:
Centering in CSS Grid
(9 answers)
Closed 3 years ago.
Using CSS-Grid, I try to put my items in the center of a grid cell, without shrinking them completely to only the content. Is this possible?
I made a simple example on stackblitz. You can see that the items there don't fill the entire grid-cell with the background color. What is the proper way to get that working? I can remove the justify-items/align-items classes, but then the content isn't centered anymore.
https://stackblitz.com/edit/angular-8bggtq?file=app/app.component.html
Cells filled, but content not in center:
Cells not filled, but content is centered:
.wrapper {
display: grid;
height: 100vh;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr;
justify-items: center;
align-items: center;
}
.item {
//justify-self: stretch;
//align-self: stretch;
}
.one {
background: red;
}
.two {
background: pink;
}
.three {
background: violet;
}
.four {
background: yellow;
}
.five {
background: brown;
}
.six {
background: green;
}
html,
body {
margin: 0;
}
<div class="wrapper">
<div class="item one">1</div>
<div class="item two">2</div>
<div class="item three">3</div>
<div class="item four">4</div>
<div class="item five">5</div>
<div class="item six">6</div>
</div>

The HTML structure of a grid container has three levels:
the container
the items (the children of the container)
the content (the grandchildren of the container and children of the items)
The problem you're having is that you're taking a two-level approach instead of the correct three-level approach. When you set align-items and justify-items on the container, they apply to the grid items, not to the content.
That's exactly what you are seeing: The grid items are being vertically and horizontally centered.
If you want to center the grid item children (the content), you need to specify that on the items. You can repeat on the items what you did on the container:
.item {
display: grid;
justify-items: center;
align-items: center;
}
Or, if you don't need grid layout in the items, here's another simple method:
.item {
display: flex;
justify-content: center;
align-items: center;
}
The above concepts apply to flex containers, as well.
For a more complete explanation and other centering methods see this post: Centering in CSS Grid
.wrapper {
display: grid;
height: 100vh;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr;
}
.item {
display: flex;
align-items: center;
justify-content: center;
}
.one { background: red; }
.two { background: pink; }
.three { background: violet; }
.four { background: yellow; }
.five { background: brown; }
.six { background: green; }
body { margin: 0; }
<div class="wrapper">
<div class="item one">1</div>
<div class="item two">2</div>
<div class="item three">3</div>
<div class="item four">4</div>
<div class="item five">5</div>
<div class="item six">6</div>
</div>

I would say the only way to do that just with CSS-grid is to insert a additional element- / grid-level.
However, I would also say that here - as #Zuber has already showed - the combination between grid and flexbox is the best way to achieve what you want.
Grid is designed to be used with flexbox, not instead of it
Ollie Williams: Things I’ve Learned About CSS Grid Layout
Pure Grid-example:
* { margin: 0; padding: 0; box-sizing: border-box; }
body { margin: 20px; }
.wrapper {
height: 100vh;
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr;
grid-gap: 20px;
}
.wrapper__item {
display: grid;
align-items: center;
justify-items: center;
background: gray;
color: white;
font-size: 2em;
}
<div class="wrapper">
<div class="wrapper__item"><span>1</span></div>
<div class="wrapper__item"><span>2</span></div>
<div class="wrapper__item"><span>3</span></div>
<div class="wrapper__item"><span>4</span></div>
<div class="wrapper__item"><span>5</span></div>
<div class="wrapper__item"><span>6</span></div>
</div>
Grid- & Flexbox-example:
* { margin: 0; padding: 0; box-sizing: border-box; }
body { margin: 20px; }
.wrapper {
height: 100vh;
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr;
grid-gap: 20px;
}
.wrapper__item {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
background: gray;
color: white;
font-size: 2em;
}
<div class="wrapper">
<div class="wrapper__item">1</div>
<div class="wrapper__item">2</div>
<div class="wrapper__item">3</div>
<div class="wrapper__item">4</div>
<div class="wrapper__item">5</div>
<div class="wrapper__item">6</div>
</div>

you need to add some css in the class "item"
.item {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}

Try with justify-self: center or text align:center if it is only text.

Related

why does child divs take 100% height of parent div with display: grid

I have a paren div which is has display grid and height 100%. for some reason all the children divs inside it now have height 100% even though i didnt specify the height to have 100%. How can i make the child divs have the height based on their content.
.parent {
height: 100%;
width: 100%;
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr;
gap: 0;
}
.child {
width: 100%;
display: flex;
background: red;
}
<div class="parent">
<div class="child">
<div class="child-1">
child
</div>
</div>
</div>
Cause
The reason is that the default value for the CSS property align-items on a grid-container is normal. This property defines the align-self behaviour (vertical alignment) of those grid cells which don't explicitly set align-self.
See MDN:
normal
The effect of this keyword is dependent of the layout mode we are in:
In absolutely-positioned layouts, the keyword behaves like start on replaced absolutely-positioned boxes, and as stretch on all other absolutely-positioned boxes.
In static position of absolutely-positioned layouts, the keyword behaves as stretch.
For flex items, the keyword behaves as stretch.
For grid items, this keyword leads to a behavior similar to the one of stretch, except for boxes with an aspect ratio or an intrinsic sizes where it behaves like start.
The property doesn't apply to block-level boxes, and to table cells.
html, body { height: 100%; margin: 0; color: white; }
.parent {
background-color: orange;
height: 100%;
width: 100%;
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr;
gap: 10px;
}
.child {
background-color: red;
width: 100%;
}
<div class="parent">
<div class="child">
child 1
</div>
<div class="child">
child 2
</div>
</div>
Solution
If you want all your grid-cells to start at the top of the cell and have height: auto, simply apply align-items: start; on your grid container:
html, body { height: 100%; margin: 0; color: white; }
.parent {
background-color: orange;
height: 100%;
width: 100%;
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr;
gap: 10px;
align-items: start;
}
.child {
background-color: red;
width: 100%;
}
<div class="parent">
<div class="child">
child 1
</div>
<div class="child">
child 2
</div>
</div>
If you want only some of your grid-cells to start at the top of the cell and have height: auto, simply apply align-self: start; on those grid cells:
html, body { height: 100%; margin: 0; color: white; }
.parent {
background-color: orange;
height: 100%;
width: 100%;
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr;
gap: 10px;
}
.child {
background-color: red;
width: 100%;
}
.auto-height {
align-self: start;
}
<div class="parent">
<div class="child auto-height">
child 1
</div>
<div class="child">
child 2
</div>
</div>

How to make an element of a Grid take all remaining space?

I am building a grid layout based on 3 rows and I would like the middle row to take as much space as possible.
The first row should be at the start of the screen (blue bar in the code example) and the third row should be at the end of the screen(red bar in the code example)
How can I achieve this? :S
https://jsfiddle.net/xmghkLvs/31/
.grid {
display: grid;
grid-template-columns: 1fr;
grid-template-rows: auto auto auto;
row-gap: 1%;
}
.top-bar{
background-color: blue;
border-radius: 5px;
}
.main-menu{
justify-self: center;
display: flex;
flex-direction: column;
background-color: green;
}
.bottom-bar{
background-color: red;
border-radius: 5px;
}
<div class="grid">
<div class="top-bar">
<h1>
Title
</h1>
</div>
<div class="main-menu">
<button>
One Button
</button>
<button>
Other Button
</button>
</div>
<div class="bottom-bar">
<p>
I'm a text
</p>
</div>
</div>
1st: Give the grid a min-height like 100vh (.grid { min-height: 100vh; }). This will make consume at least the viewports height.
2nd: Give the the first and last row a height of min-content. That will make it only consume as much height as needed. auto will then consume all remaining space by default.
.grid {
min-height: 100vh;
display: grid;
grid-template-columns: 1fr;
grid-template-rows: min-content auto min-content;
row-gap: 1%;
}
.top-bar{
background-color: blue;
border-radius: 5px;
}
.main-menu{
justify-self: center;
display: flex;
flex-direction: column;
background-color: green;
}
.bottom-bar{
background-color: red;
border-radius: 5px;
}
<div class="grid">
<div class="top-bar">
<h1>
Title
</h1>
</div>
<div class="main-menu">
<button>
One Button
</button>
<button>
Other Button
</button>
</div>
<div class="bottom-bar">
<p>
I'm a text
</p>
</div>
</div>
Try using 100vh
.grid {
display: grid;
grid-template-columns: 1fr;
grid-template-rows: auto auto auto;
row-gap: 1%;
height: 100vh;
}
and add specific height for the .top-bar abd .bottom-bar
You could approach this using Flexbox and 100vh as show below.
.grid {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
}
.top-bar{
display: flex;
height: 20%;
}
.main-menu{
display: flex;
align-items: center;
justify-content: center;
height: 60%;
}
.main-menu button {
height: 60px;
width: 120px;
}
.bottom-bar{
display: flex;
align-items: center;
justify-content: center;
height: 20%;
}

Keep Grid Items The Height Of The Content and Thus Prevent Them Matching Their Parent Height - CSS

I have a grid where one of the two grid items (columns) has its own grid. This inner grid is also two columns and is going to hold blog posts.
I would like it so the articles inside this inner grid don't stretch the full height of the parent container, but effectively stack from the top down and their height is restricted to that of their content (i.e. the text + the given padding). Is this possible to do?
In the example code it would mean the yellow <article> elements being stack up at the top of the column and separated by the grid gap still.
Code snippet is below or CodePen is here: https://codepen.io/emilychews/pen/WNwNayG
* {
box-sizing: border-box;
position: relative;
}
body {
margin: 0;
width: 100%;
height: 100vh;
background: red;
display: flex;
justify-content: center;
align-items: center;
}
.main {
background: #fff;
width: 50%;
height: 90%;
}
.inner-wrapper {
display: grid;
grid-gap: 2rem;
grid-template-columns: repeat(2, 1fr);
width: 100%;
height: 100%;
padding: 2rem;
}
.column {
background: lightgray;
}
.column-1 {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-gap: 1rem;
}
/* GRID ITEMS THAT I WANT TO RESTRICT THEIR HEIGHT TO THAT OF THEIR CONTENT */
.article {
padding: 1rem;
background: yellow;
margin: 0 0 0.5rem 0;
}
<main class="main">
<div class="inner-wrapper">
<div class="column column-1">
<article class="article">Lorem Ipsum</article>
<article class="article">Lorem Ipsum</article>
<article class="article">Lorem Ipsum</article>
<article class="article">Lorem Ipsum</article>
</div>
<aside class="column column-2"></aside>
</div>
</main>
Add align-content: start;
.column-1 {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-gap: 1rem;
align-content: start;
}

CSS: Need help how to get my two items in my container to be placed correctly

I have a problem with how i am supposed to center my text in the middle of the box and get my number (01, 02 etc) in the top left corner?
I am using flexbox to first center all my contents and then align-self my heading to flex start. All fine and dandy but as you can see my heading is not in the top right corner. How would i make sure the heading is in the top left corner and my text is in the center of the box and not slightly off center?
I have tried to set margin right on auto to push the heading to the left, it works but my text is then pushed all the way to the right.
How would I go ahead of fixing this?
footer {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr;
}
.box {
min-height: 354.48px;
max-height: 354.48px;
display: flex;
align-items: center;
justify-content: center;
padding: 1rem;
}
.box h2 {
font-size: 2rem;
}
.how-it-works {
background-color: #c7ddea;
}
.O1 {
background-color: white;
}
.O1 h2 {
align-self: flex-start;
}
.O2 {
background-color: #e7e7e7;
}
.O2 h2 {
align-self: flex-start;
}
.O3 {
background-color: #fff;
}
.O3 h2 {
align-self: flex-start;
}
.O4 {
background-color: #f17949;
}
.O4 h2 {
align-self: flex-start;
}
.O5 {
background-color: #fff;
}
.O5 h2 {
align-self: flex-start;
}
<footer>
<div class="box how-it-works">
<h1>How it works?</h1>
</div>
<div class="box O1">
<h2>01</h2>
<p>Answer a few questions about yourself</p>
</div>
<div class="box O2">
<h2>02</h2>
<p>Choose a plan. Get a quote.</p>
</div>
<div class="box O3">
<h2>03</h2>
<p>Answe some questions about your medical history</p>
</div>
<div class="box O4">
<h2>04</h2>
<p>Wait 90 sec to get approved.</p>
</div>
<div class="box O5">
<h2>05</h2>
<p>Done!</p>
</div>
</footer>
You could do something like this:
footer {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr;
}
.box {
position: relative;
min-height: 354.48px;
max-height: 354.48px;
display: flex;
flex-direction: column;
justify-content: center;
padding: 1rem;
}
.box h2 {
font-size: 2rem;
line-height: 0;
position: absolute;
top: 1rem;
left: 1rem;
}
.box p {
text-align: center;
}
.how-it-works {
background-color: #c7ddea;
}
.O1 {
background-color: white;
}
.O2 {
background-color: #e7e7e7;
}
.O3 {
background-color: #fff;
}
.O4 {
background-color: #f17949;
}
.O5 {
background-color: #fff;
}
<footer>
<div class="box how-it-works"><h1>How it works?</h1></div>
<div class="box O1">
<h2>01</h2>
<p>Answer a few questions about yourself</p>
</div>
<div class="box O2">
<h2>02</h2>
<p>Choose a plan. Get a quote.</p>
</div>
<div class="box O3">
<h2>03</h2>
<p>Answe some questions about your medical history</p>
</div>
<div class="box O4">
<h2>04</h2>
<p>Wait 90 sec to get approved.</p>
</div>
<div class="box O5">
<h2>05</h2>
<p>Done!</p>
</div>
</footer>
If I understood well what you need, one solution could be adding this to .box class:
.box{
flex-direction: column;
}

horizontal scroll for css grid-layout

I need to have different layouts for a dashboard. I need only horizontal scroll for layout-container if the items exceed to fit in a visible viewport. I came across a layout with the following requirements.
I have created the layout style using CSS-flexbox, but could not get the horizontal scroll, got the vertical scroll only.
html,
body {
height: 100%;
margin: 0px;
}
* {
box-sizing: border-box;
}
.flexbox {
height: 100%;
width: 100%;
display: flex;
flex-wrap: wrap;
overflow-x: auto;
background-color: lightgreen;
}
.item {
min-width: 50%;
min-height: 50%;
flex: 1 0 0;
border: 1px solid;
}
.item:nth-child(odd) {
background-color: lightblue;
}
.item:nth-child(even) {
background-color: lightslategray;
}
.item1 {
min-width: 100%;
}
<div class="flexbox">
<div class="item item1">1</div>
<div class="item item2">2</div>
<div class="item item3">3</div>
<div class="item item1">4</div>
<div class="item item2">5</div>
<div class="item item3">6</div>
</div>
https://codepen.io/TechnoGeek/pen/GdZodo
So, I thought, CSS grid can help with this. So I tried something but did not understand how to get it.
html,
body {
height: 100%;
margin: 0px;
}
.grid {
display: grid;
height: 100%;
background-color: lightgreen;
grid-template-columns: repeat(2, 1fr);
grid-template-row: repeat(2, 1fr);
grid-gap: 5px;
/* grid-auto-flow: column; */
}
.item {
border: 1px solid;
}
.item:nth-child(odd) {
background-color: lightblue;
}
.item:nth-child(even) {
background-color: lightslategray;
}
.item1 {
grid-column: 1/3;
}
<div class="grid">
<div class="item item1">1</div>
<div class="item item2">2</div>
<div class="item item3">3</div>
<div class="item item1">4</div>
<div class="item item2">5</div>
<div class="item item3">6</div>
</div>
https://codepen.io/TechnoGeek/pen/BxKoaG
In the grid layout, items are shrinking to fit within the layout.
The number of items inside the container is dynamic. Irrespective of the item count the layout must maintain the structure for each visible group.
Can someone help how to achieve this?
Thanks in advance.
I found a satisfactory answer using CSS Grid layout.
In the grid layout, items are shrinking to fit within the layout.
I have defined the grid lines using fr in my question that is why the items are shrinking. Now I have used % because I want the cell items to flow out of visible area to produce scroll if needed.
and span keyword in defining grid cell areas helped a lot for auto placement of grid cells.
From MDN: span && [ <integer> || <custom-ident> ]
Contributes a grid span to the grid item’s placement such that the corresponding edge of the grid item’s grid area is n lines from the opposite edge.
html,
body {
height: 100%;
margin: 0px;
}
.grid {
display: grid;
height: 100%;
background-color: lightgreen;
grid-template-columns: repeat(2, 50%);
grid-template-rows: repeat(2, 50%);
/*grid-gap: 5px;*/
grid-auto-columns: 50%;
grid-auto-flow: column;
}
.item {
border: 1px solid;
grid-area: span 1 / span 1;
}
.item:nth-child(odd) {
background-color: lightblue;
}
.item:nth-child(even) {
background-color: lightslategray;
}
.item1 {
grid-area: span 1/ span 2;
}
<div class="grid">
<div class="item item1">1</div>
<div class="item item2">2</div>
<div class="item item3">3</div>
<div class="item item1">4</div>
<div class="item item2">5</div>
<div class="item item3">6</div>
</div>
For horizontal scroll the simplest solution would be to create a separate container for each view. Then make the overall container (body) a flex container in row direction.
body {
display: flex;
margin: 0;
}
.flexbox {
flex: 0 0 100vw;
height: 100vh;
display: flex;
flex-wrap: wrap;
background-color: lightgreen;
}
.item {
flex: 1 0 50%;
min-height: 50%;
border: 1px solid;
}
.item1 {
flex-basis: 100%;
}
.item:nth-child(odd) {
background-color: lightblue;
}
.item:nth-child(even) {
background-color: lightslategray;
}
* {
box-sizing: border-box;
}
<div class="flexbox">
<div class="item item1">1</div>
<div class="item item2">2</div>
<div class="item item3">3</div>
</div>
<div class="flexbox">
<div class="item item1">4</div>
<div class="item item2">5</div>
<div class="item item3">6</div>
</div>
The main trick is to add grid-auto-flow: column; to your container's display grid css styles.
For Example
.container-grid {
display: grid;
grid-gap: 1rem;
grid-template-columns: repeat(auto-fill, minmax(20rem, 20rem));
grid-auto-flow: column;
overflow-x: auto;
}
try to add class with this style to the element that you want to have horizontal scroll on it
display: block;
width: 99%;
overflow-x: auto;