How can I use CSS or JS to make a fixed background darker but keep the area around the cursor slightly lighter so it gives a flashlight type effect ? Cant seem to figure it out. Thank you.
-
What have you tried? Can you paste your code? – Josh Adams Jan 21 '18 at 02:26
-
Not managed any code yet as Im not sure if i should use some kind of mask or some kind of hover code – Scott Hunter Jan 21 '18 at 02:27
-
1On Stack Overflow, you are expected to try to **write the code yourself**. After **[doing more research](//meta.stackoverflow.com/questions/261592)** if you have a problem you can **post what you've tried** with a **clear explanation of what isn't working** and providing a **[Minimal, Complete, and Verifiable example](//stackoverflow.com/help/mcve)** within the question itself – Rob Jan 21 '18 at 02:28
-
oh ok thank you, sorry i didnt realise. – Scott Hunter Jan 21 '18 at 02:30
-
1@ScottHunter without having any attempt or starting point from you, I can't help much. Check this out though, I think it is kind of what you are going for https://codepen.io/tomhodgins/pen/egWjBb – Josh Adams Jan 21 '18 at 02:31
3 Answers
Just create an overlay using a <div>
or a pseudoelement (::before
or ::after
) and style it as your "torch" / "highlight" using CSS. I would suggest using shadows, gradients or a combination of both, depending on the desired result.
Then, with JS, you can keep track of the cursor's position and move that overlay around following it or change its CSS properties' values (maybe using CSS variables, depending on your browser support needs), depending on your implementation.
If you go for the former, ideally you should be using window.requestAnimationFrame()
in order to get smoother transitions without harming performance.
Try to implement that yourself and, if you have issues with the implementation, come back and create another question with that specific issue. As some have pointed out in the comments, we are not supposed to write the code for you, especially when you haven't tried before (or at least you have not provided any evidence about it).
EDIT:
As it's been a few days since this question was created, I guess it's fine to post a working solution now, as I was curious myself to know how realistic this effect could be using just CSS.
@LambdaNinja's solution is a good starting point, but that doesn't look like a real torch.
The Pen @JoshAdams posted in a comment gets closer, but there's still room for improvement.
I have used window.requestAnimationFrame
, CSS variables, background-blend-mode
and CSS animations.
const W = window.innerWidth;
const H = window.innerHeight
function updateAnimationTiming() {
const animationDuration = 5 + Math.random() * 5; // [5 - 10)
const animationDelay = 5 + Math.random() * 10; // [5 - 15)
window.requestAnimationFrame(() => {
document.documentElement.style.setProperty('--animationDuration', animationDuration + 's');
document.documentElement.style.setProperty('--animationDelay', animationDelay + 's');
});
const timeout = (animationDuration + animationDelay) * 1000 - 100;
setTimeout(updateAnimationTiming, timeout);
}
updateAnimationTiming();
document.addEventListener('mousemove', e => {
window.requestAnimationFrame(() => {
const X = e.clientX;
const Y = e.clientY;
document.documentElement.style.setProperty('--cursorX', X + 'px');
document.documentElement.style.setProperty('--cursorY', Y + 'px');
const X2 = X - (12 * W / 100) * (X / W - 0.5);
const Y2 = Y - (12 * W / 100) * (Y / H - 0.5);
document.documentElement.style.setProperty('--cursorX2', X2 + 'px');
document.documentElement.style.setProperty('--cursorY2', Y2 + 'px');
});
});
:root {
cursor: crosshair;
--cursorX: 50vw;
--cursorY: 50vh;
--cursorX2: 50vw;
--cursorY2: 50vh;
--animationDuration: 10s;
--animationDelay: 15s;
}
:root:before {
content: '';
position: fixed;
display: block;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-blend-mode: normal, overlay;
background-position: center center;
background-size: auto, auto, cover;
background-image:
radial-gradient(
circle 16vmax at var(--cursorX2) var(--cursorY2),
rgba(0,0,0,0) 30%,
rgba(0,5,5,.1) 40%,
rgba(5,5,0,.5) 60%,
rgba(0,0,0,.75) 70%,
rgba(0,0,0,.95) 100%
),
radial-gradient(
circle 12vmax at var(--cursorX) var(--cursorY),
rgba(255,255,255,1) 30%,
rgba(255,255,255,.3) 50%,
rgba(255,255,255,.05) 100%
),
url(https://handluggageonly.co.uk/wp-content/uploads/2016/01/Sewers-of-Paris-2.jpg);
animation: torch var(--animationDuration) linear var(--animationDelay) infinite alternate;
}
@keyframes torch {
0%, 1%, 2%, 3%, 4%, 5%, 20%, 21%, 60%, 61%, 62%, 100% { background-image:
radial-gradient(
circle 16vmax at var(--cursorX2) var(--cursorY2),
rgba(0,0,0,0) 30%,
rgba(0,5,5,.1) 40%,
rgba(5,5,0,.5) 60%,
rgba(0,0,0,.75) 70%,
rgba(0,0,0,.95) 100%
),
radial-gradient(
circle 12vmax at var(--cursorX) var(--cursorY),
rgba(255,255,255,1) 30%,
rgba(255,255,255,.3) 50%,
rgba(255,255,255,.05) 100%
),
url(https://handluggageonly.co.uk/wp-content/uploads/2016/01/Sewers-of-Paris-2.jpg);
}
0.5%, 1.5%, 60.5% { background-image:
radial-gradient(
circle 12vmax at var(--cursorX2) var(--cursorY2),
rgba(0,0,0,0) 30%,
rgba(0,5,5,.1) 40%,
rgba(5,5,0,.5) 60%,
rgba(0,0,0,.75) 70%,
rgba(0,0,0,.95) 100%
),
radial-gradient(
circle 8vmax at var(--cursorX) var(--cursorY),
rgba(255,255,255,1) 30%,
rgba(255,255,255,.3) 50%,
rgba(255,255,255,.05) 100%
),
url(https://handluggageonly.co.uk/wp-content/uploads/2016/01/Sewers-of-Paris-2.jpg);
}
2.5%, 3.5%, 4.5%, 20.5%, 61.5% { background-image:
radial-gradient(
circle 8vmax at var(--cursorX) var(--cursorY),
rgba(0,0,0,0) 30%,
rgba(0,5,5,.1) 40%,
rgba(5,5,0,.5) 60%,
rgba(0,0,0,.75) 70%,
rgba(0,0,0,.95) 100%
),
radial-gradient(
circle 4vmax at var(--cursorX) var(--cursorY),
rgba(255,255,255,1) 0%,
rgba(255,255,255,.5) 50%,
rgba(255,255,255,.05) 100%
),
url(https://handluggageonly.co.uk/wp-content/uploads/2016/01/Sewers-of-Paris-2.jpg);
}
}
You can also access it here: https://codepen.io/Danziger/pen/VyOZpy
Keep in mind it has some limitations though, as the overlay will cover all the page, so the effect is limited to the background image and different gradients added to it.
Even if you replace the pseudoelement with a <div>
and add content in it, that content will not be affected by the blend mode.
However, it might be possible to achieve that using mix-blend-mode
. You can check out the cursor on my website, which also uses animations/transitions between its different shapes or states and mix-blend-mode
so that the cursor blends with any element on the page, not just with the background of one specific element:
Check it out here: https://gmzcodes.com/.
Check the code here: https://github.com/Danziger/gmzcodes
Lastly, here you can see another answer with a simpler custom cursor that might be all you need in most cases and might help you understand how to do it: CSS - Custom cursor that changes depending on hovered element flickers when moving left to right but not right to left

- 19,628
- 4
- 53
- 83
-
Please don't answer off topic questions. It only encourages them. Not all questions can or should be answered. – Rob Jan 21 '18 at 02:35
-
@Rob I think if the answer is non-trivial, and this one might not be, depending on one's experience, it's ok to provide some guidance on possible implementations, as long as we don't code it for them, the same way it is ok to suggest possible improvements on questions about performance, which are less likely to get a specific answer. Anyway, someone already has... – Danziger Jan 21 '18 at 02:41
-
He is asking for code and the question is off topic. It will be closed for that reason. – Rob Jan 21 '18 at 02:42
edit: as @Rob has said below, always try to answer questions on your own first. This is merely an implementation suggestion and should not be copied mindlessly.
I think you can create a CSS element with a radial gradient that you keep under your mouse with JS.
window.onload = function() {
var flashlight = document.querySelector('#flashlight');
window.addEventListener('mousemove', function(event) {
flashlight.style.left = (event.pageX-25) + 'px';
flashlight.style.top = (event.pageY-25) + 'px';
});
};
body, html {
margin: 0;
padding: 0;
background-image: url('https://scontent-lga3-1.xx.fbcdn.net/v/t1.0-9/12140762_1159067420823544_4471328164031495581_n.jpg?oh=78a75ea8fe74295d8087eff97dbcef5a&oe=5AF0967D');
background-size: cover;
height: 100%;
}
#mask {
position: absolute;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
}
#flashlight {
height: 50px;
width: 50px;
position: absolute;
background-image: radial-gradient(white 0%, transparent 50%);
}
<!-- darken background -->
<div id='mask'></div>
<!-- flashlight effect -->
<div id='flashlight'></div>

- 16,831
- 17
- 68
- 94
-
-
@Rob What image? The background is dark, and the cursor should have a flashlight-type effect, correct? – Jonathan Lam Jan 21 '18 at 02:41
-
-
@Rob I guess I read that wrong. That should be simple with a partially-transparent div over the image. I'll edit that in. – Jonathan Lam Jan 21 '18 at 02:43
-
Don't waste your time. The question is off topic and will be closed. You shouldn't be writing code. Stack Overflow is not a code writing service. – Rob Jan 21 '18 at 02:43
-
@Rob I realized that after I posted, but it seemed fun to implement what he asked at first glance. – Jonathan Lam Jan 21 '18 at 02:44
-
It only encourages others to break SO's policy and rules which state such question shouldn't even be answered at all. – Rob Jan 21 '18 at 02:45
There aren’t many options using only CSS. You can check out this link where they detail all the types of cursors you can use. But those are not relevant to your use case as it’s just changing the icon.
You might need to look into a JS solution to track the cursor position. Check out this StackOverflow answer.
After you know where the cursor is, you can create a div:
#cursor-background {
border-radius: 50%;
height: 20px;
width: 20px;
position: absolute;
background-color: rgba(255, 255, 255, 0.2);
}
You can then try and change the position of this div using:
document.getElementById("cursor-background").style.transform = "translate(“ + X + “,” + Y + “)";
Where X and Y are your desired position on the screen.
To avoid it looking jumpy, add a transition property in the CSS of “cursor-background”:
transition: all 0.1s ease-in-out;
I haven’t tested any of this out, just trying to provide guidance as to which direction you should take.
As for the background, make it whichever color you want it to be. The flashlight effect will come from the light div hovering over your dark background.

- 134
- 1
- 6