this post was submitted on 05 Aug 2023
1 points (60.0% liked)

Web Development

3439 readers
11 users here now

Welcome to the web development community! This is a place to post, discuss, get help about, etc. anything related to web development

What is web development?

Web development is the process of creating websites or web applications

Rules/Guidelines

Related Communities

Wormhole

Some webdev blogsNot sure what to post in here? Want some web development related things to read?

Heres a couple blogs that have web development related content

CreditsIcon base by Delapouite under CC BY 3.0 with modifications to add a gradient

founded 1 year ago
MODERATORS
 

SOLVED: by @[email protected] using columns property

TL;DR: I want to achieve this behavior for the menu layout, but all I can get is this; note the different menu options order.

Two days ago I asked for help for implementing the current behavior without hardcoding the menu height for each resolution step, and there were two suggestions to try display: grid. It looked promising and after reading some documentation I was able to get something very close to what I'm looking for.

The only difference being that I want the chapters to be sorted vertically (as in the current version), but what I got sorts the chapters horizontally.

Here it is (what I think is) the relevant code:

#menu ul {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr 1fr;
  grid-auto-flow: row dense;
}

Sorry, I don't have the display: grid version online.

I did a quick search for display grid multiple columns vertical sort and saw this StackOverflow post: CSS Grid vertical columns with infinite rows which, if I understand correctly, says it's not possible. But I'm pretty sure I'm not understanding it correctly.

Any help will be welcome, thanks!

EDIT: I also tried grid-audto-flow: column (as suggested here) but it just renders a single row. Probably because I'm missing something...

#menu ul {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr 1fr;
  grid-auto-flow: column;
}

EDIT-2: I was told that for grid-audto-flow: column to work I need to specify the numbers of columns. If I understand correctly, then that doesn't really help. The original issue is that I need to edit the CSS file every time a new chapter is added. Which would be the same if I have to hardcode the number of rows.

I mean, it's a bit cleaner to hardcode the number of rows than the height in pixels, but I was looking for a solution that doesn't require magic numbers in the CSS.

all 13 comments
sorted by: hot top controversial new old
[–] [email protected] 3 points 1 year ago (2 children)

This is kinda sad. I was hoping someone will give you working solution eventually but nope.

I saw both of your posts. People really overthink this. It's not flex, it's not grid... you need columns.
Straight up columns, not flex column not grid column.

columns - CSS: Cascading Style Sheets | MDN

Sure you can do it with flex or grid, but you need to do some unnecessary trickery on it.
Flex and grid won't wrap column unless you specified it to somehow, parent element will just grow to accommodate any amount of child elements and keep them in one column.

[–] [email protected] 1 points 1 year ago* (last edited 1 year ago) (1 children)

(Different account, same user)

EDIT: I got it working, thank you very much!

Original message:

This is really promising, thank you very much!!

I did a quick test and the only issue is that "extra elements" are not placed from left to right, but from center to the sides. See image below.

If that's not how it works by default, I will take a deeper look to see if that's caused by other CSS properties I have.

image

For some reason, adding a left/right margin to ul li made it behave like the previous lnked image, I don't understand why, but removing the margin fixes it.

[–] [email protected] 2 points 1 year ago* (last edited 1 year ago) (1 children)

Generally you don't need anything for child element, except in rare case, which you have seen before a fix...
Columns usually try to balance every columns to have same height, and last column have least items.

EDIT: In your case, \ having a margin-top, which got clipped when new column starts. I don't know if there is a fix for this but I would use padding instead.

CSS is chaotic, dude.

ul {
  /* reset */
  margin: 0;
  padding: 16px;

  columns: 2;
  /* box-sizing: border-box; */
}
  @media screen and (min-width: 640px) {
    ul {
      columns: 3;
    }
  }
  @media screen and (min-width: 960px) {
    ul {
      columns: 4;
    }
  }

  ul li {
    list-style-type: none;
    padding: 2px 16px 2px 4px;
    font-size: 120%;

    display: flex;
    break-inside: avoid;
  }
  ul li a {
    /* display: inline-block; */
    background-color: #35516c;
    color: #d2dade;
    text-decoration: none;
    padding: 2px 8px;
    border: solid 1px #d2dade;

    flex-grow: 0;
  }
    ul li a:first-child {
      flex-grow: 1;
      /* width: 106px; */
      /* margin-right: -3px; */
    }
    ul li a:hover {
      background-color: #1e445d;
      color: #fff;
      border: solid 1px #fff;
    }

[–] [email protected] 1 points 1 year ago

Generally you don't need anything for child element,

Makes sense. in this case the margin was there from the "display: flex version" and I didn't realize in the first tests.

Columns usually try to balance every columns to have same height, and last column have least items.

Which is exactly what I wanted... and was confused as to why there wasn't an easy option. This is perfect.

Thank you very much!

[–] [email protected] 2 points 1 year ago (1 children)
[–] [email protected] 1 points 1 year ago (1 children)

I also tried that but it just renders a single row. Probably because I'm missing something...

#menu ul {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr 1fr;
  grid-auto-flow: column;
}
[–] [email protected] 2 points 1 year ago (1 children)

Did you read the article? You need to define the number of rows.

[–] [email protected] 1 points 1 year ago (1 children)

If that's the case, I think that doesn't really help. The original issue is that I need to edit the CSS file every time a new chapter is added. Which would be the same if I have to hardcode the number of rows.

I mean, it's a bit cleaner to hardcode the number of rows than the height in pixels, but I was looking for a solution that doesn't require magic numbers in the CSS.

Thanks!

[–] [email protected] 2 points 1 year ago* (last edited 1 year ago) (1 children)

Well you can do a little math to figure it out yourself in that case.

--row-count: item-count / column-count (you need to substitute the item and colum count yourself) You can do something like that in an inline style to define the number of rows. Then in your css define do this grid-template-columns: repeat(var(--row-count), 1fr); this will make it so that the row count is defined in the html which can be dynamic without having to change the css.

[–] [email protected] 1 points 1 year ago (1 children)

(If the ideal solution is not possible) I think you are right.

Let me check I understood: the idea is to have a single changing-magic-number (the number of menu options) set in a variable --item-count and then calculate all the other values from that. The --column-count would be fixed for each resolution step, so that's ok.

Thank you very much for the help!

[–] [email protected] 2 points 1 year ago (1 children)

Yeah more or less. I'm not sure what's rendering your html though, myself I'd do the math in js and just set the row-count variable off the value in the inline style, but it depends on what's doing your dynamic rendering.

[–] [email protected] 1 points 1 year ago

Yep, a bit of JS is another option.

I'm not sure what's rendering your html though

Nothting really, I wanted to keep the project very simple (because there are non-devs contributing to it) and the HTML is static code.