Yami Odymel
Yami Odymel

Reputation: 1898

Specify the columns to start from the right with CSS Grid

I'm trying to change my Flexbox layout to the new display: grid, and I have three columns.

<div class="grid">
    <div class="three wide column"></div>
    <div class="two   wide column"></div>
    <div class="two   wide column"></div>
</div>

It looks like this:

enter image description here

Is it possible to specify some of the columns to start from the right instead of the left like the following picture?

(And without specifing the grid-column-start and the grid-column-end, this can be done with the margin-left: auto with the Flexbox)

<div class="grid">
    <div class="three wide column"></div>
    <div class="right floated two wide column"></div>
    <div class="right floated two wide column"></div>
</div>

enter image description here

Upvotes: 12

Views: 17484

Answers (3)

Aaron Turkel
Aaron Turkel

Reputation: 154

Actually, you can make a normal grid layout and set the columns as if you were to start from left to right (with the spacing you want). Then just put an Html attr of "dir: rtl"

(run the snippet)

ul {
  border: 1px solid black;
  width: 80%;
  height: 300px;
  display: grid;
  grid-auto-flow: column;
  list-style: none;
}

li {
  width: 20px;
  height: 100%;
  border: 1px solid green;
}

.colored {
  background: green;
}
<ul dir="rtl">
  <li class="colored"></li>
  <li class="colored"></li>
  <li></li>
  <li></li>
  <li class="colored"></li>
</ul>

Upvotes: 3

Michael Benjamin
Michael Benjamin

Reputation: 371221

You wrote:

Specify the columns to start from the right with CSS Grid

Is it possible to specify some of the columns to start from the right instead of the left?

The answer is "yes".

From the Grid spec:

9.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.

So this rule...

div {
   grid-column: -1;
   grid-row: -2;
}

...would position your item in the last column and second-to-last row.


More specifically to your question:

Flexbox allows you to shift items across rows and columns with auto margins and keyword alignment properties (such as justify-content and align-items).

This works because flex layout operates along columns or rows, not both at the same time. Rows and columns don't intersect, so there is no obstruction (other than other items) restricting movement across the line.

Grid Layout operates differently. It works along columns and rows, meaning they can overlap / intersect each other. (This is why Grid can create full-scale grids and flexbox cannot.)

Of course, the problem with intersecting rows and columns is that they block free movement across the line. With intersecting rows and columns, auto margins and keyword alignment properties can only work within the grid area, which could be a single cell or whatever else has been defined.

Some ways to overcome this limitation are to:

  1. expand the grid area (example)
  2. bring in a flex container (flex and grid can be nested within each other)
  3. use absolute positioning

However, the fact that auto margins don't work in Grid as in flex is not really a big deal.

Grid Layout has its own methods for aligning and positioning items.

You have a 12-column layout. You want to move two two-column grid areas to the end of the row. For this, you don't even need to know the total column count, because Grid lets you start counting from the end side. Here's all you need:

div.column:nth-child(2) {
    grid-column: -5 / span 2;
}

div.column:nth-child(3) {
    grid-column: -3 / span 2;
}

These rules tell the grid areas to span two columns (wherever they may be).

Negative integer values on grid-column and grid-row start the count at the end side.

.grid {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  grid-column-gap: 15px;
  height: 50vh;
}

div.column:nth-child(1) {
  grid-column: 1 / span 3;
  background-color: gray;
}

div.column:nth-child(2) {
  grid-column: -5 / span 2;
  background-color: gray;
}

div.column:nth-child(3) {
  grid-column: -3 / span 2;
  background-color: gray;
}

.grid>div {
  background-color: lightgray;
  grid-row: 1;
}
<div class="grid">
  <div class="column three"></div>
  <div class="column two"></div>
  <div class="column two"></div>
  <div class="column"></div>
  <div class="column"></div>
  <div class="column"></div>
  <div class="column"></div>
  <div class="column"></div>
</div>

jsFiddle

Upvotes: 4

Kaivosukeltaja
Kaivosukeltaja

Reputation: 15735

Placing one item into the last column is easy using negative column values, but unfortunately CSS grids don't support flowing the next one automatically to its left. Items are placed into grid cells by the auto-placement algorithm (controlled using the grid-auto-flow property), which is a grid container level setting - meaning your content will get placed either horizontally or vertically. Changing the axis or direction per element is not allowed.

What you could do is create a wrapper element for the floated columns, extend it to the last column using grid-column-end: -1; and place the floated columns using flexbox. You'll need to alter your markup for that though, so you might want to reconsider using CSS grid as your grid system's layout engine. It makes a lot of previously near-impossible layouts easy, but this is one case which it does the opposite.

Upvotes: 5

Related Questions