Responsive centering of divs - css

How do I go from here
To here
I'm trying to center the inner div's to their parent except for the last row where I'd like to align it left to the row above it.
Here is the jsfiddle for the top image https://jsfiddle.net/L15p2nev
.container {
text-align: center;
background-color: green;
}
.item {
display: inline-block;
width: 300px;
background-color: red;
}
<div class="container">
<div class="item">
item
</div>
<div class="item">
item
</div>
<div class="item">
item
</div>
</div>

Using grid display layout, this can be archived.
You can set grid-template-columns: repeat(auto-fit, 300px) to align items as the image.
.container {
background-color: green;
display: grid;
grid-template-columns: repeat(auto-fit, 300px);
justify-content: center;
grid-column-gap: 10px;
grid-row-gap: 10px;
}
.item {
display: inline-block;
background-color: red;
}
<div class="container">
<div class="item">
item
</div>
<div class="item">
item
</div>
<div class="item">
item
</div>
</div>

Related

Image pushing divs below

I have a 2 column layout with an image to the left and wanted to have 3 divs on the right but can only manage to get 1 div to align next to the image and the other 3 divs are below the image. How can I have all 3 divs next to the image?
I know this is easy with grid-areas but wanted to do it with out.
.wrapper {
background-color: pink;
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-template-rows: auto auto 1fr;
}
.hero {
background-color: red;
}
.foo {
background-color: orange;
}
.bar {
background-color: lime;
}
.baz {
background-color: aqua;
}
img {
width: 100%;
display: block;
}
<div class="wrapper">
<div class="hero">
<img src="https://via.placeholder.com/1080x1080" alt="">
</div>
<div class="foo">
foo
</div>
<div class="bar">
bar
</div>
<div class="baz">
baz
</div>
</div>
https://codepen.io/emmabbb/pen/oNqPwad
Set a specific grid row value on your hero: grid-row: 1 / 4;
Like this:
.wrapper {
background-color: pink;
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-template-rows: auto auto 1fr;
}
.hero {
background-color: red;
grid-row: 1 / 4;
}
.foo {
background-color: orange;
}
.bar {
background-color: lime;
}
.baz {
background-color: aqua;
}
img {
width: 100%;
display: block;
}
<div class="wrapper">
<div class="hero">
<img src="https://via.placeholder.com/1080x1080" alt="">
</div>
<div class="foo">
foo
</div>
<div class="bar">
bar
</div>
<div class="baz">
baz
</div>
</div>
If you want your divs with text in them to be of equal height change the grid template rows to grid-template-rows: 1fr 1fr 1fr; Like this:
.wrapper {
background-color: pink;
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-template-rows: 1fr 1fr 1fr;
}
.hero {
background-color: red;
grid-row: 1 / 4;
}
.foo {
background-color: orange;
}
.bar {
background-color: lime;
}
.baz {
background-color: aqua;
}
img {
width: 100%;
display: block;
}
<div class="wrapper">
<div class="hero">
<img src="https://via.placeholder.com/1080x1080" alt="">
</div>
<div class="foo">
foo
</div>
<div class="bar">
bar
</div>
<div class="baz">
baz
</div>
</div>
I believe the easiest way to get the 3 divs on the right of the image without using grid area would be to wrap foo, bar, and baz in a parent div and use 1 row on your grid; you may have to mess with the hight of the divs on the right though.
<div class="wrapper">
<div class="hero">
<img src="https://via.placeholder.com/1080x1080" alt="">
</div>
<div>
<div class="foo">
foo
</div>
<div class="bar">
bar
</div>
<div class="baz">
baz
</div>
</div>
</div>
I hope that does what your looking for!

css grid fit rows heights

I want to remove the worthless margin between rows, so I want every div takes the content height without giving margin to his side div, I tried everything but nothing works.
.grids {
width: 90%;
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: minmax(min-content, max-content);
margin: auto;
grid-gap: 32px;
}
.grid {
position: relative;
width: 95%;
height: max-content;
margin: 10px;
padding: 20px;
background: black;
border-radius: 10px;
}
<div class="grids">
<div class="grid"></div>
<div class="grid"></div>
<div class="grid"></div>
<div class="grid"></div>
<div class="grid"></div>
<div class="grid"></div>
</div>
Edit: To make a masonry layout I have wrapped grid items in div tag
so you can nest as many tags as you want.
grid items overflow the content because of the width and height properties.
you're using a grid gap for both rows and columns.
So I guess this might help you out.
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
grid-template-rows: masonry;
grid-gap: 10px;
}
.grid-item {
padding: 20px;
background: red;
border-radius: 10px;
margin-bottom: 24px;
}
<div class="grid">
<div>
<div class="grid-item">
<h1>Hello world</h1>
</div>
<div class="grid-item">
<h1>Hello world</h1>
</div>
</div>
<div>
<div class="grid-item"></div>
<div class="grid-item"></div>
<div class="grid-item"></div>
</div>
<div>
<div class="grid-item">
<h1>Hello
<br>
friend
</h1>
</div>
<div class="grid-item"></div>
</div>
</div>
Also, I renamed the classes for naming purposes only.
MDN docs grid-row: row-gap
MDN docs masonry layout: masonry layout
You can try to set grid-gap: 32px to grid-gap: 0 32px, it will remove the margin between grid rows;

