Trying to implement slider with grid items, using grid layout and grid-auto-flow: column;
Issue that I am having is that grid with column option, does not see my container with, as I would predict it should see, thus last item is show partially.
My goal is to allways show full items in grid container, and overflow: hide other items.
Is it possible using grid?
https://codepen.io/evelina-rim/pen/gOaLQEq
.container {
border: 10px solid red;
background-color: grey;
width: 700px;
display: grid;
grid-gap: 20px;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
grid-auto-flow: column;
grid-auto-columns: minmax(300px, 1fr);
grid-column-end: 1
}
.item {
background-color: coral;
border: 3px solid blue;
}
<div class="container">
<div class="item">Vienas</div>
<div class="item">Du</div>
<div class="item">Trys</div>
<div class="item">Keturi</div>
<div class="item">Penki</div>
</div>
Use percentage value to control this and you can decide how many item you want to show and this will define the width of your items:
.container {
border: 10px solid red;
background-color: grey;
width: 700px;
display: grid;
grid-gap: 20px;
grid-auto-flow: column;
grid-auto-columns: calc((100% - 2*20px)/3); /* don't forget to consider the gap */
}
.item {
background-color: coral;
border: 3px solid blue;
}
<div class="container">
<div class="item">Vienas</div>
<div class="item">Du</div>
<div class="item">Trys</div>
<div class="item">Keturi</div>
<div class="item">Penki</div>
</div>
It can be easier using CSS variables
.container {
--n:2;
border: 10px solid red;
background-color: grey;
width: 700px;
display: grid;
grid-gap: 20px;
grid-auto-flow: column;
grid-auto-columns: calc((100% - (var(--n) - 1)*20px)/var(--n)); /* don't forget to consider the gap */
}
.item {
background-color: coral;
border: 3px solid blue;
}
<div class="container">
<div class="item">Vienas</div>
<div class="item">Du</div>
<div class="item">Trys</div>
<div class="item">Keturi</div>
<div class="item">Penki</div>
</div>
<div class="container" style="--n:4">
<div class="item">Vienas</div>
<div class="item">Du</div>
<div class="item">Trys</div>
<div class="item">Keturi</div>
<div class="item">Penki</div>
</div>
Related
I'm trying to use the grid layout for two columns in one row which can be easily achieved by flex. I have to create one more div for flex but the grid doesn't need one more div.
The problem with the grid is that it will divide the width space by 2 (cannot align to start/left) and that's not what I want, please refer to the first example below and you will understand.
Is there any way to use the grid in this situation but we can align the items to the left like in the second example?
#main-1 {
display: grid;
gap: 30px;
grid-teplate-column: repeat(2, minmax(0, 1fr));
}
.test-1 {
background-color: orange;
grid-area: span 1 / span 2;
}
.test-2 {
background-color: gray;
width: 150px;
}
#main-2 {
display: flex;
gap: 30px;
margin-top: 30px;
}
.test-3 {
background-color: orange;
width: 100%;
}
.test-4 {
background-color: gray;
width: 150px;
}
.test-1,
.test-2,
.test-3,
.test-4 {
height: 60px;
}
<h1>Grid</h1>
<div id="main-1">
<div class="test-1"></div>
<div class="test-2"></div>
<div class="test-2"></div>
</div>
<h1 style="margin:30px 0 0 0;padding-top:15px;border-top: 3px solid #000;">Flex</h1>
<p style="margin:0 0 30px 0;">This is the desired layout but with one more extra div</p>
<div>
<div class="test-3"></div>
<div id="main-2">
<div class="test-4"></div>
<div class="test-4"></div>
</div>
</div>
Edited
Inline-block might work but we cannot control how many items should be on each row. Imagine the width of the first div .first is dynamic and we do not know how wide it would be(but I will make it 30px for illustration). Now the desired layout should be only one .first and one .second on each row.
By inline-block it would appear that now each row is one .first, one .second, and one .first. Check out the example below. Because we cannot control the amount like grid on each row.
#main {
width: 120px;
}
.first,
.second {
display: inline-block;
height: 60px;
}
.first {
background-color: orange;
width: 30px;
}
<div id="main">
<div class="first"></div>
<p class="second">hhhhhh</p>
<div class="first"></div>
<p class="second">hhhhhh</p>
<div class="first"></div>
<p class="second">hhhhhh</p>
</div>
Define the columns as auto and keep only one at 1fr then you can align to the left.
#main-1 {
display: grid;
gap: 30px;
/* update "5" based on your needs */
grid-template-columns: repeat(5,auto) 1fr;
justify-content: left; /* align to left */
}
.test-1 {
background-color: orange;
grid-column: 1/-1; /* take all the columns */
}
.test-2 {
background-color: gray;
width: 150px;
}
#main-2 {
display: flex;
gap: 30px;
margin-top: 30px;
}
.test-3 {
background-color: orange;
width: 100%;
}
.test-4 {
background-color: gray;
width: 150px;
}
.test-1,
.test-2,
.test-3,
.test-4 {
height: 60px;
}
<h1>Grid</h1>
<div id="main-1">
<div class="test-1"></div>
<div class="test-2"></div>
<div class="test-2"></div>
</div>
<h1 style="margin:30px 0 0 0;padding-top:15px;border-top: 3px solid #000;">Flex</h1>
<p style="margin:0 0 30px 0;">This is the desired layout but with one more extra div</p>
<div>
<div class="test-3"></div>
<div id="main-2">
<div class="test-4"></div>
<div class="test-4"></div>
</div>
</div>
I have a multiple column CSS Grid defined with repeat(6, 1fr) but with only one or two columns defined. It seems justifying center or space-between does not work in this case, probably because the grid already knows it has 6 equal width columns so there is nothing to justify?
.grid {
display: grid;
grid-template-columns: repeat(6, 1fr);
grid-template-rows: 3em;
grid-gap: 1rem;
/*justify-items: center; horizontally centers column content */
/*align-items: center; vertically centers column content */
}
.grid > div {
background-color: yellow;
}
.grid > div:first-child {
background-color: orange;
}
<div class="grid">
<div>content1</div>
<div>content2</div>
</div>
If you will have only one row you can do the following otherwise use flexbox:
.grid {
display: grid;
grid-auto-columns: calc((100% - 5rem)/6);
grid-auto-flow: column;
grid-template-rows: 3em;
grid-gap: 1rem;
justify-content: center;
border: 1px solid;
}
.grid>div {
background-color: yellow;
}
.grid>div:first-child {
background-color: orange;
}
<div class="grid">
<div>content1</div>
<div>content2</div>
</div>
<div class="grid">
<div>content1</div>
<div>content2</div>
<div>content3</div>
</div>
<div class="grid" style="justify-content: space-between;">
<div>content1</div>
<div>content2</div>
</div>
<div class="grid" style="justify-content: space-between;">
<div>content1</div>
<div>content2</div>
<div>content3</div>
</div>
I want to set for fist element '1fr' and any other elements should have fixed size
I'm tried this and it works.
grid-template-columns: 500px repeat(auto-fill, 50px);
This, what I'm trying to do.
.container {
display: grid;
grid-template-columns: 1fr repeat(auto-fill, 50px);
> div {
border: 1px solid red;
}
}
A first element should have a 1fr (any available space)
enter image description here
I think flexbox would be more appropriate here.
.container {
display: flex;
height: 98vh;
margin: 1vh 1vw;
}
.item {
border: 1px solid red;
flex: 0 0 50px;
margin: .5em;
}
.wide {
flex: 1
}
<div class="container">
<div class="item wide">Auto Remaining Width</div>
<div class="item">50px</div>
<div class="item">50px</div>
<div class="item">50px</div>
</div>
This question already has answers here:
Targeting flex items on the last or specific row
(10 answers)
Closed 4 years ago.
I have a simple grid here using css flex.
I need the 3 columns that are a percentage of the parent container width.
I also need a right margin on each block.
I nearly have it working here but I need the blocks in the second line to go from left to right, here the second block on the second row is on the right.
.block {
border: 1px solid lightgrey;
display: flex;
flex-wrap: wrap;
padding: 5px;
max-width: 900px;
justify-content: space-between;
//justify-content: flex-start;
}
.block__item {
//align-self: flex-start;
background: grey;
height: 20px;
//margin-right: 8px;
margin-bottom: 2px;
width: calc(33.3% - 2px);
}
<div class="block">
<div class="block__item"></div>
<div class="block__item"></div>
<div class="block__item"></div>
<div class="block__item"></div>
<div class="block__item"></div>
</div>
You were on the right track originally with using justify-content: flex-start. It was justify-content: space-between that was giving you the gap on the second row, so I removed that and everything lined up. I adjusted the margins and padding too to match the spacing.
.block {
border: 1px solid lightgrey;
display: flex;
flex-wrap: wrap;
padding: 5px 3px 5px 5px;
max-width: 900px;
justify-content: flex-start;
}
.block__item {
background: grey;
height: 20px;
margin-bottom: 2px;
width: calc(33.3% - 2px);
margin-right:2px;
}
<div class="block">
<div class="block__item"></div>
<div class="block__item"></div>
<div class="block__item"></div>
<div class="block__item"></div>
<div class="block__item"></div>
</div>
Another way to think about it is to use a wrapping element (.block__item) that provides the spacing between elements with internal padding. These wrapping elements are physically next to each other but provide the visual distinction between their contents (.block__content).
The benefit of this is that you don't need to include the spacing in your calculations for width or flex-basis. If you want to change the spacing, simply update padding.
*Note that you need to change the box-model of your elements to border-box to take advantage of this.
* {
box-sizing: border-box;
}
.block {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
max-width: 900px;
border: 1px solid lightgrey;
padding: 2px;
}
.block__item {
flex: 0 1 calc(100% / 3);
padding: 2px;
}
.block__content {
height: 20px;
background-color: grey;
color: white;
font-size: 10px;
font-weight: 700;
line-height: 20px;
text-align: center;
}
#media (max-width: 400px) {
.block__item {
flex-basis: 50%;
}
}
<div class="block">
<div class="block__item">
<div class="block__content">1</div>
</div>
<div class="block__item">
<div class="block__content">2</div>
</div>
<div class="block__item">
<div class="block__content">3</div>
</div>
<div class="block__item">
<div class="block__content">4</div>
</div>
<div class="block__item">
<div class="block__content">5</div>
</div>
</div>
You could reduce the margins a bit so they fit better and keep aligning flex items to the left with justify-content: flex-start; or you could also use CSS Grid instead and define the gap you need as well as the total columns you need (3 in this case), with grid you can even avoid percentage calculations and just tell each item to use a fraction of the available space.
The biggest benefit of CSS Grid I think would be that you avoid wasting space that might be left out with percentages, and also you don't need to change anything else on the items if you want to add or remove columns.
.block {
border: 1px solid lightgrey;
display: flex;
flex-wrap: wrap;
padding: 5px;
max-width: 900px;
justify-content: flex-start;
}
.block__item {
background: grey;
height: 20px;
margin-right: 2px;
margin-bottom: 2px;
width: calc(33.3% - 2px);
}
.block-grid{
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: minmax(20px, auto);
grid-gap: 2px;
border: 1px solid grey;
padding: 5px;
}
.block-grid__item{
background-color: red;
}
<div class="block">
<div class="block__item"></div>
<div class="block__item"></div>
<div class="block__item"></div>
<div class="block__item"></div>
<div class="block__item"></div>
</div>
<div class="block-grid">
<div class="block-grid__item"></div>
<div class="block-grid__item"></div>
<div class="block-grid__item"></div>
<div class="block-grid__item"></div>
<div class="block-grid__item"></div>
</div>
What I have is a two-column layout with several items inside:
.grid {
column-count: 2;
}
.grid-item {
break-inside: avoid;
height: 50px;
margin-bottom: 10px;
background-color: green;
text-align: center;
line-height: 50px;
color: white;
}
<div class="grid">
<div class="grid-item">1</div>
<div class="grid-item">2</div>
<div class="grid-item">3</div>
<div class="grid-item">4</div>
<div class="grid-item">5</div>
</div>
https://codepen.io/Deka87/pen/RgdLeZ
Now I need an ability to reorder those items inside the columns with CSS only (so they were in a different order on different screen resolutions), so I thought I can do this with:
.grid {
display: flex;
flex-direction: column;
column-count: 2;
}
.grid-item:nth-child(1) {
order: 5;
}
Obviously, this didn't work and broke the 2-column layout. Anybody tried to solve this before? Any chance I can get this working?
PS: Items on the same line should not be of the same height (I could have used simple floats in this case). Sorry for not specifying in the beginning.
Without a fixed height on the container, a column of flex items won't know where to wrap. There's nothing to cause a break, so items will continue expanding the single column.
Also, column-count and display: flex represent two different CSS technologies. column-count is not a valid property in a flex container.
CSS Grid Layout may be useful to you:
re-size the screen width to trigger the media query
revised codepen
.grid {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: repeat(3, auto);
grid-auto-rows: 50px;
grid-auto-flow: column;
grid-gap: 10px;
}
.grid-item {
background-color: green;
text-align: center;
line-height: 50px;
color: white;
}
#media ( max-width: 500px) {
.grid-item:nth-child(2) {
order: 1;
background-color: orange;
}
}
<div class="grid">
<div class="grid-item">1</div>
<div class="grid-item">2</div>
<div class="grid-item">3</div>
<div class="grid-item">4</div>
<div class="grid-item">5</div>
</div>
I tend to use flexbox for this
.grid {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: flex-start;
}
.grid-item {
box-sizing: border-box;
width: calc( 50% - 5px );
min-height: 50px;
margin-bottom: 10px;
background-color: green;
text-align: center;
line-height: 50px;
color: white;
}
.grid-item:nth-child(1) {
order: 5;
}
<div class="grid">
<div class="grid-item">1</div>
<div class="grid-item">2</div>
<div class="grid-item">3</div>
<div class="grid-item">4</div>
<div class="grid-item">5</div>
</div>
The flex syntax is widely supported and super flexible.