CSS Conditional Formatting with a colour range - html

I am looking to create a basic chart using divs and spans and want to apply conditional formatting to each column in the chart depending on the value setting its height. The trick which I haven't been able to crack is that I want to have it function a bit like Excel conditional formatting in the example here:
Where the colours are in a range (light to dark).
Is there a simple way of doing this? I can see how I could apply static values to static colours but was hoping I could do something with colour ranges like this excel example.
So, the below screenshot shows a column chart where each column has a different shade of orange determined by the value of the column:
The closer to 25 the column is, the darker the colour.. Like-wise, the lower the value, the lighter the shade of orange is.

It sounds like your goal is to color a bar somewhere between two colors depending on a value. If that's the case, you can use css animations to simulate the color gradient.
The idea is this:
Set up an animation setting the background to be one of two colors. This effectively calculates a gradient between the two colors. You do this with #keyframes and animation.
Pause the animation, since we don't want it to actually play. This is done with animation-play-state.
Select a specific frame in the animation to get the correct in-between color. This can be done with a negative animation-delay.
.bars {
display: flex;
justify-content: space-evenly;
}
.bar {
animation: color-gradient 25s linear 1;
animation-fill-mode: forwards;
animation-play-state: paused;
width: 3em;
}
#keyframes color-gradient {
from { background: red; }
to { background: blue; }
}
<div class="bars">
<div class="bar" style="height: 5em; animation-delay: -5s;"></div>
<div class="bar" style="height: 10em; animation-delay: -10s;"></div>
<div class="bar" style="height: 15em; animation-delay: -15s;"></div>
<div class="bar" style="height: 20em; animation-delay: -20s;"></div>
<div class="bar" style="height: 25em; animation-delay: -25s;"></div>
</div>
The granularity can be adjusted by making the animation duration longer than 25 seconds if need be.

I am going to provide two options and maybe you can provide some more details based on these on exactly what you need.
This first one may not be what you want as it sets a specific gradient based on a specific height. Only going to provide a Codepen for this one. https://codepen.io/jfirestorm44/pen/yLMNPPM?editors=1100
This next one is more of what I think you want. If you know the max height of the bar graph you can use that to set the gradient breaks on your linear-gradient.
UPDATED:
HTML
<div id="container">
<div id="first" class="bar"></div>
<div id="second" class="bar"></div>
<div id="third" class="bar"></div>
<div id="fourth" class="bar"></div>
<div id="fifth" class="bar"></div>
</div>
SCSS
.bar {
#for $i from 1 through 5 {
$height: 20px * $i;
$light: 75% + $i * -5;
&:nth-child(#{$i}) {
position: absolute;
bottom: 50%;
left: 20% + ($i * 10%);
width: 20px;
height: $height;
font-size: 25px;
transform: translate(-80%, 0);
background: hsl(35, 100%, $light);
}
}
}
Updated Codepen: https://codepen.io/jfirestorm44/pen/jOBPopj?editors=1100
ADDING a JS Option:
let inputNum = document.getElementById("number");
let button1 = document.getElementById("button1");
let border = document.getElementById("border");
let dropDown = document.getElementById("cars");
function color() {
if (inputNum.value > 0) {
let bar = document.createElement("div");
bar.classList.add("bar");
border.appendChild(bar);
let bars = document.getElementsByClassName("bar");
let carName = document.createElement("p");
carName.classList.add("carType");
carName.textContent = cars.options[cars.selectedIndex].text;
border.appendChild(carName);
let names = document.getElementsByClassName("carType");
let height = inputNum.value * 26;
for (let i = 0; i < bars.length; i++) {
names[names.length - 1].style.top = "275px";
names[names.length - 1].style.left = -5 + i * 30 + "px";
bars[bars.length - 1].style.height = height + "px";
bars[bars.length - 1].style.backgroundColor =
"hsl(35, 100%," + (75 - height / 5.2) + "%)";
bars[bars.length - 1].style.left = 10 + i * 30 + "px";
}
}
}
#container {
position: absolute;
top: 40px;
left: 0;
width: 400px;
height: 300px;
}
#border {
position: relative;
left: 100%;
top: 0;
width: 90%;
height: 90%;
border-left: 2px solid grey;
border-bottom: 2px solid grey;
transform: translate(-100%, 0);
}
#numberContainer {
position: relative;
left: -5%;
}
.num {
line-height: 10px;
}
.num:before {
content: "";
position: absolute;
left: 18px;
width: 100%;
height: 10px;
border-bottom: 1px lightgrey solid;
}
.bar {
position: absolute;
bottom: 0;
width: 20px;
}
#button1 {
position: relative;
top: 0;
width: 60px;
height: 20px;
}
.car {
position: absolute;
top: 10px;
}
.carType {
position: absolute;
bottom: -85px;
writing-mode: vertical-rl;
text-orientation: upright;
}
<div id="container">
<div id="border">
<div id="numberContainer">
<p class="num">10</p>
<p class="num">9</p>
<p class="num">8</p>
<p class="num">7</p>
<p class="num">6</p>
<p class="num">5</p>
<p class="num">4</p>
<p class="num">3</p>
<p class="num">2</p>
<p class="num">1</p>
<p class="num">0</p>
</div>
</div>
</div>
<input type="number" min="0" max="10" value="0" id="number"/>
<label for="cars">Choose a car:</label>
<select name="cars" id="cars">
<option value="volvo">Volvo</option>
<option value="saab">Saab</option>
<option value="mercedes">Mercedes</option>
<option value="audi">Audi</option>
</select>
<button type="button" onclick="color()" id="button1">Submit</button>

