Effet de lueur au curseur avec setProperty
HTML
index.html <form>
<label for="sat">Saturation</label>
<input id="sat" type="range" min="0" max="100" value="30" step="0.1"/>
<label for="alp">Alpha</label>
<input id="alp" type="range" min="0" max="100" value="100" step="0.1"/>
<label for="lig">Lightning</label>
<input id="lig" type="range" min="0" max="100" value="30" step="0.1"/>
</form>
<div class="features">
<div class="feature" style="--hue:0"><a class="feature-content" href="#"><strong>Title card</strong><span>Description of my card</span></a></div>
<div class="feature" style="--hue:60"><a class="feature-content" href="#"><strong>Title card</strong><span>Description of my card</span></a></div>
<div class="feature" style="--hue:120"><a class="feature-content" href="#"><strong>Title card</strong><span>Description of my card</span></a></div>
<div class="feature" style="--hue:180"><a class="feature-content" href="#"><strong>Title card</strong><span>Description of my card</span></a></div>
<div class="feature" style="--hue:240"><a class="feature-content" href="#"><strong>Title card</strong><span>Description of my card</span></a></div>
<div class="feature" style="--hue:300"><a class="feature-content" href="#"><strong>Title card</strong><span>Description of my card</span></a></div>
</div>
CSS
style.css @layer demo {
.features {
width: 75vw;
height: 50vh;
display: grid;
gap: 1rem;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(2, 1fr);
.feature {
--x-px: calc(var(--x) * 1px);
--y-px: calc(var(--y) * 1px);
--border: 1px;
--color: var(--hue, 0deg) var(--sat, 28%) var(--lig, 46%);
--hsla-color: hsla(var(--color) / var(--alp, 100%));
background: rgba(255, 255, 255, 0.125);
border-radius: 0.5rem;
overflow: hidden;
box-shadow: 0 0 10px 5px rgba(0 0 0 / 100%);
&:before,
&:after {
content: "";
display: block;
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
inset: 0px;
border-radius: inherit;
background: radial-gradient(
200px circle at var(--x-px) var(--y-px),
var(--hsla-color),
transparent 100%
);
mix-blend-mode: hard-light;
}
&:before {
z-index: 1;
}
&:after {
opacity: 1;
z-index: 2;
transition: opacity 0.4s ease;
}
&:hover:after {
opacity: 1;
}
.feature-content {
background: hsla(0deg 0% 0% / 100%);
border-radius: inherit;
color: white;
text-decoration: none;
z-index: 1;
position: absolute;
inset: var(--border);
display: grid;
grid-template-rows: 1fr 1fr;
grid-row-gap: 0.5rem;
padding: 0 1rem 0 2rem;
> strong {
align-self: self-end;
font-size: 125%;
}
> span {
opacity: 0.8;
}
}
}
}
}
@layer demoStyles {
* {
position: relative;
}
form {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1rem;
}
label {
color: white;
}
}
JavaScript
script.js const featuresEl = document.querySelector(".features");
document.querySelector("#sat").addEventListener("input", () => {
featuresEl.style.setProperty("--sat", sat.value + "%");
});
document.querySelector("#alp").addEventListener("input", () => {
featuresEl.style.setProperty("--alp", alp.value + "%");
});
document.querySelector("#lig").addEventListener("input", () => {
featuresEl.style.setProperty("--lig", lig.value + "%");
});
featuresEl.addEventListener("pointermove", ({ clientX, clientY }) => {
document.querySelectorAll(".feature").forEach((featureEl) => {
const { left, top } = featureEl.getBoundingClientRect();
featureEl.style.setProperty("--x", clientX - left);
featureEl.style.setProperty("--y", clientY - top);
});
});