How to vertically center align the bottom of a horizontal list of items of varying heights

I'm trying to achieve the following layout without using absolute positioning
The reason is that I would like to use css grid or flexbox as much as possible and try to avoid taking thins out of the flow if at all possible. In this case the surrounding div has a padding which should be respected, if it comes to that, and instead it should increase it's height if necessary. Usually I use max-content with css grid to achieve this.
If it was only the text it would have been as easy as align-items: center; however, because of the images/badges, the text will not properly align in the center if I do this.
https://stackblitz.com/edit/react-ts-t4h6ff?file=style.css
.list {
width : 100%;
background : red;
display : flex;
flex-direction : row;
align-items : center;
}
.list-item {
background : yellow;
display : grid;
grid-template-rows : max-content max-content;
padding : 1rem;
}
<div class="list">
<div class="list-item">list item 1</div>
<div class="list-item">
<div>image</div>
<div>list item 2</div>
</div>
<div class="list-item">
<div>image</div>
<div>list item 3</div>
</div>
</div>
Basically https://stackblitz.com/edit/react-ts-4xy14d?file=style.css is what I want to achieve, but without position absolute or transform translate.
Ended up with: https://stackblitz.com/edit/react-ts-78pckz?file=style.css
html,
body,
#root,
.wrapper {
height: 100%;
width: 100%;
}
.wrapper {
display: grid;
grid-template-rows: minmax(5rem, 50%) auto;
background: purple;
}
.list {
width: 100%;
background: red;
display: flex;
flex-direction: row;
height: 100%;
}
.list-item {
background: yellow;
display: grid;
grid-template-rows: 1fr max-content 1fr;
padding: 1rem;
box-sizing: border-box;
height: 100%;
overflow: hidden;
}
.image-wrapper {
position: relative;
}
.image {
max-width: 100%;
max-height: 100%;
position: absolute;
bottom: 0;
right: 0;
}
.text {
align-self: center;
white-space: nowrap;
}
<div class="wrapper">
<div class="list">
<div class="list-item">
<div> </div>
<div class="text">list item 1</div>
<div> </div>
</div>
<div class="list-item">
<div class="image-wrapper">
<img class="image" src="https://via.placeholder.com/100" />
</div>
<div class="text">list item 2</div>
<div> </div>
</div>
<div class="list-item">
<div class="image-wrapper">
<img class="image" src="https://via.placeholder.com/150" />
</div>
<div class="text">list item 3</div>
<div> </div>
</div>
</div>
<div>... :-)</div>
</div>
I don't think it's the most elegant solution, but here's how I would solve the problem (assuming your diagram is saying that the size of the images are going to be consistent).
Edit: Didn't quite get there with my answers, but it did help Dac0d3r come up with this final solution. Source from him is in the comments.
html,
body,
#root,
.wrapper {
height : 100%;
width : 100%;
}
.wrapper {
display : grid;
grid-template-rows : minmax(5rem, 50%) auto;
background : purple;
}
.list {
width : 100%;
background : red;
display : flex;
flex-direction : row;
height : 100%;
}
.list-item {
background : yellow;
display : grid;
grid-template-rows : 50% 50%;
padding : 1rem;
box-sizing : border-box;
height : 100%;
}
.image {
max-width : 100%;
max-height : 100%;
align-self : end;
}
<div class="wrapper">
<div class="list">
<div class="list-item">
<div></div>
<div class="text">list item 1</div>
</div>
<div class="list-item">
<img class="image" src="https://via.placeholder.com/100" />
<div class="text">list item 2</div>
</div>
<div class="list-item">
<img class="image" src="https://via.placeholder.com/150" />
<div class="text">list item 3</div>
</div>
</div>
</div>

Overflow-X not working in muli-column CSS grid layout

