How to repeat grid-template-rows for all rows - css

I'm trying create template for rows in my grid block:
grid-template-rows: repeat(3, 150px);
I know, this template should be work for first 3 rows.
However, from 4 row this template is not work.
Can i make template for all rows?
P.S.
This template work only for 1st row.
grid-template-rows: 150px;

Use grid-auto-rows (automatically generated rows) instead of grid-template-rows (manually generated rows). In current case grid-auto-rows: 150px will do the trick. Demo:
.grid {
display: grid;
grid-auto-rows: 150px;
/* space between columns for demo */
grid-gap: 10px;
}
/* just styles for demo */
.grid__item {
background-color: tomato;
color: white;
}
<div class="grid">
<div class="grid__item">One</div>
<div class="grid__item">Two</div>
<div class="grid__item">Three</div>
<div class="grid__item">Four</div>
<div class="grid__item">Five</div>
<div class="grid__item">Six</div>
<div class="grid__item">Seven</div>
<div class="grid__item">Eight</div>
<div class="grid__item">Nine</div>
</div>

Related

Grid item not expanding with inner content height

I have a menu grid layout with an inner item (in this case it's the .metadata div) that I want to expand and push down another item. See example here :
.wrapper {
display: grid;
grid-column-gap: 8px;
grid-row-gap: 4px;
grid-template-columns: 48px minmax(0px, 3fr) 1fr;
grid-template-rows: 24px 20px 44px;
grid-template-areas:
"icon title action-bar"
"icon metadata action-bar"
"tabs .... bottom-right";
padding: 16px 16px 0 16px;
}
.metadata {
grid-area: metadata;
display: flex;
align-items: baseline;
direction: ltr;
}
.innterTest {
height: 100px;
background-color: red;
}
.metadataItem {
display: flex;
}
.tabs {
grid-area: tabs;
grid-column-end: 3;
padding-top: 4px;
}
<div class="wrapper">
<div class="icon">icon
</div>
<div class="title">TITLE
</div>
<div class="action-bar">action bar
</div>
<div class="metadata">
<div class="metadataItem">
data node 1
<div class="innterTest">
testing
</div>
</div>
<div class="metadataItem">
data node 2
</div>
<div class="metadataItem">
data node 3
</div>
<div class="metadataItem">
data node 4
</div>
</div>
<div class="tabs">tabs
</div>
</div>
https://jsfiddle.net/c8wx2bgn/
If you inspect the outer .metadata wrapping div it seems to stay a small size. What I would like to happen is for it to expand and push down the .tabs grid item. The general grid layout has been working as I had hoped, but I've added more items inside metadata and want it to push tabs down when it expands.
I've tried enforcing a height on the metadata and metadata divs but this does not seem to effect the layout. New to grid so unsure what I am missing here.
You have grid-template-rows: 24px 20px 44px.
This means that the second row, which contains your metadata div, is limited in height to 20px.
Try this: grid-template-rows: 24px auto 44px.

CSS grid: Find last item of each row [duplicate]

Is it possible to select a specific grid column or row with CSS?
For example, say I have a 3 row by 2 column CSS Grid Layout: grid-template-rows: 1fr 1fr 1fr; grid-template-columns: 1fr 1fr;. How would I select all elements from the 2nd column? For example: grid:nth-child(column:2) (just my idea, not valid code).
I have tried nth-child selectors on the div elements, but this does not allow me to specify row or column when the items are automatically placed by the Grid Layout engine.
body {
display: grid;
grid-template-rows: 1fr 1fr 1fr;
grid-template-columns: 1fr 1fr;
grid-gap: 10px;
}
.item {
background: #999;
}
<div class="item">
<p>Customer Name</p>
<p>Element 1 | Element 2</p>
</div>
<div class="item">
<p>Right Justify</p>
<p>Element 1 | Element 2</p>
</div>
<div class="item">
<p>Customer Name</p>
<p>Element 1 | Element 2</p>
</div>
<div class="item">
<p>Customer Name</p>
<p>Element 1 | Element 2</p>
</div>
<div class="item">
<p>Customer Name</p>
<p>Element 1 | Element 2</p>
</div>
<div class="item">
<p>Customer Name</p>
<p>Element 1 | Element 2</p>
</div>
<div class="item">
<p>Customer Name</p>
<p>Element 1 | Element 2</p>
</div>
To style an arbitrary row, you could use a wrapper element with its display set to contents. See the code snippet below:
.grid-container {
display: grid;
grid-template-columns: repeat(5, 1fr);
grid-gap: 2px;
}
.grid-item {
border: 1px solid black;
padding: 5px;
}
.grid-row-wrapper {
display: contents;
}
.grid-row-wrapper > .grid-item {
background: skyblue;
}
<div class="grid-container">
<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 class="grid-row-wrapper">
<div class="grid-item">6</div>
<div class="grid-item">7</div>
<div class="grid-item">8</div>
<div class="grid-item">9</div>
<div class="grid-item">10</div>
</div>
<div class="grid-item">11</div>
<div class="grid-item">12</div>
<div class="grid-item">13</div>
<div class="grid-item">14</div>
<div class="grid-item">15</div>
<div class="grid-item">16</div>
<div class="grid-item">17</div>
<div class="grid-item">18</div>
<div class="grid-item">19</div>
<div class="grid-item">20</div>
</div>
EDIT: As with all implementations, you should check to ensure it works in your target environment(s). You can check the compatibility table on MDN or caniuse.com for support for display: contents:
https://developer.mozilla.org/en-US/docs/Web/CSS/display#Browser_compatibility
https://caniuse.com/#search=display%3A%20contents
There are no column or row elements that you can target but if the grid is uniform (same number of cells in each row) you can select cells. Here are some examples.
1. Columns
Last column in a 5-column grid:
.item:nth-child(5n) { /* ... */ }
Fourth (2nd last) column in a 5-column grid:
.item:nth-child(5n-1) { /* ... */ }
First (5th last) column in a 5-column grid:
.item:nth-child(5n-4) { /* ... */ }
2. Rows
First row in a 5-column grid (first five cells):
.item:nth-child(-n+5) { /* ... */ }
Second row in a 5-column grid (cells from 6 to 10):
.item:nth-child(n+6):nth-child(-n+10) { /* ... */ }
Third row in a 5-column grid (cells from 11 to 15):
.item:nth-child(n+11):nth-child(-n+15) { /* ... */ }
Last row in a 5-column grid with 20 cells (cells from 16 onward):
.item:nth-child(n+16) { /* ... */ }
Not possible with CSS.
CSS targets HTML elements, attributes and attribute values.
Grid columns and rows have none of these "hooks".
You'll have to target the grid items directly.
You wrote:
For example, say I have a 3 row by 2 column CSS Grid Layout: grid-template-rows: 1fr 1fr 1fr; grid-template-columns: 1fr 1fr;. How would I select all elements from the 2nd column?
grid-container {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr;
grid-gap: 10px;
padding: 10px;
height: 50vh;
background-color: gray;
}
grid-item {
background-color: lightgreen;
}
grid-item:nth-child(2n) {
border: 2px dashed red;
}
<grid-container>
<grid-item></grid-item>
<grid-item></grid-item>
<grid-item></grid-item>
<grid-item></grid-item>
<grid-item></grid-item>
<grid-item></grid-item>
</grid-container>
You can not. You have no such selectors.
But that is strange, because you can easily target row/colum from CSS
#item3 {
background-color: blue;
grid-row: span 2 / 7;
}
This is natural to expect something:
div[style*="display:grid"]:grid-row(3) {
background-color: blue;
}
div[style*="display:grid"]:grid-column(3) {
background-color: green;
}
Do not the reasons that draft for this is not proposed yet
UPD
Seems there are for columns: https://drafts.csswg.org/selectors-4/#the-nth-col-pseudo
UPD
Issue at W3C repo
If you ever want to style a row the same principle applies.
Taking that example from above:
grid-container {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr 1fr;
grid-gap: 10px;
padding: 10px;
height: 50vh;
background-color: gray;
}
grid-item {
background-color: lightgreen;
}
grid-item:nth-child(4n+3),grid-item:nth-child(4n) {
border: 2px dashed red;
}
<grid-container>
<grid-item></grid-item>
<grid-item></grid-item>
<grid-item></grid-item>
<grid-item></grid-item>
<grid-item></grid-item>
<grid-item></grid-item>
<grid-item></grid-item>
<grid-item></grid-item>
</grid-container>
In the near future we will be able to do it thanks to the Grid-Structural Selectors
The double-association of a cell in a 2D grid (to its row and column) cannot be represented by parentage in a hierarchical markup language. Only one of those associations can be represented hierarchically: the other must be explicitly or implicitly defined in the document language semantics. In both HTML and DocBook, two of the most common hierarchical markup languages, the markup is row-primary (that is, the row associations are represented hierarchically); the columns must be implied. To be able to represent such implied column-based relationships, the column combinator and the :nth-col() and :nth-last-col() pseudo-classes are defined. In a column-primary format, these pseudo-classes match against row associations instead.
The one you need here is :nth-col() that behave the same way as :nth-child()
The :nth-col(An+B) pseudo-class notation represents a cell element belonging to a column that has An+B-1 columns before it ref

