2

I have a nested list and each list item works like a table row (using flex). The nested items i.e. rows are indented from the left so the width is different at different levels. It currently has tree levels but this may change at some point.

I want to:

  1. Align all "columns" other than first one, on a single verticle line, and
  2. Apply % widths on the columns excepts first one.

So far, I have only been able to achieve the alignment part using fixed pixel widths. But I really need to set the column .second and .third width based on % of top-most ul, otherwise the columns would not align perfectly. Fixed pixel widths aren't good for responsiveness.

I have two options in my mind:

  1. Removing the left margin on list items and adding left-margin on .first. But this would mean manually adding borders on each "cell" and also some other code duplication.
  2. Maybe there is a way to use CSS calc() somehow. With recursively rendered list, this seems quite complicated though. I am using this markup in a React.js component and I need to pass the level as prop and then use calc() in inline style. Doesn't look clean.

ul {
  list-style-type: none;
  padding: 0;
  margin-left: 2rem;
}

.row {
  display: flex;
  border: 1px solid gray;
}

.first {
  flex-grow: 1;
}

.second,
.third {
  width: 200px;
}
<ul>
  <li>
    <div class="row">
      <div class="first">
        Title
      </div>
      <div class="second">
        Description
      </div>
      <div class="third">
        Date
      </div>
    </div>
    <ul>
      <li>
        <div class="row">
          <div class="first">
            Title
          </div>
          <div class="second">
            Description
          </div>
          <div class="third">
            Date
          </div>
        </div>
      </li>
      <li>
        <div class="row">
          <div class="first">
            Title
          </div>
          <div class="second">
            Description
          </div>
          <div class="third">
            Date
          </div>
        </div>
        <ul>
          <li>
            <div class="row">
              <div class="first">
                Title
              </div>
              <div class="second">
                Description
              </div>
              <div class="third">
                Date
              </div>
            </div>
          </li>
          <li>
            <div class="row">
              <div class="first">
                Title
              </div>
              <div class="second">
                Description
              </div>
              <div class="third">
                Date
              </div>
            </div>
          </li>
        </ul>
      </li>
      <li>
        <div class="row">
          <div class="first">
            Title
          </div>
          <div class="second">
            Description
          </div>
          <div class="third">
            Date
          </div>
        </div>
      </li>
    </ul>
  </li>
  <li>
    <div class="row">
      <div class="first">
        Title
      </div>
      <div class="second">
        Description
      </div>
      <div class="third">
        Date
      </div>
    </div>
  </li>
  <li>
    <div class="row">
      <div class="first">
        Title
      </div>
      <div class="second">
        Description
      </div>
      <div class="third">
        Date
      </div>
    </div>
  </li>
</ul>
Irfanullah Jan
  • 3,336
  • 4
  • 24
  • 34
  • There is no really well supported method of aligning elements that do not share a parent. `display:subgrid` will work but is only supported by Firefox at present - https://caniuse.com/?search=subgrid – Paulie_D Jul 08 '21 at 11:17
  • https://stackoverflow.com/questions/56711501/align-child-elements-of-different-blocks – Paulie_D Jul 08 '21 at 11:18
  • Frankly I think you should be nesting `table` elements since this does seem like what you are going for. – Paulie_D Jul 08 '21 at 11:20

1 Answers1

0

I found a simple workaround. For my use case, simply setting the width of the columns to percentage of viewport does the job. i.e. width: 25vw

Now looks nice on both narrow and wider screens. Also quite happy with the browser support: https://caniuse.com/viewport-units

Please compare with above snippet on "Full page" view to see column widths are responsive on this one and are not responsive in the question snippet.

ul {
  list-style-type: none;
  padding: 0;
  margin-left: 2rem;
}

.row {
  display: flex;
  border: 1px solid gray;
}

.first {
  flex-grow: 1;
}

.second,
.third {
  width: 25vw;
}
<ul>
  <li>
    <div class="row">
      <div class="first">
        Title
      </div>
      <div class="second">
        Description
      </div>
      <div class="third">
        Date
      </div>
    </div>
    <ul>
      <li>
        <div class="row">
          <div class="first">
            Title
          </div>
          <div class="second">
            Description
          </div>
          <div class="third">
            Date
          </div>
        </div>
      </li>
      <li>
        <div class="row">
          <div class="first">
            Title
          </div>
          <div class="second">
            Description
          </div>
          <div class="third">
            Date
          </div>
        </div>
        <ul>
          <li>
            <div class="row">
              <div class="first">
                Title
              </div>
              <div class="second">
                Description
              </div>
              <div class="third">
                Date
              </div>
            </div>
          </li>
          <li>
            <div class="row">
              <div class="first">
                Title
              </div>
              <div class="second">
                Description
              </div>
              <div class="third">
                Date
              </div>
            </div>
          </li>
        </ul>
      </li>
      <li>
        <div class="row">
          <div class="first">
            Title
          </div>
          <div class="second">
            Description
          </div>
          <div class="third">
            Date
          </div>
        </div>
      </li>
    </ul>
  </li>
  <li>
    <div class="row">
      <div class="first">
        Title
      </div>
      <div class="second">
        Description
      </div>
      <div class="third">
        Date
      </div>
    </div>
  </li>
  <li>
    <div class="row">
      <div class="first">
        Title
      </div>
      <div class="second">
        Description
      </div>
      <div class="third">
        Date
      </div>
    </div>
  </li>
</ul>
Irfanullah Jan
  • 3,336
  • 4
  • 24
  • 34