5

I would like to use HTML/CSS/JS to have a <div> change its colour only up to a certain width. This certain length depends on where it is clicked inside the <div>.

Example:

Picture of what I want

I would give code, but it would just be of a <div>.
I don't know how to use CSS/JS to detect where the mouse clicks on <div> (i.e. on what width size).

Azametzin
  • 5,223
  • 12
  • 28
  • 46
user12055579
  • 694
  • 11
  • 22

4 Answers4

5

You can achieve this like this

function changeWidth(event) {
  let outerDiv = document.getElementById('outerDiv');
  document.getElementById('innerDiv').style.width = event.clientX-outerDiv.offsetLeft+'px';
}
#outerDiv {
  width: 400px;
  height:200px;
  border: 1px solid black;
}
#innerDiv {
  width: 0px;
  height: 200px;
  background-color: red;
}
<div id = 'outerDiv' onclick = 'changeWidth(event)'>
  <div id = 'innerDiv' ></div>
</div>

You have keep in check the position of the outerbox which you can get by using el.offSetLeft

Gaurav Singh
  • 369
  • 1
  • 6
3

I would do like:

//<![CDATA[
/* js/external.js */
let get, post, doc, html, bod, nav, M, I, mobile, S, Q, aC, rC, tC; // for use on other loads
addEventListener('load', ()=>{
get = (url, success, context)=>{
  const x = new XMLHttpRequest;
  const c = context || x;
  x.open('GET', url);
  x.onload = ()=>{
    if(success)success.call(c, JSON.parse(x.responseText));
  }
  x.send();
}
post = function(url, send, success, context){
  const x = new XMLHttpRequest;
  const c = context || x;
  x.open('POST', url);
  x.onload = ()=>{
    if(success)success.call(c, JSON.parse(x.responseText));
  }
  if(typeof send === 'object' && send && !(send instanceof Array)){
    if(send instanceof FormData){
      x.send(send);
    }
    else{
      const fd = new FormData;
      for(let k in send){
        fd.append(k, JSON.stringify(send[k]));
      }
      x.send(fd);
    }
  }
  else{
    throw new Error('send argument must be an Object');
  }
  return x;
}
doc = document; html = doc.documentElement; bod = doc.body; nav = navigator; M = tag=>doc.createElement(tag); I = id=>doc.getElementById(id);
mobile = nav.userAgent.match(/Mobi/i) ? true : false;
S = (selector, within)=>{
  var w = within || doc;
  return w.querySelector(selector);
}
Q = (selector, within)=>{
  var w = within || doc;
  return w.querySelectorAll(selector);
}
aC = function(){
  const a = [].slice.call(arguments), n = a.shift();
  n.classList.add(...a);
  return aC;
}
rC = function(){
  const a = [].slice.call(arguments), n = a.shift();
  n.classList.remove(...a);
  return rC;
}
tC = function(){
  const a = [].slice.call(arguments), n = a.shift();
  n.classList.toggle(...a);
  return tC;
}
// you can ignore most of the above code (but it's useful, so keep it) - put below on a separate page on another load - except the load end
const block = I('block'), colorStyle = block.firstChild.style;
let down = false;
function colorIt(e){
  if(down)colorStyle.width = e.clientX-e.target.offsetLeft+'px';
}
function touchMode(){
  block.onmousedown = block.onmousemove = undefined;
  block.ontouchstart = e=>{
    down = true; colorIt(e.touches[0]);
  }
  block.ontouchmove = e=>{
    colorIt(e.touches[0]);
  }
}
function mouseMode(){
  block.ontouchstart = block.ontouchmove = undefined;
  block.onmousedown = e=>{
    down = true; colorIt(e);
  }
  block.onmousemove = colorIt;
}
block.onclick = ()=>{
  down = false;
}
if(mobile){
  touchMode();
}
else{
  mouseMode();
}
}); // load end
//]]>
/* css/external.css */
*{
  box-sizing:border-box; padding:0; margin:0;
}
html,body{
  width:100%; height:100%; background:#ccc;
}
.main{
  padding:10px;
}
#block{
  width:200px; height:75px; background:#fff; border:1px solid #000; cursor:pointer;
}
#block>div{
  width:0; height:100%; background:green;
}
<!DOCTYPE html>
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>
  <head>
    <meta charset='UTF-8' /><meta name='viewport' content='width=device-width, height=device-height, initial-scale:1, user-scalable=no' />
    <title>Title Here</title>
    <link type='text/css' rel='stylesheet' href='css/external.css' />
    <script src='js/external.js'></script>
  </head>
<body>
  <div class='main'>
    <div id='block'><div></div></div>
  </div>
</body>
</html>
StackSlave
  • 10,613
  • 2
  • 18
  • 35
3

A simple approach using background-image to create the color.

document.querySelector(".box").addEventListener("click", function(e){
  var position = e.clientX - this.getBoundingClientRect().left;
  this.style.backgroundImage = "linear-gradient(90deg, red " + position + "px, transparent " + position + "px)";
});
.box {
  border: 2px solid #c3c3c3;
  height: 200px;
  width: 400px;
}
<div class="box"></div>

e.clientX is the position relative to the window. So you can use the left position of the div from .getBoundingClientRect().left and subtract it to get the exact click position.


If you need this to work for multiple divs:

1) Add inline onclick to each <div>

function colourBackground (e, div) {
  var position = e.clientX - div.getBoundingClientRect().left;
  div.style.backgroundImage = "linear-gradient(90deg, red " + position + "px, transparent " + position + "px)";
};
.box {
  border: 2px solid #c3c3c3;
  height: 200px;
  width: 400px;
}
<div class="box" onclick="colourBackground(event, this)"></div>
<div class="box" onclick="colourBackground(event, this)"></div>
<div class="box" onclick="colourBackground(event, this)"></div>

Or 2) Use a forEach loop to add a click event to each <div>

document.querySelectorAll(".box").forEach(function(div) {
  div.addEventListener("click", function(e){
    var position = e.clientX - div.getBoundingClientRect().left;
    div.style.backgroundImage = "linear-gradient(90deg, red " + position + "px, transparent " + position + "px)";
  });
})
.box {
  border: 2px solid #c3c3c3;
  height: 200px;
  width: 400px;
}
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
Azametzin
  • 5,223
  • 12
  • 28
  • 46
  • How does the linear gradient work? Is it the exact same thing if you had a background div and changed its width and colour to exactly red? Does the linear gradient affect the true color? – user12055579 Mar 30 '20 at 03:03
  • 1
    It is possible because `background-image` accepts [linear-gradient](https://developer.mozilla.org/en-US/docs/Web/CSS/linear-gradient) and does not interfere with the `background-color` property. So, you can use both together. – Azametzin Mar 30 '20 at 03:06
  • Also, this is only working for the first `
    ` with all with a common class.
    – user12055579 Mar 30 '20 at 03:07
  • Edited the answer with options for multple divs. – Azametzin Mar 30 '20 at 03:18
0

Interesting question.

First, use this to get the location of your div: https://stackoverflow.com/a/10445639/11444910

Then get your mouse position on click: https://stackoverflow.com/a/23744762/11444910

Now that you can tell where your div is and where your mouse is when clicked, you should be able to tell if you are clicking inside of the div or not. Then it's a matter of applying the Y location of your mouse to the div, and using that to inform the color change.

TheAmberlamps
  • 58
  • 1
  • 1
  • 6