CSS grid - responsive gallery

is there a way how to make gallery with CSS grid with following requirements?
Gallery should always fill entire container and is responsive
Gap between images is fixed
Every image has limited maximum and minimum size (e.g. 200px - 260px)
Code for gallery is following (span represents image in this example):
/* Container */
.grid {
display: grid;
grid-gap: 0.25em;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}
/* Image placeholder */
span {
display: block;
background: #eee;
border-radius: 0.25em;
width: 100%;
margin: auto;
}
/* Aspect ratio */
span:before {
content: "";
display: block;
padding-bottom: 100%;
}
<div class="grid">
<div class="item"><span></span></div>
<div class="item"><span></span></div>
<div class="item"><span></span></div>
<div class="item"><span></span></div>
<div class="item"><span></span></div>
<div class="item"><span></span></div>
<div class="item"><span></span></div>
<div class="item"><span></span></div>
<div class="item"><span></span></div>
<div class="item"><span></span></div>
<div class="item"><span></span></div>
<div class="item"><span></span></div>
<div class="item"><span></span></div>
<div class="item"><span></span></div>
</div>
When there are enough items, everything works just fine. But when gallery has only few of them, items are stretched and image becomes blurry and looks terrible. In that case, there should be behavior as with auto-fill used.
We have tried following, but none of these solutions is good enough:
Use auto-fill instead of auto-fit (images tend to be as little as possible instead of as big as possible)
Limit size of single image (gaps become uneven)
Use minmax(200px, 260px) instead of minmax(200px, 1fr) (gallery is not filling entire container)
Do anyone have any idea how to solve that? Any help would be very appreciated!
Use auto-fill instead of auto-fit
Reference: https://css-tricks.com/auto-sizing-columns-css-grid-auto-fill-vs-auto-fit/
.grid {
display: grid;
grid-gap: 0.25em;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}