[edit] This answer only colors the bars from left to right, having the lightest color to the left.
I would let the container have a white background and the bars to be black, and then add a gradient over everything, with help of a pseudo-element that have set mixed-blend-mode: lighten to only colorize the black bars.
As a bonus, I added another pseudo-element with a repeating linear gradient consisting of a really light grey to create the horizontal lines. I then added mixed-blend-mode: darken to this element to make them appear "under" the bars.
I also randomized the height of the bars, by randomizing a CSS property for each bar.
This solution scales, so it doesn't matter how many bars you got, you still get a gradient over all the of bars without having to change the CSS code.
let bars = document.querySelectorAll('.bar');
function randomize(max, min) {
min = min || 0;
return Math.floor(Math.random() * (max - min) + min);
}
for (const bar of bars) {
bar.style.setProperty('--bar-height', `${randomize(10, 2)}rem`);
}
.container {
position: relative;
display: inline-flex;
margin-left: 4.5rem;
align-items: flex-end;
background-color: #fff;
padding: 0px 1rem;
}
.container::before,
.container::after {
content: '';
position: absolute;
top: 0px;
bottom: 0px;
left: 0px;
right: 0px;
}
.container::before {
background: linear-gradient(to right, #fbe5d6, #843c0c);
mix-blend-mode: lighten;
}
.container::after {
background: repeating-linear-gradient(to top, #f4f1f1, #f4f1f1 1px, transparent 1px, transparent 1rem);
z-index: 10;
mix-blend-mode: darken;
}
.bar {
width: 1.5rem;
height: var(--bar-height);
background-color: #000;
}
.bar + .bar {
margin-left: 3rem;
}
<div class="container">
<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>
</div>

Using a combination of my and Justin's answers, but for vanilla CSS.
This answer is using HSL and CSS variables to set the color and the height.
Randomized values
let bars = document.querySelectorAll('.bar');
function randomize(max, min) {
min = min || 0;
return Math.floor(Math.random() * (max - min) + min);
}
for (const bar of bars) {
let maxValue = 25;
let randomValue = randomize(maxValue, 2);
let height = randomValue/2;
let hue = '24deg';
let saturation = '82%';
let maxHue = 90;
let minHue = 30;
let hueRange = maxHue - minHue;
let lightness = `${maxHue - hueRange * (randomValue/maxValue)}%`;
bar.style.setProperty('--bar-height', `${height}rem`);
bar.style.setProperty('--color-background-bar', `hsl(${hue}, ${saturation}, ${lightness})`);
}
.container {
display: inline-flex;
margin-left: 4.5rem;
align-items: flex-end;
padding: 0px 1rem;
background: repeating-linear-gradient(to top, #eee, #eee 1px, transparent 1px, transparent 1rem);
}
.bar {
width: 1.5rem;
height: var(--bar-height);
background-color: var(--color-background-bar);
}
.bar + .bar {
margin-left: 3rem;
}
<div class="container">
<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>
</div>
Increasing values
Static values ranging from 5 to 25, as seen in the OP's pic.
let bars = document.querySelectorAll('.bar');
bars.forEach((bar, index) => {
let maxValue = 25;
let customValue = 5 + index * 5;
let height = customValue/2;
let hue = '24deg';
let saturation = '82%';
let maxHue = 90;
let minHue = 30;
let hueRange = maxHue - minHue;
let lightness = `${maxHue - hueRange * (customValue/maxValue)}%`;
bar.style.setProperty('--bar-height', `${height}rem`);
bar.style.setProperty('--color-background-bar', `hsl(${hue}, ${saturation}, ${lightness})`);
});
.container {
display: inline-flex;
margin-left: 4.5rem;
align-items: flex-end;
padding: 0px 1rem;
background: repeating-linear-gradient(to top, #eee, #eee 1px, transparent 1px, transparent 1rem);
}
.bar {
width: 1.5rem;
height: var(--bar-height);
background-color: var(--color-background-bar);
}
.bar + .bar {
margin-left: 3rem;
}
<div class="container">
<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>
</div>

Related

I want to customize the color of the meter tag

I would like to make a meter like the following image.
I want to change the color of the Meter tag to red for the part where the value over 75 area only.
(If value is over 75, everything turns red. I want to keep blue and red area)
Ideal meter
My meter
React.js
<div className="climate_icon_and_slider_section">
<div className='ic_thermometer_and_meter'>
<img className="ic_thermometer_for_detail_page" src= {ic_thermometer_for_detail_page} />
<meter max="95" min="45" high="75" value={temperature_value}></meter>
</div>
<div className="range-container-climate">
<input className="range-input" type="range" name="speed" min="45" max="95"
value={temperature_value} onChange={handleSliderChange}></input>
</div>
</div>
CSS
.ic_thermometer_and_meter {
position: relative;
}
.ic_thermometer_for_detail_page {
height: 300px;
margin-right: 100px;
z-index: 10;
position: absolute;
top: -140px;
right: -100px;
}
meter {
width: 265px;
height: 98px;
transform:rotate(-90deg);
position: absolute;
top: -40px;
right: -83px;
z-index: 7;
}
meter::-webkit-meter-bar {background: gray;} /*background color of bar*/
meter::-webkit-meter-optimum-value {background: #0D76BE;}
meter::-webkit-meter-suboptimum-value{background:red;}
meter::-webkit-meter-bar {background: gray;} /*background color of bar*/
meter::-webkit-meter-optimum-value {background: #0D76BE;}
meter::-webkit-meter-suboptimum-value{background: linear-gradient(to right, #0D76BE 159px, red 159px)};
works!

Background larger than its container

I am trying to achieve this layout but I'm having problems with setting a background, which should be 50% of the screen size. I thought of setting up an image as background, but there are different colors that should be different on each page.
Is it possible to achieve it using only background-color?
This is how I set the HTML, TS & CSS so far:
<div [class]="getBackground(title)">
<div class="background-header">
<img [src]="'assets/assess/Custom.png'" alt="">
{{title}}
</div>
<div class="swiper-container">
<div class="swiper-wrapper">
<div class="swiper-slide" *ngFor="let theme of pillar.data; let i = index">
<button rh-btn-theme full-btn [ngClass]="{'ripple': true}" [issue]="theme" (click)="presentModal($event, theme);"></button>
</div>
</div>
</div>
</div>
TS
getBackground(pillar) {
switch (pillar) {
case "People":
return "background-people";
case "Land":
return "background-land";
case "Crop":
return "background-crop";
case "Business":
return "background-business";
default:
return "background-custom";
}
}
CSS
.background-header {
width: 100%;
height: 80%;
display: block;
position: relative;
img {
display: inherit;
background-color: #000;
}
}
.background-people {
background-color: #335F6E;
}
.background-land {
background-color: #006533;
}
.background-crop {
background-color: #7F4020;
}
.background-business {
background-color: #F8DC0B;
}
.background-custom {
background-color: map-get($colors, primary);
}
Yes you can do it by background gradient:
.content {
width: 100%;
height: 300px;
border: solid 2px #123;
background: linear-gradient( red, red 50%, white 50%, white);
}
<div class='content'></div>
Dont forget genarte cross-browser css. See about background gradient here

Basic vertical center in CSS behaving strangely on floated element

So i've come to live by these 3 CSS rules that almost always vertically center any block level element:
.vertically-center {
position: relative;
top: 50%;
transform: translateY( -50% );
}
It works often. But in the case of this particular layout I'm building it is pushing the elements too high ( partially off the screen ) and I don't know why.
This is how the webpage looks before adding my vertically-center class to my portrait-container div:
And this code snippet is how it appears after adding the vertically-center class to the portrait-container div:
.clearfix:after {
content: "";
display: block;
clear: both;
}
.vertically-center {
position: relative;
top: 50%;
transform: translateY( -50% );
}
body {
overflow: hidden;
}
main {
padding-top: 50px;
background: #fafafa;
text-align: left;
}
.portrait-container {
float: left;
}
img {
width: 150px;
border-radius: 50%;
}
.about-container {
width: 70%;
float: right;
}
<main class="clearfix">
<div class="portrait-container vertically-center">
<img src="http://i.imgur.com/Eb5sRZr.jpg" alt="Portrait of John Lesko">
</div>
<div class="about-container">
<h3>About</h3>
<p>
Hi, I'm John Lesko! This is my art portfolio where I share all
of my favorite work. When I'm not creating things, I enjoy excercising,
playing video games, drinking good Kool Aid, and more.
<br><br> If you'd like to follow me on Twitter, my username is
#jletsgo.
</p>
</div>
</main>
I just want the image container to be vertically-centered regardless of the height of it's parent. Help? Inspecting elements gave me no insights.
Edit: Just to show how this has always worked for me in the past. Here is a jsfiddle: https://jsfiddle.net/9kyjt8ze/4/. Why does it work for me there and not here?
Related question: What does top: 50%; actually do on relatively positioned elements?
Your CSS was not bad but I didn't get along with it. So here is another approach on how you could solve it, maybe it helps also. It will always center the image vertically and does not matter how much text the box on the right will have. The colored borders are just there to help show the visual effect of the box sizes.
* {
box-sizing: border-box;
}
.portrait-container {
position: relative;
margin: 20px 0;
}
.portrait-container:after {
content: '';
display: block;
clear: both;
}
.portrait-container img {
position: absolute;
top: calc(50% - 80px); /* 50% from top minus half img height*/
width: 150px;
height: 160px;
border-radius: 50%;
float: left;
}
.portrait-container {
border: solid 2px orange;
}
.portrait-container .about-container {
border: solid 2px green;
padding: 0 50px;
margin-left: 150px; /* this elements should be at least 150px away from left side */
width: calc(100% - 150px); /* the max width this element should have to be placed */
/* next to the image is the total width(100%) - the image width */
}
<main>
<div class="portrait-container">
<img src="http://i.imgur.com/Eb5sRZr.jpg" alt="Portrait of John Lesko">
<div class="about-container">
<h3>About</h3>
<p>
Hi, I'm John Lesko! This is my art portfolio where I share all
of my favorite work. When I'm not creating things, I enjoy excercising,
playing video games, drinking good fruit punch, and more.
<br><br> If you'd like to follow me on Twitter, my username is
#jletsgo.
</p>
</div>
</div>
</main>
<main>
<div class="portrait-container">
<img src="http://i.imgur.com/Eb5sRZr.jpg" alt="Portrait of John Lesko">
<div class="about-container">
<h3>About</h3>
<p>
Hi, I'm John Lesko! This is my art portfolio where I share all
of my favorite work. When I'm not creating things, I enjoy excercising,
playing video games, drinking good fruit punch, and more.
<br><br> If you'd like to follow me on Twitter, my username is
#jletsgo.
</p>
<p>
Hi, I'm John Lesko! This is my art portfolio where I share all
of my favorite work. When I'm not creating things, I enjoy excercising,
playing video games, drinking good fruit punch, and more.
<br><br> If you'd like to follow me on Twitter, my username is
#jletsgo.
</p>
</div>
</div>
</main>
UPDATE
Edit: Just to show how this has always worked for me in the past. Here is a jsfiddle: https://jsfiddle.net/9kyjt8ze/4/. Why does it work for me there and not here?
The black circle is the only element there in the Fiddle, there's no obstructions. In the code you are having trouble with, you have many elements either in the way or wrapped around other elements trapping them. Your ruleset will work if you start stripping away the layers. Or you can just add a property and change another property as per Snippet 1.
One important note a relative element is actually occupying the original spot, so if given a left:40px it appears to be moved 40px to the left, but in reality it still occupies the space 40px to the right of where it appears to be. So relative elements are not really in a flow different from static elements. Therefore they are affected by and affect static layout, it's just not noticeable normally because they stack with z-index.
Snippet 2 is an interactive demo, I figured maybe that'll help explain things better.
The 3 CSS ruleset is a common way to vertically align elements, but it was originally position: absolute instead of position:relative and it had to be in another positioned element if I remember correctly.
REFERENCE
Specific Ruleset
W3Schools
MDN
SOLUTION
.vertically-center {
/* Changed to absolute from relative */
position: absolute;
top: 50%;
transform: translateY( -50% );
}
main {
/* Added position: relative */
position: relative;
padding-top: 50px;
background: #fafafa;
text-align: left;
}
SNIPPET 1
.vertically-center {
position: relative;
top: 50%;
transform: translateY( -50%);
}
body {}
main {
padding-top: 50px;
overflow: scroll;
background: #fafafa;
text-align: left;
}
img {
width: 150px;
border-radius: 50%;
float: left;
}
.about {
width: calc(100% - 150px);
float: right;
}
<main class="clearfix">
<img src="http://i.imgur.com/Eb5sRZr.jpg" alt="Portrait of John Lesko" class="vertically-center">
<article class="vertically-center about">
<h3>About</h3>
<p>
Hi, I'm John Lesko! This is my art portfolio where I share all of my favorite work. When I'm not creating things, I enjoy excercising, playing video games, drinking good Kool Aid, and more.</p>
<p>If you'd like to follow me on Twitter, my username is
#jletsgo.
</p>
</article>
</main>
SNIPPET 2
$('#b1').click(function() {
$('body').toggleClass('R S');
});
$('#b2').click(function() {
$('#N1,#N2,#N3').toggleClass('N M');
});
$('input[id$="2"]').on('input', function() {
var grp = "." + $(this).attr('class');
var num = parseInt($(this).val(), 10);
grp !== '.S' ? $('section' + grp).css('left', num + '%') : $('section.S').css('margin-left', num + '%');
});
$('input[id$="3"]').on('input', function() {
var grp = "." + $(this).attr('class');
var num = parseInt($(this).val(), 10);
grp !== '.S' ? $('section' + grp).css('top', num + '%') : $('section.S').css('margin-top', num + '%');
});
html,
body {
height: 100%;
width: 100%;
}
body {
overflow: scroll;
font: 400 12px/1.2 Consolas;
}
section {
width: 50px;
height: 150px;
border: 2px dashed grey;
text-align: center;
color: white;
}
.R {
position: relative;
background: rgba(0, 0, 255, .3)
}
.A {
position: absolute;
background: rgba(255, 0, 0, .3)
}
.F {
position: fixed;
background: rgba(0, 255, 0, .3)
}
.S {
position: static;
background: rgba(122, 122, 0, .3)
}
.N {
position: absolute;
background: yellow;
color: blue;
}
.M {
position: relative;
background: black;
color: yellow;
}
#R1 {
left: 20%;
top: 3%;
z-index: 1;
}
#A1 {
left: 42%;
top: 44%;
z-index: 2;
}
#F1 {
right: 20%;
top: 44%;
z-index: 3;
}
#S1 {
margin-left: 0;
margin-top: -28%;
}
#N1 {
bottom: 0;
right: 0;
width: 25px;
height: 80px;
z-index: 4;
}
input {
width: 6ex;
position: static !important;
}
button {
font: inherit;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body class='S'>
<fieldset>
<button id='b1'>Body Relative/Static</button>
<button id='b2'>Nested Absolute/Relative</button>
<br><br> RLeft
<input id='R2' class='R' type='number' value='20'> RTop
<input id='R3' class='R' type='number' value='3'> ALeft
<input id='A2' class='A' type='number' value='44'> ATop
<input id='A3' class='A' type='number' value='44'><br> FLeft
<input id='F2' class='F' type='number' value='64'> FTop
<input id='F3' class='F' type='number' value='44'> SLeft
<input id='S2' class='S' type='number' value='0'> STop
<input id='S3' class='S' type='number' value='-28'><br> NLeft
<input id='N2' class='N' type='number' value='45'> NTop
<input id='N3' class='N' type='number' value='45'>
</fieldset>
<section id='R1' class='R'>RELATIVE
<section id='N1' class='N'>N<br>E<br>S<br>T<br>E<br>D</section>
</section>
<section id='A1' class='A'><br><br><br>ABSOLUTE</section>
<section id='F1' class='F'><br><br>FIXED</section>
<section id='S1' class='S'><br><br><br><br><br>STATIC</section>
</body>
You can achieve this by using flexboxwith a lot less code. The below code will do the trick.
.clearfix {
display: flex;
align-items: center;
}
img {
width: 150px;
border-radius: 50%;
}
.about-container {
width: 70%;
padding-left: 30px;
}
Check it out in codepen http://codepen.io/anon/pen/OWYxrb

How to make two-coloured stripe using CSS?

I want to make the following stripe. What is the right way of doing that?
Looks like you are looking for gradients. This is typically used when you want to style with multiple colors.
Gradients are displayed by default vertically. To display it horizontally, we need to use the optional direction parameter. In this case, it is to right.
I can't make out what the colors used in the image are, but they look like darkgreen and lime.
#colored {
background: linear-gradient(to right, DarkGreen 70%, lime);
width: 100%;
height: 50px;
}
<div id="colored"></div>
Alternately, you can use a gradient:
var progress = document.getElementById('progress');
var complete = 0;
var c1 = '#75ae2c', c2 = '#9dd156';
var timer = setTimeout(function loop() {
var bg = 'linear-gradient(to right, ' + c1 + ' 0%,' + c1 + ' ' + complete + '%,' + c2 + ' ' + complete + '%,' + c2 + ' 100%)';
progress.style.background = bg;
progress.innerHTML = 'Process is ' + complete + '% complete';
complete++;
if (complete <= 100) setTimeout(loop, 100);
}, 0);
#progress {
padding: 10px;
width: 200px;
text-align: center;
}
<div id="progress">
</div>
It is a tiny bit more complex, but the advantage over div-inside-div is that it doesn't interfere with the content.
All you need is a short div with darker color inside another with lighter color.
That's how Bootstrap implement its progress bar.
HTML:
<div class="progress">
<div class="progress-bar" role="progressbar" aria-valuenow="70" aria-valuemin="0" aria-valuemax="100" style="width:70%">
<span class="sr-only">70% Complete</span>
</div>
</div>
CSS:
.progress {
height: 20px;
margin-bottom: 20px;
overflow: hidden;
background-color: #f5f5f5;
border-radius: 4px;
-webkit-box-shadow: inset 0 1px 2px rgba(0,0,0,.1);
box-shadow: inset 0 1px 2px rgba(0,0,0,.1);
}
Have a div with 2 div's inside
HTML:
<div class="stripe">
<div class="stripe-left"></div>
<div class="stripe-right"></div>
</div>
CSS
.stripe {
height: 20px;
width: 200px;
}
.stripe-left {
display: inline-block;
height: 100%;
width: 60%;
background-color: red;
}
.stripe-right {
display: inline-block;
height: 100%;
width: 40%;
background-color: blue;
}

Draw vertical line on top of image

I've written a small Soundcloud player for my blog. I just added the possibility to skip in time when clicking inside the waveform. Now I'd like to draw a line at the current position in the track and a text indicating the curren position in time.
How would I draw this on top of my waveform (which is an <img>-tag) and which elements would I use?
You can do something like this. Absolutely positioned element (it doesn't really matter what element you choose - divs seem to be the best logical choice for me) to appear on top of the image, and easily scrollable. You denote the bar position using the left property. For your image, it goes between 48px and 358px. See here:
function play() {
document.getElementById('pos').className = 'end';
}
#c {
position: relative;
}
#pos {
height: 50px;
width: 1px;
position: absolute;
left: 48px;
top: 1px;
background: red;
transition: left 5s linear;
}
#pos.end {
left: 358px;
}
<div id="c">
<div id="pos"></div>
<img src="http://i.stack.imgur.com/LUNV8.png" />
</div>
<button onclick="play()">Play</button>
And combining it with your existing waveform listener is also easy:
var pos = document.getElementById('pos');
var wave = document.getElementById('wave');
wave.addEventListener('click', function(e) {
if (e.offsetX < 48)
return;
pos.style.left = e.offsetX + 'px';
});
#c {
position: relative;
}
#pos {
height: 50px;
width: 1px;
position: absolute;
left: 48px;
top: 1px;
background: red;
}
<div id="c">
<div id="pos"></div>
<img id="wave" src="http://i.stack.imgur.com/LUNV8.png" />
</div>