I'm trying to use display: grid to make a layout with a variable amount of columns, with horizontal and vertical overflow and the first column being a specific width.
Each of the columns, besides the first, should be the same width.
For example,
grid-template-columns: 49px repeat(auto-fill, 300px);
makes the first column the correct width, and columns after 300px - until reaching the overflowing columns, which ignore the 300px.
The vertical scroll is achieved with overflow-y and a specified height.
overflow-y: scroll;
height: 70vh;
And the horizontal css so far is:
grid-template-columns: 49px repeat(auto-fit, 300px);
grid-auto-flow: column;
overflow-x: scroll;
width: 100%;
Stack snippet:
.grid-container {
display: grid;
grid-template-columns: 49px repeat(auto-fit, 300px);
grid-auto-flow: column;
overflow-x: scroll;
width: 100%;
overflow-y: scroll;
height: 70vh;
}
<div class="grid-container">
<div class="first-item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
<div class="item">7</div>
<div class="item">8</div>
</div>
Paint attempt to visualise the goal:
You could solve this by omitting grid-template-columns and defining the width separately:
.grid-container {
display: grid;
grid-auto-flow: column;
overflow-x: scroll;
width: 100%;
overflow-y: scroll;
height: 70vh;
}
.first-item {
width: 49px;
}
.item {
width: 300px;
}
<div class="grid-container">
<div class="first-item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
<div class="item">7</div>
<div class="item">8</div>
</div>
Use grid-auto-columns and you don't need to specify any CSS on the child items
.grid-container {
display: grid;
grid-template-columns: 49px; /* 1st column */
grid-auto-columns: 300px; /* all the others */
grid-auto-flow: column;
overflow-x: scroll;
height: 70vh;
}
<div class="grid-container">
<div class="first-item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
<div class="item">7</div>
<div class="item">8</div>
</div>
Related
I'm sure this kind of question was asked before, but I really can't describe it exactly and concisely enough to let the search engine to understand me. So here we go:
To better explain my question I'm writing the code in tailwind style here. A stack snippet is also attached below:
<div class="root w-screen h-screen flex flex-col">
<div class="header h-[72px] w-full bg-red shrink-0"></div>
<div class="content grow">
<!-- a whole lot of content, very tall, height > 2000 px -->
</div>
</div>
In this example, I would like to limit the height of the entire div.root to 100vh. However, because div.content is very tall, it expands the body that it shows a vertical scrollbar.
Well this is fairly easy to overcome, I only need to add scroll-y-auto to div.content. So the body scrollbar disappears, and div.content shows a vertical scrollbar. Perfect.
However later on, I decided to split div.content into two columns: both column shall have its own vertical scrollbar. Intuitively I changed the code to:
<div class="root w-screen h-screen flex flex-col">
<div class="header h-[72px] w-full bg-red shrink-0"></div>
<div class="content grow">
<div class="left overflow-y-auto">
<!-- a whole lot of content, very tall, height > 2000 px -->
</div>
<div class="right overflow-y-auto">
<!-- a whole lot of content, very tall, height > 2000 px -->
</div>
</div>
</div>
But this does not work at all, as the attached snippet demonstrates. body got its scrollbar back, but not div.left or div.right.
I've explored several ways to solve this problem. In the end the best solution I got was to set the height of div.content to calc(100% - 72px). This works perfectly, but I understand it's only because I know the exact height of div.header is fixed at 72px.
Was I doing something wrong here? What's the most elegant way to solve this kind of problem?
body {
margin: 0;
}
.root {
width: 100vw;
height: 100vh;
display: flex;
flex-direction: column;
}
.header {
height: 72px;
width: 100%;
background-color: red;
flex-shrink: 0;
}
.content {
flex-grow: 1;
display: flex;
flex-direction: row;
}
.very-tall-content {
background-color: green;
height: 2400px
}
.left, .right {
flex-grow: 1;
margin: 0 4px;
overflow-y: auto;
}
<div class="root">
<div class="header"></div>
<div class="content">
<div class="left">
<p class="very-tall-content"></p>
</div>
<div class="right">
<p class="very-tall-content"></p>
</div>
</div>
</div>
Allright, try this one maybe it fixed your problem :)
instead of using flex for .root use grid. down here we have a
header with minimum height of 72px and if it's content overloads, the
header will auto-fit them
:root {
--header-min-height: 72px;
}
body {
margin: 0;
}
.root {
display: grid;
grid-template-rows: minmax(var(--header-min-height), auto) 1fr;
height: 100vh;
}
.header {
grid-row: 1;
background: darkcyan;
}
.content {
grid-row: 2;
display: flex;
background-color: palegreen;
overflow-y: hidden;
}
.content>div {
flex-grow: 1;
overflow-y: auto;
}
.white-space {
height: 3000px;
}
<div class="root">
<div class="header"></div>
<div class="content">
<div class="left">
Left Side
<div class="white-space"></div>
Left Side
</div>
<div class="right">
Right Side
<div class="white-space"></div>
Right Side
</div>
</div>
</div>
here's the example if it overloads.
:root {
--header-min-height: 72px;
}
body {
margin: 0;
}
.root {
display: grid;
grid-template-rows: minmax(var(--header-min-height), auto) 1fr;
height: 100vh;
}
.header {
grid-row: 1;
background: darkcyan;
}
.content {
grid-row: 2;
display: flex;
background-color: palegreen;
overflow-y: hidden;
}
.content>div {
flex-grow: 1;
overflow-y: auto;
}
.white-space {
height: 3000px;
}
.row {
display: flex;
flex-direction: row;
width: fit-content;
}
.item {
background: rgba(255, 255, 255, .5);
width: fit-content;
padding: 10px;
margin: 5px;
border-radius: 5px;
}
<div class="root">
<div class="header">
<div class="row">
<div class="item">test</div>
<div class="item">test</div>
<div class="item">test</div>
</div>
<div class="row">
<div class="item">test</div>
<div class="item">test</div>
<div class="item">test</div>
</div>
<div class="row">
<div class="item">test</div>
<div class="item">test</div>
<div class="item">test</div>
</div>
</div>
<div class="content">
<div class="left">
Left Side
<div class="white-space"></div>
Left Side
</div>
<div class="right">
Right Side
<div class="white-space"></div>
Right Side
</div>
</div>
</div>
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;
I want to make a grid in footer where the text is above the grid but also staying in the grid. Position: absolute don't work because it effects both grid and text, and i want to move them independently of each other.
How it looks:
https://i.imgur.com/norbzp1.png
How i want it to be:
https://i.imgur.com/1fYoQIF.png
Code:
<div class="footer">Footer
<div class="icon"></div>
<div class="icon"></div>
<div class="icon"></div>
<div class="icon"></div>
<div class="icon"></div>
<div class="icon"></div>
</div>
And css:
.footer{
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-auto-rows: 50px;
grid-gap: 10px;
}
.icon{
display: flex;
background: rgb(160, 84, 84);
}
You can achieve this by wrapping the grid and the footer with a container.
.footer-header {
text-align: center;
padding:20px;
}
.footer-grid {
grid-column: span 3 / auto;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-auto-rows: 50px;
grid-gap: 10px;
}
.icon{
display: flex;
background: rgb(160, 84, 84);
}
<div class="footer">
<div class="footer-header">
Footer
</div>
<div class="footer-grid">
<div class="icon">1</div>
<div class="icon">2</div>
<div class="icon">3</div>
<div class="icon">4</div>
<div class="icon">5</div>
<div class="icon">6</div>
</div>
</div>
Also you can use grid-template-areas, for example
.footer{
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-areas: "footer-head footer-head footer-head";
grid-auto-rows: 50px;
grid-gap: 10px;
}
.icon{
display: flex;
background: rgb(160, 84, 84);
}
.footer-head {
text-align: center;
grid-area: footer-head;
}
<div class="footer">
<div class="footer-head">Footer</div>
<div id="icon1" class="icon"></div>
<div class="icon"></div>
<div class="icon"></div>
<div class="icon"></div>
<div class="icon"></div>
<div class="icon"></div>
</div>
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>
I have numerous div elements that I would like to be scrolled horitonzaly rather than vertically, based on 100% parent height.
I have done a quick move up of the desired result.
As an example if the parent is 600 pixels tall, six 100px items will fit before it makes a new column and a 900px height would fit 9 items.
How can I achieve this affect? I only need it to work in Chrome is cross-browser support is not available for this.
Code for you to fiddle with, http://jsfiddle.net/yQ5AR/
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
<div class="item">7</div>
<div class="item">8</div>
<div class="item">9</div>
<div class="item">10</div>
<div class="item">11</div>
<div class="item">12</div>
<div class="item">13</div>
<div class="item">14</div>
<div class="item">15</div>
<div class="item">16</div>
<div class="item">17</div>
<div class="item">18</div>
<div class="item">19</div>
<div class="item">20</div>
</div>
.container{
max-height: 400px;
width: 100%;
overflow: scroll;
}
.item{
height: 100px;
}
Use flexbox for this
FIDDLE
CSS
.container{
max-height: 600px;
width: 100%;
display: flex;
flex-direction: column;
flex-wrap: wrap;
}
.item{
height: 70px;
background: silver;
width: 200px;
margin: 10px;
padding: 5px;
}
CSS columns and column-break-inside should do what you're looking for (-webkit in this case since you only care about Chrome).
http://jsfiddle.net/yQ5AR/4/
CSS
.container{
max-height: 400px;
width: 100%;
overflow: scroll;
-webkit-columns: 100px;
}
.item{
height: 100px;
-webkit-column-break-inside: avoid;
}