6

Is there a CSS-only way of ordering items in columns for grid layout without using pixel values? Flexbox would work as well. I need the same HTML to enable the following two scenarios (with numbers of columns between 1 and 5 in the dynamically-generated HTML):

Case A:

| item 1          | item 2          | item 3          |
| item 4          | item 5          | item 6          |
| item 7          | item 8          | item 9          |

Case B:

| item 1          | item 4          | item 7          |
| item 2          | item 5          | item 8          |
| item 3          | item 6          | item 9          |

Case A is easy, just need to do something like:

.case-a[data-column-count='3'] {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
}

<div data-column-count="3" class="case-b">
     <label>item 1</label>
     <label>item 2</label>
     <label>item 3</label>
</div>

The closest I came to it is this Codepen, though vertical alignment is messy on each individual column: https://codepen.io/anon/pen/zbGWRa

body {
  font-family: sans-serif;
}

.columns {
  column-width: 18vw;
}
.grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-auto-rows: 2em;
  grid-gap: .5em;
  align-items: center;
  background: #eee;
  padding: .5em;
  box-decoration-break: clone;
  counter-reset: nb;
  border: 2px solid red;
}
input {
  align-self: stretch;
  border-radius: 2px;
  border: 1px solid #ccc;
}
label::before {
  counter-increment: nb;
  content: counter(nb) ". ";
}
<div class="columns">
  <div class="grid">
    <label>label</label>
    <input type="text">
    <label>label</label>
    <input type="text">
    <label>label</label>
    <input type="text">
    <label>label</label>
    <input type="text">
    <label>label</label>
    <input type="text">
    <label>label</label>
    <input type="text">
    <label>label</label>
    <input type="text">
  </div>
</div>

Another Codepen - I can also indirectly control the number of columns by specifying the number of items per column, but I want to just specify a number of columns: https://codepen.io/anon/pen/BbNqGE

.container {
  display: grid;
  grid-template-columns: 1fr;
}

.container {
  grid-template-rows: 1fr 1fr 1fr 1fr 1fr;
  grid-auto-columns: 1fr;
  grid-auto-flow: column;
}

* {
  box-sizing: border-box;
}

body {
  font-size: 1.35em;
  font-family: 'Varela Round', sans-serif;
  color: #fff;
  background: #e8e9e9;
  padding-left: 5%;
  padding-right: 5%;
}

.container {
  padding: 10px;
  background: #fff;
  border-radius: 5px;
  margin: 45px auto;
}

.item {
  color: #fff;
  padding: 15px;
  margin: 5px;
  background: #3db5da;
}
<div class="container">
  <div class="item-1 item">Item 1</div>
  <div class="item-2 item">Item 2</div>
  <div class="item-3 item">Item 3</div>
  <div class="item-4 item">Item 4</div>
  <div class="item-5 item">Item 5</div>
  <div class="item-5 item">Item 6</div>
  <div class="item-5 item">Item 7</div>
</div>

8
  • For some reason I am unable to load the codepen. It keeps freezing and flickering. Commented Feb 27, 2019 at 18:59
  • That’s a chrome issue @NickLee Commented Feb 27, 2019 at 19:14
  • 1
    Please do not use external code sites. Instead, use StackOverflow snippet functionality unless you need features those don't offer. Commented Feb 27, 2019 at 19:15
  • 1
    @connexo I would agree with you but I think it’s best to include both. SO mobile apps don’t support snippets (it looks like they don’t plan on it either) Commented Feb 27, 2019 at 19:16
  • 1
    @soulshinedThat's why I added unless you need features those don't offer. This is not the case here. Commented Feb 27, 2019 at 19:41

1 Answer 1

3

You can do this with CSS' grid-template-area.

The code will look like this. Where grid-template-areas represents the placement. And in each id of the element will define the named area. grid-area: a;. The id selector of each element does not need to match the grid-are name as in my example.

*{
  box-sizing: border-box;
}
.wrapper {
  color:white;
  font-size: 2em;
  
  display:grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: 100px 100px 100px;
    
  grid-template-areas: 
                       "a d g"
                       "b e h"
                       "c f i";

}
#a{
  background-color:rgb(180,247,182);
  grid-area: a;
}
#b{
  background-color:rgb(250,235,122);
  grid-area:b;
}
#c{
  background-color:rgb(167,255,250);
  grid-area:c;

}
#d{
  background-color:rgb(227,176,252);
    grid-area:d;

}
#e{
  background-color:rgb(157,255,205);
  grid-area:e;

}
#f{
  background-color:rgb(243,152,98);
    grid-area:f;

}
#g{
  background-color:rgb(55,32,199);
    grid-area:g;

}
#h{
  background-color:rgb(120,152,98);
    grid-area:h;

}
#i{
  background-color:rgb(243,100,98);
    grid-area:i;

}

.wrapper > div {
  display: flex;
  align-items: center;
  justify-content: center;
}
<div class="wrapper">
  <div id="a">1</div>
  <div id="b">2</div>
  <div id="c">3</div>
  <div id="d">4</div>
  <div id="e">5</div>
  <div id="f">6</div>
  <div id="g">7</div>
  <div id="h">8</div>
  <div id="i">9</div>

</div>

Sign up to request clarification or add additional context in comments.

1 Comment

That's nice. Though it means that I need to know the number of items in advance (to at least be able to generate names for the grid areas (which I don't have - items will be editable by users of the component I'm building). Theoretically I could arrive at a place where I can get those items. Thanks for this tentative direction to investigate!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.