I'm trying to make a grid that has a full span row at the bottom.
For full span columns I can use grid-column: 1/-1.
For single span columns I can use grid-column: 1/1.
For single span rows I can use grid-row: 1/1.
But if I want to define the last column or row, I have to write grid-column: -2/-1.
Why is the syntax not the same as with 1/1 for the first column/row? Or am I making a mistake somewhere?
I also made a jsfiddle to demonstrate my problem: jsfiddle
.grid-container {
display: grid;
grid-template-columns: 5px 1fr 1fr;
grid-template-rows: minmax(50px, 2fr) 1fr 1fr 1fr 1fr 1fr 15px;
}
.grid-item {
width: 1fr;
}
.header {
display: flex;
grid-column: 2/-1;
grid-row: 1/1;
justify-content: center;
}
.border-left {
background: purple;
grid-column: 1/1;
grid-row: 1/-1;
}
.border-bottom {
background: #410266;
grid-column: 2/-1;
/* grid-row: -2 / -1; this will work, -1/-1 will not */
grid-row: -1 / -1;
}
<div class="grid-container">
<div class="header"> HEADER </div>
<div class="border-left"></div>
<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="border-bottom"></div>
</div>
The grid-column and grid-row shorthand properties count grid lines.
You wrote:
For single span columns I can use grid-column: 1/1
This doesn't make any sense. It resolves to:
grid-column-start: 1
grid-column-end: 1
So you're defining a column that goes from the starting line to the starting line.
A column has a starting line and an ending line. So to span the first column you use:
grid-column: 1 / 2
The only reason your code works as you expect is because the Grid error handling algorithm removes the end line when the start and end lines are equal.
So 1 / 1 resolves to 1 / auto, where auto represents a default span of 1.
You wrote:
But if I want to define the last column or row, I have to write grid-column: -2/-1
Yes, that's one way to do it. (You can also use positive integers, since you know the number of columns.)
You wrote:
Why is the syntax not the same as with 1/1 for the first column/row? Or am I making a mistake somewhere?
1 / 1
As mentioned above, 1/1 was invalid. It is fixed by the Grid system, resolving to 1 / auto. As a result, you span the first column.
-1 / -1
This combination of values is also invalid. It means span from the last line of the grid to the last line of the grid. Grid error handling changes the end value to -1 / auto. This takes you out of the explicit grid (because an implicit column is created) and negative values no longer apply. The negative values end where the implicit grid begins (demo).
-2 / -1
Correct syntax. So it works. Span one column starting from the penultimate line of the grid.
when using the same value inside grid-column/grid-row you will fall into this rule:
If the placement for a grid item contains two lines, and the start line is further end-ward than the end line, swap the two lines. If the start line is equal to the end line, remove the end line.ref
So saying grid-column:-1/-1 means grid-column:-1 which is grid-column:-1/auto
auto
The property contributes nothing to the grid item’s placement, indicating auto-placement or a default span of one. (See § 8 Placing Grid Items, above.)
So basiclly you said to your element to start at the last line and span one column which will create an implicit new column:
A basic example to illustrate:
.box {
display:grid;
grid-template-columns:20px 20px 20px;
grid-auto-columns:100px;
grid-gap:5px;
}
span {
grid-column:-1/-1;
height:40px;
background:red;
}
<div class="box">
<span></span>
</div>
You can see that the span is having 100px which means it create a new column inside the implicit grid and is not inside the explicit one defined by 20px
When using -2/-1 it's clear that you will consider the before the last and the last line and the element will be placed in the last explicit column:
.box {
display:grid;
grid-template-columns:20px 20px 20px;
grid-auto-columns:100px;
grid-gap:5px;
}
span {
grid-column:-2/-1;
height:40px;
background:red;
}
<div class="box">
<span></span>
</div>
Same logic apply when using positive value but you won't notice a strange behavior since you will most likely span an explicit column thinking it's correct to specify, for example, grid-column:1/1
Related
I want to build a grid that could, for example, look like this:
Each item is manually given its grid-row, for example the item D has grid-row: 6
If a row contains only one item, that item should span across the entire row, like the item A
If a row contains multiple items, or in other words the items "overlap", they should share the row's space equally, like items B and C or D, E and F
The grid-column property should NOT be given to items manually, for example I do not want to manually give the item F grid-column: 5 / 7. This is because items will be inserted into the grid one after the other, and when an item is inserted or removed the other items should adjust accordingly.
My current approach (that doesn't work) is this:
.grid {
height: 300px;
width: 300px;
display: grid;
border: 1px solid red;
}
.item {
border: 1px solid teal;
}
.item-a {
grid-row: 1;
}
.item-b {
grid-row: 2 / 4;
}
.item-c {
grid-row: 3;
}
<div class="grid">
<div class="item item-a">a</div>
<div class="item item-b">b</div>
<div class="item item-c">c</div>
</div>
As you can see, the item a does not span across the entire row. Giving every item grid-column: span 2 just adds new columns and doesn't change the layout.
How can I achieve the desired grid?
I'm trying to use CSS grid for a layout and having trouble figuring out how to do so. Here's a sketch of the layout:
(empty) | (empty) | label | (empty)
---------------------------------------------
col1 | col2 | col3 | col4
The bit I'm having trouble with, is that I want to repeat the second row as many times as necessary.
Ideally, I'd also like to be able to just throw the child elements in the grid container and have them flow into the correct spots without having to specify grid-area on them.
That is, ideally I can produce this layout with this markup:
<div class="grid-container">
<div>label</div>
<div>col1</div>
<div>col2</div>
<div>col3</div>
<div>col4</div>
</div>
I've been looking at grid documentation for an hour or so and can't seem to wrap my head around how to do this. Any tips?
Using grid-area: 1 / 3 / 2 / 4; for our .label div. Had to add a class to it. 1 / 3 / 2 / 4 means grid-row-start / grid-column-start / grid-row-end / grid-column-end. Basically we are placing .label in the third column of the first row with it. More about it here https://developer.mozilla.org/en-US/docs/Web/CSS/grid-area
We although can use ::before as a first element with full width using grid-area: 1 / 1 / 2 / 5;. grid treats ::before like a first element.
Using z-index to set one element over another. z-index works some specific way for grid children. More here https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/Basic_Concepts_of_Grid_Layout (Control of overlapping content)
Other children element works without specific grid-area setting, as you can see.
.grid-container {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: minmax(20px, auto);
grid-column-gap: 1px;
grid-row-gap: 1px;
}
.grid-container::before {
content: '';
grid-area: 1 / 1 / 2 / 5;
z-index: 1;
background: cyan;
}
.grid-container .label {
grid-area: 1 / 3 / 2 / 4;
z-index: 2;
}
<div class="grid-container">
<div class="label">label</div>
<div>col1</div>
<div>col2</div>
<div>col3</div>
<div>col4</div>
<div>col1</div>
<div>col2</div>
<div>col3</div>
<div>col4</div>
</div>
I have made up a grid layout that consists of 3 columns wide and 3 rows tall:
.home-works {
padding: 30px;
font-size: 1.2rem;
display: grid;
grid-template-columns: 2fr 2fr 2fr;
grid-template-rows: 2fr 4fr 4fr;
grid-gap: 10px;
}
This is giving me zero problems at desktop view, but what I need to follow up with, now, is when the view port breaks, at the moment I'm working with a max-width:768px rule. So, right now, once the view port breaks to that max-width, any CSS Grid command doesn't seem to have an effect or a change. I have tried using grid-row or grid-row-start grid-column or grid-row-start but no luck.
This is my HTML for the layout:
<div class="home-works">
<div class="head">
<h1>Let's stay connected!</h1>
</div>
<div class="col-menu">
<img class="image-home" src="img/profile-picture.png" width="50%">
<ul>
<li>home</li>
<li>about</li>
<li>contact</li>
<li>downloads</li>
</ul>
</div>
<div class="main-content">
<p>This is my website and I call it, the <em>"glassless window"</em>
Why? Because using the frame on your device (mobile, desktop or laptop)
we are allowed to establish a connection thus enabling me to show you my
up and coming projects. </p>
</div>
<div class="caption-object">
<p>I really wish you could <a class="drop-a-line-link" href="#">drop me a line</a> somewhere
in the future!</p>
</div>
</div>
And this is the CSS for the distribution:
.head {
grid-column: 1 / 4;
text-align: center;
}
.col-menu {
grid-column: 1;
grid-row: 2 / 3;
}
.main-content {
grid-column: 2 / 4;
grid-row: 2 / 3;
}
.caption-object {
grid-column: 3 / 4;
grid-row: 3;
}
This is my first time going about media queries and CSS Grid, meaning this is the first time i input a grid command inside a media query rule set. I checked to see if this would happen too if I wanted to change the background-color: plum; and it did worked. I know about repeat(minmax()) but honestly I wouldn't know how to properly achieve the same look or if it would have the same 'layout design' because then I'd have to delete the grid row's and column's placement? Like I said this is my first time ever using CSS Grid with media queries, I have attached some pics, thanks!
Initially I decided not to include it because nothing had seemed to be working so I didn't have a reason to include.
#media only screen and (max-width: 768px) {
.nav-items {
flex-direction: column;
align-items: center;
}
.navbar {
height: 200px;
padding-bottom: 20px;
}
.footer-link {
align-self: center;
left: 0;
top: 0;
}
.main-container {
flex-flow: column wrap;
margin: 0 10px;
}
.drop-a-line-link {
text-decoration: underline wavy;
}
}
Media Query
To answer my own question this is what I did and its available on MDN, have to check "Redefining the grid using media queries" topic.
To reorganize a CSS Grid layout one must set up the media query rule (which in this case I had it different than on MDN archives but somehow still worked) and in there I had to reassign my grid-template-areas, which was also another thing I lacked, I was NOT using grid-areas, I had stuff like grid-row or grid-columns. Apparently this seems to be a huge factor that comes to play when we are inside our Media Query code. One thing that they do note as important, when working with grid-areas is that one should assign them, outside of any Media Query commands, to cover just one "row" or one "column", I guess depends on your current grid-auto-flow command, which at default is set as row while defining the columns and rows
So, mine is looking like this:
display: grid;
grid-template-columns: 1fr;
grid-template-rows: minmax(350px, auto);
grid-template-areas:
"header"
"menu"
"main"
"caption";
Since I had not defined any areas on my previous grid I would never have gotten it to work the way I intended for it to behave. Well, and then once in the MQ, you assign the grid as best you can, but first, you need to use grid-template-areas to re-assign the areas, and as well as your columns, using grid-template-columns, this depends on your layout and item sizes or basically it depends on the idea that you had for the grid.
So my Media Query code ended up looking like this:
#media (min-width: 500px) {
.home-works {
grid-template-columns: 2fr 2fr 2fr;
grid-template-areas:
"header header menu"
". main main"
". . caption";
}
}
#media (min-width:700px) {
.home-works {
grid-template-areas:
"header header header"
"menu main main"
". . caption";
}
}
Important: the "." are "white-space", or "negative space" or "empty cells".
I'm trying to solve a grid problem with how the elements are automatically placed in the rows not in the way I intend them to. The code is the simplest possible variation written to demonstrate the issue. The number of paragraphs is variable-length, there can be any amount of them.
div {
display: grid;
grid-template-columns: repeat(2, 1fr);
}
p:nth-child(4n + 1) {
grid-column: 1 / span 1;
}
p:nth-child(4n + 2) {
grid-column: 2 / span 1;
}
p:nth-child(4n + 3) {
grid-column: 2 / span 1;
}
p:nth-child(4n) {
grid-column: 1 / span 1;
}
<div>
<p>Test1</p>
<p>Test2</p>
<p>Test3</p>
<p>Test4</p>
<p>Test5</p>
<p>Test6</p>
<p>Test7</p>
<p>Test8</p>
<p>Test9</p>
<p>Test10</p>
</div>
Here is the current result, with two arrows showing what I want to achieve:
And here is exactly what I want to achieve, created for presentation purposes by just reordering HTML elements in a basic grid:
Thank you in advance!
This can be solved with the grid-auto-flow: dense CSS rule on the grid parent. This has the effect that previously blank cells will be filled, rather than searching for the next available space.
I have a dynamically generated grid that, for reasons, does not have elements in an unknown number of initial rows. All of the grid container's children but the last are given what row they belong to. Is there a way to ensure that the last element is placed in the last row? Is there a grid-row-start equivalent to grid-column-start: -1?
To expand on the question, by default, the last element will probably be alone at the beginning:
.container {
display: grid;
grid-auto-columns: 1fr;
grid-auto-rows: 60px;
}
.normal-child {
background-color: blue;
}
.normal-child:nth-child(2n) {
background-color: red;
}
.normal-child--3 {
grid-row: 3 / span 1;
}
.normal-child--4 {
grid-row: 4 / span 1;
}
.normal-child--5 {
grid-row: 5 / span 1;
}
.last-child {
background-color: green;
}
<div class="container">
<div class="normal-child normal-child--3"></div>
<div class="normal-child normal-child--3"></div>
<div class="normal-child normal-child--3"></div>
<div class="normal-child normal-child--4"></div>
<div class="normal-child normal-child--4"></div>
<div class="normal-child normal-child--4"></div>
<div class="normal-child normal-child--5"></div>
<div class="normal-child normal-child--5"></div>
<div class="normal-child normal-child--5"></div>
<div class="last-child"></div>
</div>
I can assign an arbitrarily large number to the element's row-start, but that seems inelegant and there is a chance, though small, that the edge case where it breaks will be encountered.
I also have tried to figure out how to name the last row, but I wasn't able to find a way to name rows in an implicit grid.
There is actually a grid-row: -1 or grid-row-start: -1 just like there is grid-column: -1
It works pretty well as long as your within the range of your explicit grid, but stops working as soon as you get to the implicit grid. The reason is that negative numeric indexes in the grid-placement properties count from the edges of the explicit grid
See also here https://css-tricks.com/difference-explicit-implicit-grids/
The potentially is a plan to at least let items span to last row/column that has been tagged for discussion in level 3, but that doesn't rally address your case either.
But right now, there is no way to achieve what you ask with implicit grid.
There might be some (ugly) solutions but that would at least require a known amount of empty initial rows