0

Currently I am trying to show something like this in a website:

enter image description here

As you can see, there is a list of elements where all their sub elements are lined up. As of now I have something like this:

<div class="container">
    <div class="element">
        <div>Some text</div>
        <ProgressBar ... component stuff />
        <div>Another: <b>10</b></div>
    </div>
        <div class="element">
        <div>Name Two</div>
        <ProgressBar ... component stuff />
        <div>Another: <b>150</b></div>
    </div>
        <div class="element">
        <div>Whatever</div>
        <ProgressBar ... component stuff />
        <div>Another: <b>25</b></div>
    </div>
</div>

But I am not sure how to make each element data take the same amount of space as the divs inside the other elements keeping it responsive.

Maybe for this it would be better to use tables instead?

https://jsfiddle.net/zxkqjag5/

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
lpares12
  • 3,504
  • 4
  • 24
  • 45
  • have you explored `display: flex` or `display: grid`, for me grid comes to mind first because of their "fluid rows" – Sgnl Aug 16 '22 at 17:50
  • Most simple way is to use flexbox - read about it. And, never use tables for layout – Bar Aug 16 '22 at 17:51
  • 1
    Tables CAN be used for layout if you are presenting tabular data, which this appears to be. – Paulie_D Aug 16 '22 at 17:58
  • @Sgnl How would I use flex/flexbox for this case given that the elements that I want to line up are in different blocks? – lpares12 Aug 16 '22 at 21:08

2 Answers2

1

There is no method in flexbox or CSS-Grid (that's well supported, see subgrid) to align elements in different blocks.

In this case, CSS-Tables might suffice.

.container {
  display: table;
}

.element {
  display: table-row;
}

.element div {
  display: table-cell;
  border: 1px solid red;
  padding: 0 .25em;
}
<div class="container">
  <div class="element">
    <div>Some text</div>
    <div>This would be the progress bar</div>
    <div>Another: <b>10</b></div>
  </div>
  <div class="element">
    <div>Name Number Two</div>
    <div>This would be the progress bar</div>
    <div>Another: <b>150</b></div>
  </div>
  <div class="element">
    <div>Whatever</div>
    <div>This would be the progress bar</div>
    <div>Another: <b>25</b></div>
  </div>
</div>
Paulie_D
  • 107,962
  • 13
  • 142
  • 161
  • Can I ask why not just use a `` tag in this case? Also, can this be made responsive?
    – lpares12 Aug 17 '22 at 07:23
  • You can use a table if you can change the HTML but you did not indicate that this was an option. Oh, and in what way is it not responsive? – Paulie_D Aug 17 '22 at 07:38
  • Right thanks. One more question, how can I tell the `.container` to not occupuy the whole height, just whatever the rows require? I see when I add `display: table` the size of the container grows to the full height of the page. – lpares12 Aug 18 '22 at 07:16
  • And is there any way of accomplishing this without using tables? – lpares12 Aug 18 '22 at 08:36
0

To do it without tables, we can break down each row into three sections; initial text, progress bar, and terminating text. Next, we can define how much percentage of the parent width (here, it's the row) these sections should occupy. This will ensure that the progress bars of all the rows have the same width and are starting and ending at the same points horizontally. Using flexbox, we can justify and align these sections.

Lastly, using JavaScript, we can fill the progress bars whenever the page reloads.

const rows = document.querySelectorAll(".row");
const maxProgress = 175;

rows.forEach((item, index) => {
  let value = (new Number(item.querySelector(".row-value-value").innerText) / maxProgress) * 100;
  item.querySelector(".progress-bar-progress").style.width = value + "%";
});
@import url('https://fonts.googleapis.com/css2?family=Open+Sans&display=swap');

:root {
  --progressBarHeight: 18px;
  --rowCornerRadius: 10px;
}

body {
  background-color: #EFF3F6;
  padding: 10px;
  font-family: "Open Sans", sans-serif;
}

.row:first-child {
  border-radius: var(--rowCornerRadius) var(--rowCornerRadius) 0px 0px;
}

.row:last-child {
  border-radius: 0px 0px var(--rowCornerRadius) var(--rowCornerRadius);
}

.row {
  display: flex;
  align-items: center;
  justify-content: center;
  max-width: 550px;
  width: 100%;
  padding: 0px 10px;
  background-color: #FFFFFF;
  border: 1px solid rgba(0, 0, 0, 0.5);
}

.row-text {
  margin-right: 15px;
  width: 25%;
}

.progress-bar {
  position: relative;
  width: 80%;
  height: var(--progressBarHeight);
  background-color: #D5D5D5;
  overflow: hidden;
  border-radius: 10px;
}

.progress-bar-progress {
  width: 50%;
  height: var(--progressBarHeight);
  background-color: #8C65F7;
}

.row-value {
  margin-left: 15px;
  width: 25%;
}

.row-value-value {
  font-weight: bold;
}
<div class="parent">
  <div class="row">
    <p class="row-text">Some text</p>
    <div class="progress-bar">
      <div class="progress-bar-progress"></div>
    </div>
    <p class="row-value">Another: <span class="row-value-value">10</span></p>
  </div>
  <div class="row">
    <p class="row-text">Another random text</p>
    <div class="progress-bar">
      <div class="progress-bar-progress"></div>
    </div>
    <p class="row-value">Another: <span class="row-value-value">76</span></p>
  </div>
  <div class="row">
    <p class="row-text">Name Two</p>
    <div class="progress-bar">
      <div class="progress-bar-progress"></div>
    </div>
    <p class="row-value">Another: <span class="row-value-value">150</span></p>
  </div>
  <div class="row">
    <p class="row-text">Whatever</p>
    <div class="progress-bar">
      <div class="progress-bar-progress"></div>
    </div>
    <p class="row-value">Another: <span class="row-value-value">10</span></p>
  </div>
</div>
Vaibhav
  • 562
  • 5
  • 12