Can't work out how to align logo and nav in a row using CSS grid

I'm trying to align a logo and navigation bar in one row across the top of a website using CSS grid.
I've written out the code but can't work out what I'm doing wrong as to why it's not working: https://codepen.io/chloewb/pen/wRRewQ
.logo{
grid-area: logo;
background:white;}
.navi{
grid-area: navi;
background:Yellow;}
.section1{
grid-area: features;
background:LightSalmon;}
.section2{
grid-area: technology;
background:PaleTurquoise;}
.section3{
grid-area: pricing;
background:LightPink;}
.section4{
grid-area: email;
background:PaleGreen;}
.container {
display: grid;
grid-template-rows: repeat (5, auto);
grid-template-columns: 1fr 1fr 1fr;
font-size: 40px;
width: 100%;
background: grey;
grid-template-areas:
"logo navi navi"
"features features features"
"technology technology technology"
"pricing pricing pricing"
"email email email";}
The first thing to notice is that, when you use display: grid on a container element, its direct children will become grid-items, and to these items is that the grid layout you build will apply.
So let's say we have the following:
<div class="container">
<div class="child-1">
<div class="child-2"></div>
<div class="child-2"></div>
</div>
<div class="child-1"></div>
<div class="child-1"></div>
<div class="child-1"></div>
</div>
And this CSS:
.container{
display: grid;
}
Then only the child-1 will become grid items and be able to get properties like grid-area applied to them; everything else inside .child-1, like .child-2 will behave normally, as if there's no Grid. Unless you also specify the .child-1 element to be a grid with display: grid.
In your case, you header element is a direct child of the .container element, so it is a grid item and can be positioned on any place on the grid, but the logo and navi elements are children of header, so the grid layout does not apply to them. You would either have to take them out of the header so the rules you wrote take effect, or create another grid in the header and let it use the full first row. See this example and notice how the nesting of the elements affect them.
.container {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: minmax(50px, auto);
grid-template-areas: "logo navi navi";
margin-bottom: 20px;
border: 1px solid black;
}
.logo {
border: 1px solid red;
grid-area: logo;
}
.navi {
border: 1px solid blue;
grid-area: navi;
}
<div class="container">
<div class="logo">Logo</div>
<div class="navi">Nav</div>
</div>
<div class="container">
<header>
<div class="logo">Logo</div>
<div class="navi">Nav</div>
</header>
</div>