I have a simple grid layout with 2 columns. Inside of the grid cells overflow-x seems to not be working. Is there any way to make this layout with working overflow-x inside of the cells?
.main-grid {
display: grid;
grid-template-columns: minmax(min-content, 1fr) auto;
gap: 20px;
}
.main-grid>div {
display: flex;
flex-direction: column;
gap: 20px;
}
.main-grid>div>div {
background-color: lightpink;
}
.scroll-me {
overflow-x: auto;
}
.i-am-too-wide {
width: 800px;
}
.margin-top {
margin-top: 50px;
}
<div class="main-grid">
<div>
<div>
1
</div>
<div>
2
</div>
</div>
<div>
<div>
A
</div>
<div>
B
<div class="scroll-me">
<div class="i-am-too-wide">
Wide element inside grid
</div>
</div>
</div>
</div>
</div>
<div class="scroll-me margin-top">
<div class="i-am-too-wide">
WIDE element outside grid
</div>
</div>

Shrink grid items just like flex items in css

Is it possible to shrink grid items just like flex items in css?
Grid items
.container {
display: grid;
grid-gap: 10px;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}
.child {
display: flex;
flex-flow: row wrap;
align-items: center;
justify-content: center;
padding: 5px;
border: 3px solid #a07;
}
<div class="container">
<div class="child">
text
</div>
<div class="child">
text
</div>
<div class="child">
text
</div>
<div class="child">
text
</div>
<div class="child">
text
</div>
</div>
jsfiddle
Flex items
.container {
display: flex;
margin-left: -10px;
flex-flow: row wrap;
}
.child {
display: flex;
flex-flow: row wrap;
align-items: center;
justify-content: center;
padding: 5px;
border: 3px solid #a07;
flex: 200px 1 1;
margin-left: 10px;
margin-bottom: 10px;
}
<div class="container">
<div class="child">
text
</div>
<div class="child">
text
</div>
<div class="child">
text
</div>
<div class="child">
text
</div>
<div class="child">
text
</div>
</div>
jsfiddle
In a nutshell I can have the following positioning of the elements with the flex above:
While I can not achieve the same behaviour by using a grid layout. Flex layout allows items to shrink on small screen, while grid layout does not allow. At the same time I would like to preserve the behavior that the item will move to the next line with another item only when after such a placement each one of them will be no shorter than a specific size (200px in our case).
I am using grid layout because it allows to preserve the invariant that widths of all the children will be the same. With flex layout the last item will be stretched to the whole line if it will be alone on the line.
New solution
An optimized version of the initial solution using min()
.container {
display: grid;
grid-gap: 10px;
grid-template-columns: repeat(auto-fill, minmax(min(200px,100%), 1fr));
}
.child {
display: flex;
align-items: center;
justify-content: center;
padding: 5px;
border: 3px solid #a07;
}
body {
margin:0;
}
<div class="container">
<div class="child">
text
</div>
<div class="child">
text
</div>
<div class="child">
text
</div>
<div class="child">
text
</div>
<div class="child">
text
</div>
</div>
Old solution
One solution is to specify a max-width to the child element relying on the viewport unit since percentage values are relative to the size of the track defined by the minmax() and cannot be used. This solution isn't generic and you need to adjust the value depending on each situation.
In you case for example, we can use 100vw since the container is the only element in the body and is taking the whole width:
.container {
display: grid;
grid-gap: 10px;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}
.child {
display: flex;
align-items: center;
justify-content: center;
padding: 5px;
border: 3px solid #a07;
max-width:100vw;
box-sizing:border-box; /* Don't forget this !*/
}
body {
margin:0;
}
<div class="container">
<div class="child">
text
</div>
<div class="child">
text
</div>
<div class="child">
text
</div>
<div class="child">
text
</div>
<div class="child">
text
</div>
</div>
In case there is more element or some padding/margin you need to consider them within the max-width calculation:
.container {
display: grid;
grid-gap: 10px;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}
.child {
display: flex;
align-items: center;
justify-content: center;
padding: 5px;
border: 3px solid #a07;
max-width:calc(100vw - 40px); /*we remove the body margin*/
box-sizing:border-box;
}
body {
margin:0 20px;
}
<div class="container">
<div class="child">
text
</div>
<div class="child">
text
</div>
<div class="child">
text
</div>
<div class="child">
text
</div>
<div class="child">
text
</div>
</div>
It's like we no more have 2 constraints but 3:
The grid cell has a minimum size of 200px
The grid cell fill the remain space
The element inside the grid cell has a maximum size defined relatively to the screen size. (the shrink constraint we were missing)

Resources