I have a div that gets resized programmatically and sits inside a wrapper div. I would like the background color of the (inner) div to be a gradient, but with the gradient based on the height of the wrapper div.
For example, the gradient could be something like background: linear-gradient(0deg, green 0%, green 50%, yellow 80%, orange 90%, red 100%)
When the inner div is less than 50% of the height of the wrapper div, I want it to be completely green, but if it gets to 70%, it would start to turn yellow at the top, at 80% it starts going orange at the top and if it hit 100% it would have the full gradient. See the codepen below for an example of what I mean in terms of the colors.
The inner div will be resized every 10th of a second or so and will look similar to an audio peak meter.
Is this possible to achieve with pure CSS, or do I need to use javascript? If I use javascript, would it be more performant to have a bunch of css classes and switch them depending on percentage, or color things directly?
I could achieve this with multiple blocks, something like https://codepen.io/octod/pen/vPQLVo (not mine), but ideally I want it to be one continuous block of color with a smooth gradient.
I could also achieve it by keeping the inner div full height and resizing an overlay div, but unfortunately I have a transparent background, so this is not ideal.
EDIT: As requested, this is what I currently have that does not work (it shows the full gradient when the inner div is not the full height). I have simplified it and put css inline for this post.
real snippet: (Edited by Mister Jojos - this is not representative of my code, but the accepted answer is based on this version, so I have left it like this)
.outer {
display: inline-block;
height: 400px;
width: 40px;
background-color: dimgrey;
padding: 5px;
margin: 1em;
}
.outer > div {
width: 100%;
}
#inner50 {
height: 50%;
background: linear-gradient(0deg, green 0%, green 50%, yellow 80%, orange 90%, red 100%);
}
#inner70 { /* please set the gradient values */
height: 70%;
background: linear-gradient(0deg, green 0%, green 50%, yellow 80%, orange 90%, red 100%);
}
#inner100 { /* please set the gradient values */
height: 100%;
background: linear-gradient(0deg, green 0%, green 50%, yellow 80%, orange 90%, red 100%);
}
<!-- result in case 50% -->
<div class="outer"> <div id="inner50"></div> </div>
<!-- result in case 70% -->
<div class="outer"> <div id="inner70"></div> </div>
<!-- result in case 100% -->
<div class="outer"> <div id="inner100"></div> </div>
Javascript snippet:
// this function is called every 1/10th of a second
function updateMeter(newHeight) {
getElementById("inner").style.height = newHeight+'px';
}
Simply fix the size of the gradient to the size of the outer div:
.outer {
display: inline-block;
height: 400px;
width: 40px;
background-color: dimgrey;
padding: 5px;
margin: 1em;
}
.outer>div {
width: 100%;
background:
linear-gradient(0deg, green 0%, green 50%, yellow 80%, orange 90%, red 100%)
top/ /* place it on the top */
100% 400px; /* width=100% height=400px */
}
#inner50 {
height: 50%;
}
#inner70 {
height: 70%;
}
#inner100 {
height: 100%;
}
<!-- result in case 50% -->
<div class="outer">
<div id="inner50"></div>
</div>
<!-- result in case 70% -->
<div class="outer">
<div id="inner70"></div>
</div>
<!-- result in case 100% -->
<div class="outer">
<div id="inner100"></div>
</div>
Also like below:
.outer {
display: inline-flex;
height: 400px;
width: 40px;
background-color: dimgrey;
padding: 5px;
margin: 1em;
}
.outer>div {
width: 100%;
margin-top:auto;
background:
linear-gradient(0deg, green 0%, green 50%, yellow 80%, orange 90%, red 100%)
bottom/ /* place it on the top */
100% 400px; /* width=100% height=400px */
}
#inner50 {
height: 50%;
}
#inner70 {
height: 70%;
}
#inner100 {
height: 100%;
}
<!-- result in case 50% -->
<div class="outer">
<div id="inner50"></div>
</div>
<!-- result in case 70% -->
<div class="outer">
<div id="inner70"></div>
</div>
<!-- result in case 100% -->
<div class="outer">
<div id="inner100"></div>
</div>