0

Using React & Styled-Components.

How would you go about solving the following issue:

  • A progress bar, red or green background based on %, empty area is grey
  • Percentage text on the right of the progress bar (always one place)
  • Text color changes based if the red or green background overlaps it

End result should look like: half

full

What I came up with:

   export const BarContainer = styled.div`
      width: 100%;
      height: 30px;
      background: grey;
      border-radius: 16px;
    `;

    export const Bar = styled.div`
      background-color: ${props => props.background ? props.background : 'red'};
      width: ${props => (props.percent ? `${props.percent}%` : '0%')};
      height: 100%;
      transition: width 0.2s ease;
      &:before {
        color: #fff;
        font-size: 14px;
        content: ${props => (props.percent ? `'${props.percent}%'` : '0%')};
        display: block;
        text-align: right;
        mix-blend-mode: difference;
      }
    `;

... some where in the code

<BarContainer>
  <Bar percent={50} background="green" />
</BarContainer>

Issue is that mix-blend-mode: difference makes the text pink, not white on overlay. it should be white on overlay, black otherwise.

Alex
  • 1,210
  • 3
  • 21
  • 34
  • I'm not sure how to answer your question, but I wondered if you had considered the accessibility and user experience of text that has (at times) two different colours, I believe that it would be hard to read. Perhaps, you can find an alternative whereby when the green part is about to touch the text, the text gets positioned within the green part, and becomes white. Both your screenshots would look the same, only the transition between ~90% to 100% would move the percentage slightly. Not sure this is better in terms of UX though, as moving the text would be unexpected. – FMCorz Jan 30 '20 at 08:10
  • related: https://stackoverflow.com/q/50102790/8620333 – Temani Afif Jan 30 '20 at 10:40

1 Answers1

0

For your position question:

&:before {
  position: absolute;
  right: 0;
  top: 50%;
  transform: translateY(-50%); // vertical center
  width: 5em; // keep the number left aligned
  z-index: 1; // to stay above the color bar
}

For your text color changing question:

What do you mean "overlaps" it? Because if you mean the moment it starts to overlap, then you can do something like:

color: ${props => props.percent > 98 ? 'white' : 'black'};

And you can get more fancy and change the color for each letter at a time:

<div>
  <span>1</span>
  <span>0</span>
  <span>0</span>
  <span>%</span>
</div>

span {
  &:nth-child(0) {
    color: ${props => props.percent > 98 ? 'white' : 'black'};
  }
  &:nth-child(1) {
    color: ${props => props.percent > 98.1 ? 'white' : 'black'};
  }
  &:nth-child(2) {
    color: ${props => props.percent > 98.2 ? 'white' : 'black'};
  }
  &:nth-child(3) {
    color: ${props => props.percent > 98.3 ? 'white' : 'black'};
  }
}

But if you want a single character to have multiple colors at one time, you're gonna need an SVG icon for each number.

Consider GreenSock to see if it can help you out, they have some really cool features.

Mohammed Ibrahim
  • 418
  • 4
  • 11