Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reverse order of columns in CSS Grid Layout

Tags:

html

css

css-grid

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?

like image 879
Rob Avatar asked Jul 28 '17 22:07

Rob


People also ask

How do I reverse the order of CSS grid?

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.

How do you change the order of columns in CSS?

Use grid-row-start , grid-row-end , grid-column-start , grid-column-end , or their shorthands, grid-row and grid-column , to set a grid item's size and location in the grid.

What is Fr in grid layout in CSS?

Thankfully, CSS Grid Layout introduces a new unit of length called fr, which is short for “fraction”. MDN defines the fr unit as a unit which represents a fraction of the available space in the grid container.

Can I use order in grid?

The order property can be used to specify the order in which different items should be placed inside a grid. By default, the items are placed in the order in which they appear in the DOM. For example, if item A is above item B in the actual source document, it will also be placed in the grid before item B.


2 Answers

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>
like image 192
Michael Benjamin Avatar answered Sep 21 '22 22:09

Michael Benjamin


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; } 
like image 44
Angrej Kumar Avatar answered Sep 18 '22 22:09

Angrej Kumar