Make a grid column span the entire row

Imagine we have 2 CSS Grid containers with dynamic columns count based on width.
display: grid;
grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
The grid works perfectly, but what if we need to have another grid to have the 1st column to be same as in another grid with the code shown above, but it's another column to span through more cells - depending on how many cells are in the current row.
To better understand issue, there are images:
On more narrow wrapper:
We would need to apply something like grid-column: span ALL (if something like that exists), with meaning that ALL = till the end of current row.
What is really important is that "First" column should always align with "1" column.
Code to run example is here:
.grid div {
/* Not important fancy styles */
height: 40px;
text-align: center;
padding-top: 20px;
}
.grid {
width: 350px;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
background-color: silver;
}
.grid-second {
background-color: red;
}
.grid-another {
background-color: purple;
border: 1px solid gray;
}
<div class="grid">
<div class="grid-first">
First
</div>
<div class="grid-second">
Second (Want till end)
</div>
</div>
<!-- Another same grid -->
<div class="grid">
<div class="grid-another">
1
</div>
<div class="grid-another">
2
</div>
<div class="grid-another">
3
</div>
<div class="grid-another">
4
</div>
</div>
PS. please do not post solutions using media query. I am interested in any (even little hacky solution), which will work without usage of media queries.
Here are two interesting sections in the CSS Grid specification:
7.1. The Explicit Grid
Numeric indexes in the grid-placement properties count from the edges
of the explicit grid. Positive indexes count from the start side,
while negative indexes count from the end side.
also here...
8.3. Line-based Placement: the grid-row-start, grid-column-start, grid-row-end, and grid-column-end properties
If a negative integer is given, it instead counts in reverse, starting
from the end edge of the explicit grid.
In other words, when dealing with an explicit grid, which means a grid defined by these properties:
grid-template-rows
grid-template-columns
grid-template-areas
grid (which is the shorthand for the three properties above, among others)
... you can make a grid area span all columns by setting this rule:
grid-column: 1 / -1;
That tells the grid area to span from the first column line to the last column line, which I believe meets your stated objective:
"We would need to apply something like grid-column: span ALL (if something like that exists), with meaning that ALL = till the end of current row."
jsFiddle demo
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
background-color: silver;
}
.grid-second {
grid-column: 2 / -1;
background-color: red;
}
/* Not important fancy styles */
.grid div {
height: 40px;
text-align: center;
padding-top: 20px;
}
.grid-another {
background-color: purple;
border: 1px solid gray;
}
<div class="grid">
<div class="grid-first">First</div>
<div class="grid-second">Second (Want till end)</div>
</div>
<!-- Another same grid -->
<div class="grid">
<div class="grid-another">1</div>
<div class="grid-another">2</div>
<div class="grid-another">3</div>
<div class="grid-another">4</div>
<div class="grid-another">1</div>
<div class="grid-another">2</div>
<div class="grid-another">3</div>
<div class="grid-another">4</div>
<div class="grid-another">1</div>
<div class="grid-another">2</div>
<div class="grid-another">3</div>
<div class="grid-another">4</div>
</div>

Resources