I am trying out some very basic grids using display: grid. I have a simple grid with one row, divided into 6 columns. In the HTML I have a div containing the grid, then 6 nested divs containing the 6 items, which should display along one row in 6 columns.
However, instead, they stack on top of each other - why?
This is what it looks like when run:
.gridnav {
display: grid;
/*Gap between columns cells*/
grid-column-gap: 15px;
grid-row-gap: 2px;
/*Padding on left and right edges*/
padding: 0px 10px 0px;
/*Centres items vertically and horizontally*/
align-items: center;
grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr;
grid-template-areas: '1 2 3 4 5 6';
}
.navitem1 { grid-area: 1; }
.navitem2 { grid-area: 2; }
.navitem3 { grid-area: 3; }
.navitem4 { grid-area: 4; }
.navitem5 { grid-area: 5; }
.navitem6 { grid-area: 6; }
<div class="gridnav">
<div class="navitem1">1</div>
<div class="navitem2">2</div>
<div class="navitem3">3</div>
<div class="navitem4">4</div>
<div class="navitem5">5</div>
<div class="navitem6">6</div>
</div>
Any ideas most welcome, thanks
I have a simple grid with one row, divided into 6 columns.
Actually, you have the reverse. You have a grid with one column, divided into 6 rows.
The grid-area property is a shorthand property. It breaks down like this:
grid-row-start
grid-column-start
grid-row-end
grid-column-end
Therefore, your code:
.navitem1 { grid-area: 1; }
.navitem2 { grid-area: 2; }
.navitem3 { grid-area: 3; }
.navitem4 { grid-area: 4; }
.navitem5 { grid-area: 5; }
.navitem6 { grid-area: 6; }
Is equivalent to this:
.navitem1 {
grid-row-start: 1;
grid-column-start: auto;
grid-row-end: auto;
grid-column-end: auto;
}
.navitem2 {
grid-row-start: 2;
grid-column-start: auto;
grid-row-end: auto;
grid-column-end: auto;
}
...
So here's what's really happening:
This rule in the container is doing exactly what you expect.
grid-template-areas: '1 2 3 4 5 6'
But then the grid-area rules are overriding grid-template-areas. Above is what it looks like in Chrome dev tools.
As you can see, the items are originally lined up in one row and six columns (as you expect). But in the end, all items line up on six rows in a one column (because of the grid-area overrides).
However, if you use a non-integer value, like this:
.navitem1 { grid-area: a; }
It would translate to this:
.navitem1 {
grid-row-start: a;
grid-column-start: a;
grid-row-end: a;
grid-column-end: a;
}
... which would work for your purposes, as the values of grid-template-areas and grid-area are fully aligned.
Spec reference for the grid-area property.
It seems that grid template areas can't be named integers. Changing them to a, b, c, etc. makes it work.
.gridnav {
display: grid;
/*Gap between columns cells*/
grid-column-gap: 15px;
grid-row-gap: 2px;
/*Padding on left and right edges*/
padding: 0px 10px 0px;
/*Centres items vertically and horizontally*/
align-items: center;
grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr;
grid-template-areas: 'a b c d e f';
}
.navitem1 { grid-area: a; }
.navitem2 { grid-area: b; }
.navitem3 { grid-area: c; }
.navitem4 { grid-area: d; }
.navitem5 { grid-area: e; }
.navitem6 { grid-area: f; }
<div class="gridnav">
<div class="navitem1">1</div>
<div class="navitem2">2</div>
<div class="navitem3">3</div>
<div class="navitem4">4</div>
<div class="navitem5">5</div>
<div class="navitem6">6</div>
</div>
The solution can be achieved without writing these many lines of code. You don't need to use grid-template-area until and unless you want to switch the div positions. Let me take you to the solution real quick.
.gridnav {
width: 90%;
margin: 0 auto;
display: grid;
grid-template-rows: 1fr; /* Optional */
grid-template-columns: repeat(6,1fr);
grid-column-gap: 15px;
grid-row-gap: 2px;
align-items: center;
}
.gridnav div {
border: 2px solid red;
text-align: center;
}
First thing, define some width to the parent container. In your case it is div with class .gridnav. Since you already defined this section as a grid, I would define the rows and columns first. Since you don't need many rows but just one, it is okay not to define row.
For columns, you can have 1fr 1fr 1fr 1fr 1fr 1fr; but I would reduce code to grid-template-columns: repeat(6,1fr);
Further styling you can have as you want. Let me know if you have any further questions regarding this.
For more details you can always visit these two links:
https://mozilladevelopers.github.io/playground/css-grid/02-first-grid/
https://css-tricks.com/snippets/css/complete-guide-grid/
Hope you will find your answer in this. You can see code working here : Hit that Run Code Snippet button
.gridnav {
width: 90%;
margin: 0 auto;
display: grid;
grid-template-rows: 1fr; /* Optional */
grid-template-columns: repeat(6,1fr);
grid-column-gap: 15px;
grid-row-gap: 2px;
align-items: center;
}
.gridnav div {
border: 2px solid red;
text-align: center;
}
<div class="gridnav">
<div class="navitem1">1</div>
<div class="navitem2">2</div>
<div class="navitem3">3</div>
<div class="navitem4">4</div>
<div class="navitem5">5</div>
<div class="navitem6">6</div>
</div>
Related
I have a CSS grid with several columns and many rows (I'm building a timetable view). The rows and columns are defined on the grid element itself, and then on the elements within the grid I set their column (always only one column) and their rows (might be more than one row).
An example is as follows:
.grid {
display: grid;
grid-template-rows: [row-a] 1fr [row-b] 1fr [row-c] 1fr [row-d] 1fr;
grid-template-columns: [col] 1fr;
flex-grow: 1;
}
.entry-one {
grid-column: col;
grid-row: row-a/row-d;
background-color: red;
}
.entry-two {
grid-column: col;
grid-row: row-b;
background-color: green;
}
<div class='grid'>
<div class='entry-one'>
Foobar
</div>
<div class='entry-two'>
Barfoo
</div>
</div>
Now, what I would like to have is that the elements resize themselves and flow nicely, such that they fit next to each other. I can mock this using width and margin on the elements:
.grid {
display: grid;
grid-template-rows: [row-a] 1fr [row-b] 1fr [row-c] 1fr [row-d] 1fr;
grid-template-columns: [col] 1fr;
flex-grow: 1;
}
.entry-one {
grid-column: col;
grid-row: row-a/row-d;
background-color: red;
width: 50%; /* ADDED */
}
.entry-two {
grid-column: col;
grid-row: row-b;
background-color: green;
width: 50%; /* ADDED */
margin-left: 50%; /* ADDED */
}
<div class='grid'>
<div class='entry-one'>
Foobar
</div>
<div class='entry-two'>
Barfoo
</div>
</div>
However this is not optimal, especially as the elements are inserted dynamically. Is there a way to have the elements size & align themselves automatically using CSS? I've tried to use display: flex on the entries, but that did not result in what I want (or maybe I forgot to add another rule).
Thank you for any ideas, and have a nice day!
I made this to see if that is what you are looking for
.grid{
display: flex;
grid-template-rows: [row-a] 1fr [row-b] 1fr [row-c] 1fr [row-d] 1fr;
grid-template-columns: [col] 1fr;
flex-grow: 1;
}
I just changed your display to flex and delete your margin-left: 50%; on the entry two, hope it is what you are looking for
I'm working on a website and I have 4 grid cells which take up a section of my webpage. The issue is that all of my text is in random places, I want it to be centered within each grid item (one is gray, one is blue, one is black, one is yellow).
I've tried every combination of justify, align, self, any idea how I can do this? Any help would be very much appreciated.
Here's my jsfiddle documenting the problem: https://jsfiddle.net/RomelF/jd8L7a6n/3/
And here's my HTML:
<div class="container">
<section id="welcome-section"><h1 id="name">My name's Romel, here are some of my projects:</h1>
</section>
<section id="projects">
<div class="project-tile" id="p1"><p class="ptext"><a href="#">Tribute Page<a></p></div>
<div class="project-tile" id="p2"><p class="ptext"><a href="#">Political Questionnaire<a></p></div>
<div class="project-tile" id="p3"><p class="ptext"><a href="#">Landing Page<a></p></div>
<div class="project-tile" id="p4"><p class="ptext"><a href="#">Technical Documentation<a></p></div>
</section>
And here's my CSS:
#projects {
width: 70%;
display: grid;
}
...
.project-tile {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr;
place-items: stretch;
height: 50vh
}
#p1 {
background: rgb(255,253,254);
background: radial-gradient(circle, rgba(255,253,254,1) 0%, rgba(74,75,75,0.4) 100%);
grid-column: 1 / 2;
grid-row: 1 / 2;
}
#p2 {
background-color: black;
grid-column: 1 / 2;
grid-row: 2 / 3;
}
#p3 {
background-color: blue;
grid-column: 2 / 3;
grid-row: 1 / 2;
}
#p4 {
background-color: yellow;
grid-column: 2 / 3;
grid-row: 2 / 3;
}
.project-tile a {
text-decoration: none;
}
.ptext {
align-self: center;
}
your .project-tile doesn't need to be a grid itself. Using flexbox gives you all the tools you need to center an element.
.project-tile {
display: flex;
place-items: center;
height: 50vh;
}
.ptext {
margin: auto
}
This will give you centred text as long as the text fits inside the boundaries of the parent.
Please remove this style
.project-tile{
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr;
}
I want to achieve the following layout in CSS Grid.
Notice how row "C" has a blue background that is full width but the content inside it is wrapped, and not full width. But I don't know what's the most optimal way of achieving this?
So here's my code:
container {
display: grid;
grid-template-columns: 0.5fr 1fr 1fr 0.5fr;
grid-template-areas:
"A A A A"
". B B ."
"C C C C"
". D D .";
}
What I've tried:
I've tried 16.66% padding to both sides for row "C".
I've tried making the row C be a Grid itself. Inside it, I'd have columns 0.5fr, 1fr, 1fr, 0.5fr. But this is lot of repeated code, and is lot of work for a simple thing.
What is the most CSS Grid way of approaching this? All the tutorials I've seen, doesn't seem to cover this special case.
One option is to make C span the two columns in the center which seems in line with your layout and use a pseudo element that takes care of the background
add grid-row: 3 and grid-column: 1 / -1 to the pseudo element to place it in the same position as C but spanning the whole width
push it to the back using z-index: -1 and position: relative
See demo below:
body {
margin: 0;
}
* {
box-sizing: border-box;
}
.wrapper{
display: grid;
grid-template-columns: 0.5fr 1fr 1fr 0.5fr;
grid-template-areas:
"A A A A"
". B B ."
". C C ."
". D D .";
height: 100vh;
}
.wrapper:after {
content: '';
display: block;
grid-column: 1 / -1;
grid-row: 3;
background: cadetblue;
position: relative;
z-index: -1;
}
.A {
grid-area: A;
background: pink;
}
.B {
grid-area: B;
background: orange;
}
.C {
grid-area: C;
background: lightgreen;
}
.D {
grid-area: D;
background: orange;
}
<div class="wrapper">
<div class="A">A</div>
<div class="B">B</div>
<div class="C">C</div>
<div class="D">D</div>
</div>
we are trying to develop UI layout using css grid for IE-11, problem here is we have already developed the layout for all the browsers but have not tested on IE11, now we are in last stages of the application and trying to make it work for IE11 but it looks like current css is not working for IE11, so decided to write the separate css for IE11 by browser detection.
here is my mockup (trying to develop without changing the HTML -> if we change the HTML it will effect other browsers)
my question is , if you see the code i am unable to produce the required layout as shown in the mockup with out changing the html structure.
body {
margin: 100px;
}
.box {
background-color: #444;
color: #fff;
border-radius: 5px;
padding: 20px;
font-size: 150%;
margin: 10px;
}
.ie-content {
display: -ms-grid;
display: grid;
grid-gap: 10px;
-ms-grid-columns: 1fr 1fr 1fr 1fr;
grid-template-columns: 1fr 1fr 1fr 1fr;
background-color: blueviolet;
color: #444;
}
.ie-viewer {
-ms-grid-column: 1;
grid-column: 1;
background: yellowgreen;
-ms-grid-column-span: 3;
grid-column: 1 / span 3;
}
.ie-viewerControls {
-ms-grid-column: 1;
grid-column: 1;
}
.ie-configure {
-ms-grid-column: 4;
grid-column: 4;
background: red;
height:100px;
}
<div class="ie-content">
<div class="box ie-viewer">viewer</div>
<div class="box ie-viewerControls">viewerControls</div>
<div>
<div class="box ie-configure">configure </div>
</div>
</div>
</div>
IE 11 has no equivalent for grid-column-gap and grid-row-gap. If you need that, you will have to add fake column/gaps like
-ms-grid-columns: 1fr 20px 1fr 20px 1fr 20px 1fr;
On top of that, each and every element in an IE 11 grid must be positioned col/row-wise, otherwise they end up stacking on top of each other in col 1/row 1.
That being said, of course you need to take the fake "gap" columns/rows into account when positioning/spanning elements.
I was hoping to use CSS Grid to reverse the apparent order of two side-by-side divs, where one of the divs grows arbitrarily (I don't want to use floats).
I've created a plunkr here: http://plnkr.co/edit/6WZBnHbwhD7Sjx2ovCO7?p=preview
#container {
grid-template-columns: 240px 1fr;
display: grid;
}
.a {
background: yellow;
}
.b {
background: blue;
color: white;
}
#container>.a {
grid-column: 1;
}
#container>.b {
grid-column: 2;
}
#container.reverse>.a {
grid-column: 2;
}
#container.reverse>.b {
grid-column: 1;
}
<div id="container" class="reverse" style="width: 800px;">
<div class="a">A</div>
<div class="b">B</div>
</div>
The crux of it is that when I have the .reverse class applied (so that you should see B | A), B is offset to a new line so it looks more like:
| A
B
If I invert the document ordering of .a with .b, this goes back to normal (but of course, if I drop the .reverse class, I get the same problem).
Why is this, and how can I address?
As the Grid auto-placement algorithm lays out items in the container, it uses next available empty cells (source).
In your source code the A element comes before the B element:
<div id="container" class="reverse" style="width: 800px;">
<div class="a">A</div>
<div class="b">B</div>
</div>
Therefore, the grid container first places A, then uses the next available space to place B.
By default, the auto-placement algorithm looks linearly through the grid without backtracking; if it has to skip some empty spaces to place a larger item, it will not return to fill those spaces. To change this behavior, specify the dense keyword in grid-auto-flow.
http://www.w3.org/TR/css3-grid-layout/#common-uses-auto-placement
grid-auto-flow: dense
One solution to this problem (as you have noted) is to override the default grid-auto-flow: row with grid-auto-flow: dense.
With grid-auto-flow: dense, the Grid auto-placement algorithm will look to back-fill unoccupied cells with items that fit.
#container {
display: grid;
grid-template-columns: 240px 1fr;
grid-auto-flow: dense; /* NEW */
}
7.7. Automatic Placement: the grid-auto-flow
property
Grid items that aren’t explicitly placed are automatically placed into
an unoccupied space in the grid container by the auto-placement
algorithm.
grid-auto-flow controls how the auto-placement algorithm works,
specifying exactly how auto-placed items get flowed into the grid.
dense
If specified, the auto-placement algorithm uses a “dense” packing
algorithm, which attempts to fill in holes earlier in the grid if
smaller items come up later. This may cause items to appear
out-of-order, when doing so would fill in holes left by larger items.
#container {
display: grid;
grid-template-columns: 240px 1fr;
grid-auto-flow: dense; /* NEW */
}
.a {
background: yellow;
}
.b {
background: blue;
color: white;
}
#container>.a {
grid-column: 1;
}
#container>.b {
grid-column: 2;
}
#container.reverse>.a {
grid-column: 2;
}
#container.reverse>.b {
grid-row: 1;
grid-column: 1;
}
<div id="container" class="reverse" style="width: 800px;">
<div class="a">A</div>
<div class="b">B</div>
</div>
grid-row: 1
Another solution would be to simply define the row for the second item.
#container>.b {
grid-column: 2;
grid-row: 1; /* NEW */
}
#container {
display: grid;
grid-template-columns: 240px 1fr;
}
.a {
background: yellow;
}
.b {
background: blue;
color: white;
}
#container>.a {
grid-column: 1;
}
#container>.b {
grid-column: 2;
grid-row: 1; /* NEW */
}
#container.reverse>.a {
grid-column: 2;
}
#container.reverse>.b {
grid-row: 1;
grid-column: 1;
}
<div id="container" class="reverse" style="width: 800px;">
<div class="a">A</div>
<div class="b">B</div>
</div>
The simplest way is to add order: 1 to element B or order: -1 to element A in .reverse
It's also correct CSS rather than hack-y
I'm not sure how to reverse more grid items. But if you have 2 grid items in your grid, you can simply position 2nd grid item using below code.
#container > .b {
grid-column-start: 1;
grid-row-start: 1;
}
I had this same issue just now. I tried auto-row-dense and then set the direction of the container parent to rtl. It worked.
Just this, on the plunker link, seemed to do the trick.
.reverse{
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-auto-flow: dense;
direction: rtl;
}
You can use direction property to reverse a grid x-axis order.
Nested elements will be reversed too so you have to make sure to add additional styles to fix this behavior.
<div class="grid">
<div class="grid-item"><div>
</div>
<style>
.grid { direction : rtl; }
.grid-item { direction : ltr; }
</style>
Edit: this may work but could cause accessibilty issues.
Round peg in square hole
Remember even if you're using fancy 'new' grid features the older flex layout will still work. You can combine them, nest them and sometime you have to admit that certain problems like this may just be better solved with good old
flex-direction: row-reverse
But I know some people will want to downvote me for that so here's another way with grid.
Use named template regions
You can use named template regions and reverse them in the definition.
#container
{
grid-template-areas: a b;
grid-template-rows: 240px 1fr;
display: grid;
}
#container.reverse
{
// note the order is flipped for both these properties
grid-template-areas: b a;
grid-template-rows: 1fr 240px;
}
.a {
grid-area: a;
background: yellow;
}
.b {
grid-area: b;
background: blue;
color: white;
}
Here's an more complex example that uses that technique with media queries
I found out: I need to apply grid-auto-flow: dense; on the container:
#container {
grid-template-columns: 240px 1fr;
display: grid;
grid-auto-flow: dense;
}
According to MDN, this algorithm attempts to fill in holes earlier in the grid.
I want to mention a solution which is also relevant to this question in some cases. When having a multi-row layout, and you want a reversed look of how you grid fills up.
You can play with grid-start combined with some :nth-child & :last-child selectors to achieve a reverse auto flow.
Reversed grid-auto-flow: column
.container{
display: grid;
width: 10rem;
gap: 0.5rem;
grid-template-rows: repeat(2, 1fr);
grid-auto-flow: column; /* => vertical grid*/
}
/* REMOVE THIS TO SEE THE DIFFERENCE */
.pixel:nth-child(odd):last-child { /* reversed auto-flow: column */
grid-row-start: 2;
}
.pixel{
width: 2rem;
height: 2rem;
background: red;
border: 1px solid black
}
<div class="container">
<!-- ADD/REMOVE SOME PIXELS to see the result -->
<div class="pixel"></div>
<div class="pixel"></div>
<div class="pixel"></div>
<div class="pixel"></div>
<div class="pixel"></div>
<div class="pixel"></div>
<div class="pixel"></div>
</div>
Reversed: horizontal & vertical
.container{
display: grid;
width: 10rem;
gap: 0.5rem;
grid-template-rows: repeat(2, 1fr);
grid-auto-flow: column;
direction: rtl; /* reversed horizontal */
}
/* REMOVE THIS TO SEE THE DIFFERENCE */
.pixel:nth-child(odd):last-child { /* reversed vertical */
grid-row-start: 2;
}
.pixel{
width: 2rem;
height: 2rem;
background: red;
border: 1px solid black
}
<div class="container">
<!-- ADD/REMOVE SOME PIXELS to see the result -->
<div class="pixel">1</div>
<div class="pixel">2</div>
<div class="pixel">3</div>
<div class="pixel">4</div>
<div class="pixel">5</div>
<div class="pixel">6</div>
<div class="pixel">7</div>
</div>
I found out: I need to apply grid-auto-flow: dense; on the container: