How to modify flexbox so that one element fills up whole row

38 views Asked by At

Trying to make a progress bar (for music playback), but when width of the #progress bar is 100%, it doesn't fill up the whole container .progress-bar (as seen in photo)(Light grey part depicts whole duration). I assume this is due to flexbox, as the dot fills up part of the space, but don't know a workaround for this so that the dot stays at the end of #progress.

.progress-bar {
  display: flex;
  flex-direction: row;
  width: 50%;
  margin: 20px auto;
  background-color: #b3b3b3;
  height: 10px;
  border-radius: 10px;
}

#progress {
  background-color: #535353;
  position: relative;
  height: 100%;
  width: 100%;
  border-radius: 10px;
}

#progress-dot {
  position: relative;
  height: 25px;
  width: 25px;
  transform: translate(-12.5px, -7px);
  background-color: #000000;
  border-radius: 50%;
}
<div class="progress-bar">
  <div id="progress"></div>
  <div id="progress-dot"></div>
</div>

IMAGE https://i.stack.imgur.com/Olub3.png

2

There are 2 answers

3
Paulie_D On BEST ANSWER

The issue is that the thumb is inside of the progress container and hence space must be allowed for it in a flex container.

The transform is purely visual and does not affect actual layout.

I'd suggest "removing" it from the flow by positioning it absolutely.

.progress-bar {
  display: flex;
  flex-direction: row;
  width: 50%;
  margin: 20px auto;
  background-color: #b3b3b3;
  height: 10px;
  border-radius: 10px;
  position: relative;
}

#progress {
  background-color: #535353;
  height: 100%;
  width: 100%;
  /* equivalent to value */
  border-radius: 10px;
}

#progress-dot {
  position: absolute;
  left: 100%;
  /* equivalent to value */
  height: 25px;
  width: 25px;
  transform: translate(-50%, -7px);
  background-color: #000000;
  opacity: .25;
  border-radius: 50%;
}
<div class="progress-bar">
  <div id="progress"></div>
  <div id="progress-dot"></div>
</div>

0
isherwood On

You can position the components absolutely. You can also do this with just one element. Note that I've used a variable (custom property) to avoid value repetition.

:root {
  --progress-dot-size: 25px;
  --progress-value: 75%;
}

.progress-bar {
  display: flex;
  flex-direction: row;
  align-items: center;
  width: 50%;
  margin: 20px auto;
  background-color: #b3b3b3;
  height: 10px;
  border-radius: 10px;
  position: relative;
}

.progress-bar::before {
  content: '';
  background-color: #535353;
  position: absolute;
  height: 100%;
  width: var(--progress-value);
  border-radius: 10px;
}

.progress-bar::after {
  content: '';
  position: absolute;
  left: var(--progress-value);
  transform: translateX(calc(0px - var(--progress-dot-size) / 2));
  height: var(--progress-dot-size);
  width: var(--progress-dot-size);
  background-color: #000000;
  border-radius: 50%;
  opacity: 0.2;
}
<div class="progress-bar"></div>