2

OK, so what I need is to render nested ul / li into 3 columns.

I want to do this with pure CSS (and no JS) and I have 2 semi-working examples.

Example 1 via display: grid https://jsfiddle.net/slick/1rtucfmL/2/

So for parent ul you simply specify display: grid with grid-template-columns: 1fr 1fr 1fr and you have 3 columns. When you hover on item, then child ul renders nicely.

enter image description here

This example however has issue where items are rendered horizontally (don't want that):

a b c
d e f
g h i

rather than vertically (this is what I need):

a d g 
b e h
c f i

Someone asked this before and the solution is to define qty. of rows. I can't do this because I have dynamic quantity of rows and I don't want to hardcode any values.

So I went to the second example…

Example 2 via column-count: 3 https://jsfiddle.net/slick/g5p2j8bo/2/

This renders column items as I want, from A to Z vertically. However the issue is that when you hover on item, the child ul is shown in a very bizarre way (sometimes it's broken into columns as well, I don't want this).

enter image description here

If only I could fix this child positioning then example 2 would suit my needs.

I have no idea why this happens. I tried to set column-count: 1 because I thought that maybe it inherits 3 from parent but that didn't help.

Any hints? Thanks!

Matt Komarnicki
  • 5,198
  • 7
  • 40
  • 92

2 Answers2

2

Something that can help is avoid breaks, so your css code should be like this

ul#root li>ul {
  top: -12px;
  left: 190px;
  position: absolute;
  break-inside: avoid;  // added
  page-break-inside: avoid;  // added
  will-change: transform;  // added
  visibility: hidden;
  z-index: 1;
  background: #ffffff;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.25);
  list-style: none;
  width: 190px;
  padding: 10px 0;
  font-size: 14px;
  line-height: 16px;
  letter-spacing: .02em;
}

Couldn't add snippet because body limit, but here is a fiddle.

MSclavi
  • 427
  • 2
  • 10
  • Hi @MSclavi, thanks for your reply. This looks like a step in a good direction however still some child `ul` elements are positioned in a weird way. – Matt Komarnicki Apr 14 '19 at 07:28
0

Use MSclavi's solution, along with display: inline-block.

JSfiddle

ul#root li>ul {
  top: -12px;
  left: 190px;
  position: absolute;
  display: inline-block;
  break-inside: avoid; 
  page-break-inside: avoid;  
  will-change: transform; 
  visibility: hidden;
  z-index: 1;
  background: #ffffff;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.25);
  list-style: none;
  width: 190px;
  padding: 10px 0;
  font-size: 14px;
  line-height: 16px;
  letter-spacing: .02em;
}

This is one of the most frustrating problems that I've encountered in CSS3, but!

Try using flex columns with a static height.

ul#root {
  list-style-type: none;
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
  height: 16em; /* Static heights! Oh no! */
}

JSfiddle

Chris Happy
  • 7,088
  • 2
  • 22
  • 49