started using CSS grid instead of boostrap, and im having some issue to get it right.
i want to create a grid layout that have 4fr, and 8fr columns (just like boostrap 8 and 4 columns)
and when the divs inside the grid of 4r gets fill its the divs go to a second row just like flex-wrap:wrap.
BUT Its not work its only push it inline one after another, and ignoring the grid boundaries
.home {
display: grid;
grid-template-columns: 4fr 8fr;
grid-template-rows: 100%;
height: 100%;
}
<div class="home">
<div class="col-8">
</div>
<div class="col-4">
<mat-button-toggle-group class="side-menu-button">
<mat-button-toggle>test </mat-button-toggle>
<mat-button-toggle>test</mat-button-toggle>
<mat-button-toggle>test</mat-button-toggle>
<mat-button-toggle>test</mat-button-toggle>
<mat-button-toggle>test</mat-button-toggle>
<mat-button-toggle>test</mat-button-toggle>
<mat-button-toggle>test</mat-button-toggle>
<mat-button-toggle>test</mat-button-toggle>
</mat-button-toggle-group>
</div>
</div>
i even tried changing it to
grid-template-columns: repeat(1, auto-fill, 4fr 8fr);
If you're just wanting to use the grid to have items wrap inside of a div, what you're doing should basically work. Don't forget to tell .col-8 and .col-4 where they belong inside of the grid you've set up, and set the children you want to wrap to inline-block:
* {
box-sizing: border-box;
}
.home {
display: grid;
grid-template-columns: repeat(12, 1fr);
grid-template-rows: 100%;
height: 100%;
width: 100%;
grid-gap: 20px;
}
.col-8 {
grid-area: 1/1/1/9;
}
.col-4 {
grid-area: 1/9/1/13;
}
.bluebox,
.blackbox {
display: inline-block;
width: 50px;
height: 20px;
}
.bluebox {
background-color: blue;
}
.blackbox {
background-color: black;
}
<div class="home">
<div class="col-8">
<div class="bluebox"></div>
<div class="bluebox"></div>
<div class="bluebox"></div>
<div class="bluebox"></div>
<div class="bluebox"></div>
<div class="bluebox"></div>
<div class="bluebox"></div>
<div class="bluebox"></div>
<div class="bluebox"></div>
<div class="bluebox"></div>
</div>
<div class="col-4">
<div class="blackbox"></div>
<div class="blackbox"></div>
<div class="blackbox"></div>
<div class="blackbox"></div>
<div class="blackbox"></div>
<div class="blackbox"></div>
<div class="blackbox"></div>
<div class="blackbox"></div>
<div class="blackbox"></div>
<div class="blackbox"></div>
</div>
</div>
The reason I set up 12 columns instead of one that's 8fr and one that's 4fr is because I'm unclear about whether you're wanting a 12 column usable system like bootstrap (which is the way I implemented it), or literally only two columns. Either way should function for what you are describing in your question, but 12 separate columns is arguably more extensible later-on.
Here's a pen that contains the above code:
https://codepen.io/grantnoe/pen/MdOQOv
grid-area is what I used to set the location of .home's children. The format is as follows:
grid-area: <row-start> / <column-start> / <row-end> / <column-end>;
The only caveat is that you've nested the children you're wanting to wrap inside of secondary element <mat-button-toggle-group>. Consider adjusting the width of that element to 100% to fill the grid's child .col-4.
Related
I would like to have a CSS grid that renders the items column by column, where the max number of columns and rows is not assumed. I have below the best version that I was able to come up with, although with some workarounds that I am hoping to not be required:
.grid {
display: grid;
grid-auto-flow: column;
grid-template-rows: repeat(4, 1fr);
}
.item {
margin: 1em;
}
.column {
display: contents;
}
.clear {
grid-row-end: -1;
}
<div class="grid">
<div class="column">
<div class="item">A1</div>
<div class="item">A2</div>
<div class="clear"></div>
</div>
<div class="column">
<div class="item">B1</div>
<div class="item">B2</div>
<div class="item">B3</div>
<div class="clear"></div>
</div>
<div class="column">
<div class="item">C1</div>
<div class="clear"></div>
</div>
</div>
As you can see:
The CSS hard codes the number of rows using grid-template-rows. Removing this will cause items to appear in incorrect columns if there are more items than the hard-coded number of rows, while making the hard-coded number extremely large (e.g., 1000) will work for all practical number of items in a column, but cause a large amount of blank space to be added to the bottom of the document.
There is a "clear" div that I'd rather not need in each column to force the auto-placement to the next column.
Note that just having each column lay itself out (using something like flexbox or CSS Columns) will not work, as it is important that the grid items (which may have varying heights) remain aligned with their horizontal neighbors.
You can easily get rid of the clear element by setting the row of the first element of each column then you can consider the trick of a big number of rows but with auto sizing and not 1fr. You won't have any blank space if you don't use row gaps:
.grid {
display: grid;
grid-auto-flow: column;
grid-template-rows: repeat(1000, auto);
}
.item {
margin: 1em;
}
.column {
display: contents;
}
.column .item:first-child {
grid-row: 1;
}
<div class="grid">
<div class="column">
<div class="item">A1</div>
<div class="item">A2</div>
</div>
<div class="column">
<div class="item">B1</div>
<div class="item">B2</div>
<div class="item">B3</div>
</div>
<div class="column">
<div class="item">C1</div>
</div>
</div>
I tried to achieve the masonry style using css with the column layout like the markup below.
I want to know if it's possible to make the .green one to take two columns instead of one?
Thank you in advance!
.parent{
column-gap: 1rem;
column-count: 2;
}
.element{
display:inline-block;
background:red;
width:100%;
height:100px;
}
.green{
background:green;
}
<div class="parent">
<div class="element green">
</div>
<div class="element">
</div>
<div class="element">
</div>
<div class="element">
</div>
</div>
With CSS grid you can use grid-column: span 2:
.wrapper {
display: grid;
grid-gap: 0.5rem;
grid-template-columns: 1fr 1fr 1fr;
grid-auto-flow: dense;
padding: 0.5rem;
}
.box {
background-color: lightblue;
padding: 0.5rem;
}
.a,
.d,
.e,
.f {
background-color: lightcoral;
grid-column: span 2; /* <-- here is the trick */
}
<div class="wrapper">
<div class="box a">A</div>
<div class="box b">B</div>
<div class="box c">C</div>
<div class="box d">D</div>
<div class="box e">E</div>
<div class="box f">F</div>
<div class="box g">G</div>
<div class="box h">H</div>
</div>
Learn more about it here: https://developer.mozilla.org/en-US/docs/Web/CSS/grid-column
Regarding masonry style: At the time of writing, Level 3 of the CSS Grid Layout specification includes a masonry value for grid-template-columns and grid-template-rows layout, though browser support is pretty non-existent: https://caniuse.com/?search=masonry
Learn about it here: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/Masonry_Layout
So instead I used grid-auto-flow: dense; on the grid, which makes grid item G come before grid item F. It's not really masonry style (placing elements in optimal position based on available vertical space), but it comes close by making the grid dense filling up all available horizontal space with the next grid item that fits that space.
"dense" packing algorithm attempts to fill in holes earlier in the grid
Learn about it here: https://developer.mozilla.org/en-US/docs/Web/CSS/grid-auto-flow
Oh, if you are new to CSS grid, I recommend watching Wes Bos' talk “CSS Grid in 45 Minutes!”: https://www.youtube.com/watch?v=DCZdCKjnBCs
CSS Grid layout provides a simple, easy and efficient solution.
.parent {
display: grid;
grid-template-columns: 1fr 1fr;
grid-auto-rows: 100px;
grid-gap: 1rem;
}
.element.green {
grid-column: 1 / -1;
background: green;
}
.element {
background: red;
}
<div class="parent">
<div class="element green"></div>
<div class="element"></div>
<div class="element"></div>
<div class="element"></div>
</div>
More information:
Make a grid column span the entire row
CSS-only masonry layout
I would say, no you can't make the single .green element take up two columns, becuase you are specifically telling the browser to use two columns. If you need it to span the two columns, then I would suggest using a separate element. Perhaps a more suitable solution for this would be to use the CSS grid layout. The snippet below contains an example of both of these solutions:
.parent {
column-gap: 1rem;
column-count: 2;
}
.element {
display: inline-block;
background: red;
width: 100%;
height: 100px;
}
.green {
background: green;
width: 100%;
height: 100px;
margin-bottom: 1rem;
}
.grid-container {
margin-top: 20px;
display: grid;
grid-template-columns: auto auto;
grid-gap: 1rem;
}
.greenGrid {
background: green;
height: 100px;
grid-column-start: 1;
grid-column-end: 3;
}
.redGrid {
background: red;
height: 100px;
}
<div class="green">
</div>
<div class="parent">
<div class="element">
</div>
<div class="element">
</div>
<div class="element">
</div>
</div>
<div class='grid-container'>
<div class='greenGrid'></div>
<div class='redGrid'></div>
<div class='redGrid'></div>
<div class='redGrid'></div>
</div>
I understand that fr is calculated based on available space in the grid container. I have a situation where I have a grid container that I want to split into 5 columns. The children however, are dynamically generated and depending on the situation, it could be 3 children or 4 or 5. I still want to keep the 5-column grid intact with the specified grid-column-gap, but I want the grid to start populating the elements from the right. Please see my code below: https://codepen.io/skepticacid/pen/dyGxaJb
<html>
<body>
<div class = "grid-container">
<div class = "grid-child">1</div>
<div class = "grid-child">2</div>
<div class = "grid-child">3</div>
<div class = "grid-child">4</div>
<div class = "grid-child">5</div>
</div>
<div class = "grid-container">
<div class = "grid-child">1</div>
<div class = "grid-child">2</div>
<div class = "grid-child">3</div>
<div class = "grid-child">4</div>
</div>
<div class = "grid-container">
<div class = "grid-child">1</div>
<div class = "grid-child">2</div>
<div class = "grid-child">3</div>
</div>
</body>
</html>
html{
font-size: 16px;
}
.grid-container {
background-color: coral;
display: grid;
grid-template-columns: repeat(5, 1fr);
grid-column-gap: 1rem;
justify-content: end;
align-items: center;
padding: 1rem;
margin-bottom: 2rem;
}
.grid-child{
background-color: saddlebrown;
color: white;
padding: 1rem;
}
5 elements is the happy path. However, when it comes down to 4 or 3 elements, I want them to be aligned similar to a justify-content: end or flex-end (so in the 4-column example, I want div number 4 to align with div number 5 above). Also, I also want to retain the width of the column to match the ones in the 5-column width.
Is this possible through CSS grid? Apologies, if I'm missing something glaringly obvious.
There is no such property to reverse the flow in CSS-Grid.
One solution (which does not scale nicely) is to use nth-last-child in this situation to designate which column is required.
html{
font-size: 16px;
}
.grid-container {
background-color: coral;
display: grid;
grid-template-columns: repeat(5, 1fr);
grid-gap: .25rem;
padding: 1rem;
}
.grid-child{
background-color: saddlebrown;
color: white;
padding: 1rem;
}
.grid-child:nth-last-child(1) {
grid-column:5;
}
.grid-child:nth-last-child(2) {
grid-column:4;
}
.grid-child:nth-last-child(3) {
grid-column:3;
}
.grid-child:nth-last-child(4) {
grid-column:2;
}
.grid-child:nth-last-child(5) {
grid-column:1;
}
<html>
<body>
<div class="grid-container">
<div class="grid-child">1</div>
<div class="grid-child">2</div>
<div class="grid-child">3</div>
<div class="grid-child">4</div>
<div class="grid-child">5</div>
</div>
<div class="grid-container">
<div class="grid-child">1</div>
<div class="grid-child">2</div>
<div class="grid-child">3</div>
<div class="grid-child">4</div>
</div>
<div class="grid-container">
<div class="grid-child">1</div>
<div class="grid-child">2</div>
<div class="grid-child">3</div>
</div>
</body>
</html>
If that you want it this way
direction: rtl;
if issue with direction hope it solve it.
last answer:
justify-items: center;
Doesn't matter.
We can make use of auto-fit Which only creates columns when needed unlike auto-fill and the current setup which creates columns even when not needed.
This will work if we know the maximum number of columns we're going to have we'll go with 5.
Our grid-template-columns becomes like this:
grid-template-columns: repeat(auto-fit, minmax(0px,calc((100% - ( .25rem * 4)) / 5)));
Instead of the predefined 5 columns we calculate 5 columns from the width of the parent, Subtracting the grid-gap
And finally we apply justify-content: flex-end;
.grid-container {
background-color: coral;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(0,calc((100% - ( .25rem * 4)) / 5)));
grid-gap: .25rem;
padding: 1rem;
justify-content: flex-end;
}
.grid-child {
background-color: saddlebrown;
color: white;
padding: 1rem;
}
<div class="grid-container">
<div class="grid-child">1</div>
<div class="grid-child">2</div>
<div class="grid-child">3</div>
<div class="grid-child">4</div>
<div class="grid-child">5</div>
</div>
<div class="grid-container">
<div class="grid-child">1</div>
<div class="grid-child">2</div>
<div class="grid-child">3</div>
<div class="grid-child">4</div>
</div>
<div class="grid-container">
<div class="grid-child">1</div>
<div class="grid-child">2</div>
<div class="grid-child">3</div>
</div>
I'm programming a web application with collapsible sidebar inside a CSS grid. The CSS grid divides the whole UI into sections, and the sidebar panel is a sub-component of one of those sections.
The issue I am running into is that I want the side panel to automatically shrink to the minimum size of it's contents, which it does fine until it's added to a CSS grid cell, at which point it expands to fill the entire cell.
Here is a quick example of the issue:
<style>
#myGrid{
display: grid;
grid-template-areas:
"g1 g2";
}
#panel{
grid-area: g2;
display: inline-block;
background: #FFAAAA;
height: 100%;
width: auto;
min-width: minmax(0, 1fr);
}
#panelContents{
display: flex;
flex-direction: row;
height: 100%;
}
#collapseArrow{
align-self: center;
right: 0;
top: 50%;
}
#block{
grid-area: g1;
width: 200px;
height: 100%;
background: #AAAAFF;
}
</style>
<body>
<div id="myGrid">
<div id="block">
Contents
</div>
<div id="panel">
<div id="panelContents">
<div id="collapseContents">
<div class="item">
Item1
</div>
<div class="item">
Item2
</div>
<div class="item">
Item3
</div>
<div class="item">
Item4
</div>
<div class="item">
Item5
</div>
</div>
<div id="collapseArrow"><</div>
</div>
</div>
</div>
</body>
Any idea how to solve this? I am trying to get the red panel to shrink to fit it's contents. I tried changing the min-width to 0, but that didn't seem to help.
EDIT: This is a more complex UI for an HTML5 game engine. The left grid cell is an asset browser, and the red panel is a simple properties panel for the right editor window (right grid cell), which I'm trying to display only on the left portion of the cell, so the rest of the right cell can be the editor window.
Use the other column to squeeze the panel down to its content width.
#myGrid {
display: grid;
grid-template-columns: 1fr auto; /* 1fr consumes all free space on the row */
grid-template-areas: "g1 g2";
}
#block {
grid-area: g1;
background: #AAAAFF;
}
#panel {
grid-area: g2;
background: #FFAAAA;
}
#panelContents {
display: flex;
}
#collapseArrow {
align-self: center;
}
<div id="myGrid">
<div id="block">
Contents
</div>
<div id="panel">
<div id="panelContents">
<div id="collapseContents">
<div class="item">Item1</div>
<div class="item">Item2</div>
<div class="item">Item3</div>
<div class="item">Item4</div>
<div class="item">Item5</div>
</div>
<div id="collapseArrow"><</div>
</div>
</div>
</div>
Using the following css:
.container {
display : grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr;
grid-template-areas:
'first second'
'first second'
;
}
.first {
grid-area: first;
width: 200px;
height: 200px;
background-color: red;
}
.second {
grid-area: second;
width: 200px;
height: 200px;
background-color: #0eb5d6;
These boxes will stack (appearing as one red, 1 blue):
<div class="container">
<div class="first"></div>
<div class="second"></div>
<div class="first"></div>
<div class="second"></div>
</div>
However, these will not stack, and correctly appear as 2 rows with the same css:
<div class="container">
<div class="first"></div>
<div class="second"></div>
</div>
<div class='container'>
<div class="first"></div>
<div class="second"></div>
</div>
In my actual use case I'm trying to align a form using css grid. I would like to not need divs for rows if possible. Or is this the only way to avoid stacking of elements into one row?
Note that here grid-template-areas form a rectangle and so first and second spans their columns. And multiple declaration will only overlap:
A row is created for every separate string listed, and a column is
created for each cell in the string. Multiple named cell tokens within
and between rows create a single named grid area that spans the
corresponding grid cells. Unless those cells form a rectangle, the
declaration is invalid.
MDN
You can remove grid-template-areas here - it works fine without it. See demo below:
.container {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr;
}
.first {
width: 200px;
height: 200px;
background-color: red;
}
.second {
width: 200px;
height: 200px;
background-color: #0eb5d6;
}
<div class="container">
<div class="first"></div>
<div class="second"></div>
<div class="first"></div>
<div class="second"></div>
</div>