skip to Main Content

I’m trying to achieve a calculator-like icon layout on a mobile navmenu.
The icons should display like on a mobile phone home screen, 3 columns and as many rows as needed for all the list items.
Now, if a list only has 2 items for example, that fill column 1 and 2, I want the next list to start in the empty column 3. If it has more than 1 item, it should go to the next row and fill up that row. Is there a way to achieve this with css only?

I’ve tried the attached flex and grid layouts, but get stuck because I can’t get the behaviour mentioned before. I also don’t wanna assign the columns and rows that items are on with template areas, because the items in the lists are dynamic and can vary from page to page.
Thanks in advance!

Edit: Restriction: I can’t edit the HTML and enclose all <li> elements in one <ol>

My HTML:

<div class="entries">
  <ol>
    <li>1a</li>
    <li>2a</li>
    <li>3a</li>
  </ol>
  <ol>
    <li>4b</li>
    <li>5b</li>
  </ol>
  <ol>
    <li>6c</li>
    <li>7c</li>
  </ol>
  <ol>
    <li>8d</li>
  </ol>
  <ol>
    <li>9e</li>
    <li>10e</li>
  </ol>
</div>

My Grid CSS:

.entries {
  display: grid;
  grid-template-rows: 1fr;
  width: 500px;
}

ol {
  list-style: none;
  margin: 0;
  padding: 0;
  gap: 20px;
  margin: 10px 0;
  display:grid;
  grid-template-columns: repeat(3, 1fr);
}

Codepen of Grid Layout
Codepen of Flex Layout

4

Answers


  1. why not change the structure of the HTML?div > some spans will make it easy to achieve your target by using CSS.

    Login or Signup to reply.
  2. You could remove all those ol and leave onle one wrapping all items, and it could be done easily.

    <div class="entries">
      <ol>
        <li>1a</li>
        <li>2a</li>
        <li>3a</li>
        <li>4b</li>
        <li>5b</li>
        <li>6c</li>
        <li>7c</li>
        <li>8d</li>
        <li>9e</li>
        <li>10e</li>
      </ol>
    </div>
    

    And with your same grid (or flex) CSS rules it’s done

    Login or Signup to reply.
  3. It is possible by "opening" the ol by using display: contents and then using display: grid on the wrapping div container.

    display: contents causes an element’s children to appear as if they were direct children of the element’s parent, ignoring the element itself. This can be useful when a wrapper element should be ignored when using CSS grid or similar layout techniques.

    body {
      margin: 0;
    }
    
    .entries {
      border: 1px solid red;
      margin: 0 auto;
      display: grid;
      grid-template-rows: 1fr;
      gap: 20px;
      width: 500px;
      grid-template-columns: repeat(3, 1fr);
    }
    
    ol {
      list-style: none;
      margin: 0;
      padding: 0;
      gap: 20px;
      margin: 10px 0;
      outline: 1px solid green;
      display: contents;
    }
    
    li {
      background-color: lightblue;
      box-sizing: border-box;
      padding: 10px;
      text-align: center;
      border-radius: 5px;
      aspect-ratio: 1/1;
    }
    <div class="entries">
      <ol>
        <li>1a</li>
        <li>2a</li>
        <li>3a</li>
      </ol>
      <ol>
        <li>4b</li>
        <li>5b</li>
      </ol>
      <ol>
        <li>6c</li>
        <li>7c</li>
      </ol>
      <ol>
        <li>8d</li>
      </ol>
      <ol>
        <li>9e</li>
        <li>10e</li>
      </ol>
    </div>
    Login or Signup to reply.
  4. You may change your CSS a little bit like:

            .entries {
            display: grid;
            grid-template-columns: repeat(3, 1fr);    
    
            /* grid-template-rows: 1fr; */
            width: 500px;
            }
    
            ol {
            list-style: none;
            margin: 0;
            padding: 0;
            gap: 20px;
            margin: 10px 0;
    
            /* display:grid; */
            /* grid-template-columns: repeat(3, 1fr); */
            }
        <div class="entries">
            <ol>
              <li>1a</li>
              <li>2a</li>
              <li>3a</li>
            </ol>
            <ol>
              <li>4b</li>
              <li>5b</li>
            </ol>
            <ol>
              <li>6c</li>
              <li>7c</li>
            </ol>
            <ol>
              <li>8d</li>
            </ol>
            <ol>
              <li>9e</li>
              <li>10e</li>
            </ol>
          </div>    

    Does this serve your purpose?

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search