Home > database >  How to emulate styled HTML meter with two linear-gradient backgrounds, while avoiding the gradients
How to emulate styled HTML meter with two linear-gradient backgrounds, while avoiding the gradients

Time:10-05

It seems to be damn-near impossible to style a <meter> HTML element to any interesting degree, so I am emulating a meter using CSS.

I have a step-wise gray linear gradient I want to use for the "unfilled" right-hand portion of the meter gray step gradient

background-image: linear-gradient(
  to right,
  #70f600 20%,
  #0e0 20%,
  #0e0 40%,
  #0d0 40%,
  #0d0 60%,
  #0c0 60%,
  #0c0 80%,
  #0b0 80%,
  #0b0 100%
)

and a step-wise green-ish gradient I want to use for the "filled" left-hand portion of the meter. green step gradient

background-image: linear-gradient(
  to right,
  #ddd 20%,
  #ccc 20%,
  #ccc 40%,
  #bbb 40%,
  #bbb 60%,
  #aaa 60%,
  #aaa 80%,
  #999 80%,
  #999 100%
);

The effect I want is that

  • at 0% full meter, the styled meter will be the gray step gradient alone;
  • at 100% full meter, the styled meter will be the green step gradient alone;
  • at some intermediate percent (0% < X < 100%) full meter, the leftmost X% of the styled meter will be the leftmost X% of the green step gradient, and the remaining rightmost space of the styled meter will be the corresponding rightmost space of the gray step gradient. For example:
    • at ~36% fill green and gray step gradient 36%
    • at ~82% fill green and gray step gradient 82%
  • crucially, neither step gradient should be horizontally compressed to fit into the available space.

This last bulletpoint is what I am struggling to achieve.

My current best effort is the following HTML and CSS (to produce, in this case, a 36% filled meter):

HTML

<div >
  <div  style="width: calc(100% - 36%)"/>
</div>

CSS

.meter-gauge {
  position: relative;

  display: inline-block;
  height: 1em;
  min-width: 10em;

  background-image: linear-gradient(
    to right,
    #70f600 20%,
    #0e0 20%,
    #0e0 40%,
    #0d0 40%,
    #0d0 60%,
    #0c0 60%,
    #0c0 80%,
    #0b0 80%,
    #0b0 100%
  );
}

.negative-space {
  position: absolute;
  top: 0;
  right: 0;
  
  height: inherit;
  width: 0; /* Overridden by style attribute */

  background-image: linear-gradient(
    to right,
    #ddd 20%,
    #ccc 20%,
    #ccc 40%,
    #bbb 40%,
    #bbb 60%,
    #aaa 60%,
    #aaa 80%,
    #999 80%,
    #999 100%
  );
  z-index: 1;
}

Here, unlike the desired meter styling, displayed earlier, we get a version where the gray step gradient is horizontally compressed to fit 100% of the gradient into 64% of the space. green and gray step gradient 36% incorrect

For comparison, an 82% filled meter with the above CSS looks like this, where the issue is even more obvious: green and gray step gradient 82% incorrect

How can I achieve the look I want, and avoid one of the two gradients being included in its entirety but horizontally squashed into the available space?

I have noted that the effect I want would have been possible to achieve if the two gradients were instead two image files, as demonstrated by this enter image description here

CodePudding user response:

Just have a couple of elements, or pseudo elements, with the green on top of the gray.

Green one has clip-path:

clip-path: polygon(0 0, var(—pc) 0, var(—pc) 100%, 0 100%);

Where —pc is percentage required e.g 36%

Sorry I can’t give a proper snippet as am stuck on an iOS device.

  • Related