I can't seem to find the issue I'm using Gatsby and I created a Ref for handling form validation on the input, pretty basic stuff gone wrong for some reason
Here is the html:
<form onSubmit={(event) => handleSubmit(event, email)}>
<label htmlFor="email">Our newsletter</label>
<input
value={email || ''}
name="email"
placeholder="La tua e-mail"
type="text"
spellCheck="false"
className="input"
onChange={() => setEmail(myRef.current.value)}
ref={myRef}
/>
<button className="button" onClick={checkInput} type="submit">
Iscriviti
</button>
{message && (
<>
<br />
<small>{message.substring(0, 45)}</small>
</>
)}
</form>
These are the functions
const [message, setMessage] = useState();
const [email, setEmail] = useState('');
let myRef = useRef();
function handleSubmit(event, email) {
event.preventDefault();
addToMailchimp(email) // listFields are optional if you are only capturing the email address.
.then((data) => {
// I recommend setting data to React state
// but you can do whatever you want (including ignoring this `then()` altogether)
setMessage(data.msg);
})
.catch(() => {
// unnecessary because Mailchimp only ever
// returns a 200 status code
// see below for how to handle errors
});
}
const checkInput = () => {
console.log(myRef);
if (myRef.current.value === '') {
setErrorFor();
} else if (!isEmail(myRef.current.value)) {
setErrorFor();
} else {
setSuccessFor();
}
};
function setErrorFor() {
const formControl = myRef.current;
formControl.className = 'error shaka';
}
function setSuccessFor() {
const formControl = myRef.current;
formControl.className = 'success';
}
function isEmail(email) {
return /^(([^<>()\[\]\\.,;:\s#"]+(\.[^<>()\[\]\\.,;:\s#"]+)*)|(".+"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(
email
);
}
This is the CSS
form {
display: flex;
justify-content: space-between;
align-items: flex-start;
flex-direction: column;
width: 45%;
#media only screen and (max-width: 699px) {
width: 100%;
text-align: center;
}
label {
font-size: calc(1.3rem + (24 - 14) * ((100vw - 300px) / (1600 - 300)));
text-transform: uppercase;
font-weight: bolder;
font-family: 'Acme', sans-serif;
letter-spacing: 0.1rem;
#media only screen and (max-width: 699px) {
text-align: center;
margin: 4rem auto 0 auto;
font-size: calc(2rem + (24 - 14) * ((100vw - 300px) / (1600 - 300)));
}
}
}
input {
width: 100%;
max-width: 320px;
min-width: 150px;
border: none;
padding: 0.5rem;
border-radius: 3px;
margin-top: 1rem;
height: 2.5rem;
font-size: 1rem;
color: black;
#media only screen and (max-width: 699px) {
width: 100%;
min-width: 100%;
}
}
.button {
height: 2.5rem;
border: 1px solid white;
margin-top: 1rem;
width: 100%;
max-width: 320px;
min-width: 150px;
cursor: pointer;
padding: 0.5rem;
border-radius: 3px;
background-color: cornflowerblue;
color: white;
font-size: 1.3rem;
font-family: 'Acme', sans-serif;
#media only screen and (max-width: 699px) {
width: 100%;
min-width: 100%;
}
}
.success {
border: 2px solid $maingreen;
}
.error {
border: 2px solid red;
}
.input {
z-index: 5;
outline: none;
:focus,
:hover {
outline: none;
text-rendering: optimizeLegibility;
text-indent: inherit;
z-index: 5000000000000000000000;
display: flex;
font-size: inherit;
color: inherit;
}
}
.input:hover {
z-index: 5;
color: inherit;
}
.shaka {
animation: shake 0.82s cubic-bezier(0.36, 0.07, 0.19, 0.97) both;
transform: translate3d(0, 0, 0);
backface-visibility: hidden;
perspective: 1000px;
animation-duration: 1s;
}
#keyframes shake {
10%,
90% {
transform: translate3d(-1px, 0, 0);
}
20%,
80% {
transform: translate3d(2px, 0, 0);
}
30%,
50%,
70% {
transform: translate3d(-4px, 0, 0);
}
40%,
60% {
transform: translate3d(4px, 0, 0);
}
}
}
Live example: don't know what that black border is, perhaps after validating it it works normally, same story on all browsers
If you ever notice the same problem happening to you, I would like to know what's happening. Thank you
I dont understand why u use z-index to the input,
remove that and the z-index in the input:hover
Disappearing text on hover for me I looks like it get the color from inherit, change inherit to a color like #000.
.input:hover {
z-index: 5;
color: inherit;
}
Related
so I have this three button I need to find a way any of these two solution
make animation so that each time one button come in front and the
two other go to the back
or, when I click on a button it come to the front and the other go to the back
here is my code for the style
.index-environement-specialise-boutton-main {
width: 279px;
height: 76px;
border: 1px solid var(--color-text-primary);
border-radius: 46px;
text-align: center;
font-style: normal !important;
font-variant: normal !important;
font-weight: bold !important;
font-size: 32px !important;
line-height: 34px !important;
font-family: Poppins !important;
letter-spacing: 0.5px;
color: var(--color-text-primary);
opacity: 1;
margin-inline: 2.625rem;
position: relative;
box-shadow: 0px 0px 222px 150px rgba(193, 186, 243, 0.75);
-webkit-box-shadow: 0px 0px 222px 150px rgba(193, 186, 243, 0.75);
-moz-box-shadow: 0px 0px 222px 150px rgba(193, 186, 243, 0.75);
display: flex;
align-items: center;
justify-content: center;
}
.index-environement-specialise-boutton-main.b1 {
background: #C1BAF3 0% 0% no-repeat padding-box;
}
.index-environement-specialise-boutton-main.b2 {
background: #F8D6B5 0% 0% no-repeat padding-box;
}
.index-environement-specialise-boutton-main.b3 {
background: #F3B9C5 0% 0% no-repeat padding-box;
}
.index-environement-specialise-boutton-behind {
width: 176px;
height: 48px;
border: 1px solid var(--color-text-primary);
border-radius: 46px;
text-align: center;
font-style: normal !important;
font-variant: normal !important;
font-weight: bold !important;
font-size: 20px !important;
line-height: 21px !important;
font-family: Poppins !important;
letter-spacing: 0.5px;
color: var(--color-text-primary);
opacity: 1;
display: flex;
align-items: center;
justify-content: center;
}
.index-environement-specialise-boutton-behind.b1 {
background: #C1BAF3 0% 0% no-repeat padding-box;
}
.index-environement-specialise-boutton-behind.b2 {
background: #F8D6B5 0% 0% no-repeat padding-box;
}
.index-environement-specialise-boutton-behind.b3 {
background: #F3B9C5 0% 0% no-repeat padding-box;
}
.index-environement-specialise-boutton-main:hover,
.index-environement-specialise-boutton-behind:hover {
color: var(--color-text-primary);
}
.index-environement-specialise-col-right{
width:700px;
}
<div class="w-100 index-environement-specialise-col-right">
<a class="index-environement-specialise-boutton-behind b2"
role="button"
href="javascript:void(0)"
id="A2" runat="server" title="hôtesses">
hôtesses
</a>
<a class="index-environement-specialise-boutton-main b1"
role="button"
href="javascript:void(0)"
id="A3" runat="server" title="sitters">
sitters
</a>
<a class="index-environement-specialise-boutton-behind b3"
role="button"
href="javascript:void(0)" id="A4" runat="server"
title="vendeurs">
vendeurs
</a>
</div>
With some CSS flex positioning, with JS's getBoundingClientRect() method and some simple math — animate the buttons wrapper using CSS3 transition and transform (inside a .carousel container) by the center point of each button item in relation to the horizontal center of the carousel:
// DOM helpers:
const els = (sel, par) => (par || document).querySelectorAll(sel);
const el = (sel, par) => (par || document).querySelector(sel);
// Carousel:
const btnCarousel = (elCarousel) => {
const move = (evt) => {
const elButton = evt.target.closest("button");
if (!elButton) return; // do nothing
const elSlider = el(".carousel-slider", elCarousel);
const bcrButton = elButton.getBoundingClientRect();
const bcrCarousel = elCarousel.getBoundingClientRect();
const bcrSlider = elSlider.getBoundingClientRect();
const centerCarousel = bcrCarousel.width / 2;
const centerButton = bcrButton.width / 2;
const xButton = bcrButton.left;
const xSlider = bcrSlider.left;
const x = centerCarousel - xButton - centerButton + xSlider;
elSlider.style.translate = `${x}px 0`;
};
elCarousel.addEventListener("click", move);
};
els(".carousel").forEach(btnCarousel);
.carousel {
position: relative;
overflow: hidden;
}
.carousel-slider {
display: flex;
margin: 0 auto;
justify-content: center;
gap: 1rem;
transition: 0.5s;
}
<div class="carousel">
<div class="carousel-slider">
<button type="button">1 Button</button>
<button type="button">2 Btn</button>
<button type="button">3 Button longer text</button>
</div>
</div>
<div class="carousel">
<div class="carousel-slider">
<button type="button">1 Super Button</button>
<button type="button">2 Some Button</button>
<button type="button">3</button>
</div>
</div>
Add a .is-active on click, some more styles, a CSS transition-origin to the button's center-top and you're almost done:
// DOM helpers:
const els = (sel, par) => (par || document).querySelectorAll(sel);
const el = (sel, par) => (par || document).querySelector(sel);
// Carousel:
const btnCarousel = (elCarousel) => {
const elButtons = els("button", elCarousel);
const move = (evt) => {
const elButton = evt.target.closest("button");
if (!elButton) return; // do nothing
const elSlider = el(".carousel-slider", elCarousel);
const bcrButton = elButton.getBoundingClientRect();
const bcrCarousel = elCarousel.getBoundingClientRect();
const bcrSlider = elSlider.getBoundingClientRect();
const centerCarousel = bcrCarousel.width / 2;
const centerButton = bcrButton.width / 2;
const xButton = bcrButton.left;
const xSlider = bcrSlider.left;
const x = centerCarousel - xButton - centerButton + xSlider;
elSlider.style.translate = `${x}px 0`;
elButtons.forEach(el => el.classList.remove("is-active"));
elButton.classList.add("is-active");
};
elCarousel.addEventListener("click", move);
};
els(".carousel").forEach(btnCarousel);
/* QuickReset*/
*,
::before,
::after {
margin: 0;
box-sizing: border-box;
}
body {
font: 16px/1.5 sans-serif;
background: linear-gradient(90deg, rgba(244, 246, 255, 1) 0%, rgba(213, 208, 247, 1) 50%, rgba(244, 246, 255, 1) 100%);
}
.carousel {
position: relative;
overflow: hidden;
padding: 4rem 0;
}
.carousel-slider {
display: flex;
margin: 0 auto;
justify-content: center;
gap: 4rem;
transition: 0.5s;
}
.btn {
border: 0.1rem solid #455171;
padding: 0.4em 2.6em;
font-weight: 900;
font-size: 1rem;
border-radius: 2em;
cursor: pointer;
}
.carousel .btn {
transform-origin: center top;
transition: 0.5s;
}
.carousel .btn.is-active {
scale: 1.4;
}
.bg-1 {
background-color: #ecb9cc;
}
.bg-2 {
background-color: #c1baf3;
}
.bg-3 {
background-color: #f0d2be;
}
<div class="carousel">
<div class="carousel-slider">
<button type="button" class="btn bg-1">Hôtesses</button>
<button type="button" class="btn bg-2 is-active">Sitters</button>
<button type="button" class="btn bg-3">Vendeurs</button>
</div>
</div>
I have a react component called TeamBanner like so
import styles from "./teamBanner.module.css";
import { useNavigate } from "react-router-dom";
import { TeamBannerProps } from "../ProjectTypes.types";
export const TeamBanner = ({
team,
onBannerClick,
showName,
}: TeamBannerProps) => {
let navigate = useNavigate();
const handleOnClick = () => {
navigate(`/${team}`);
onBannerClick();
};
return (
<div
className={`${styles.container} flex theme-light ${
showName ? "" : styles["no-name"]
}`}
title={team}
onClick={handleOnClick}
>
<div>
<img
src={require(`../logos/${team}.svg`)}
alt="logo"
className={`${styles.logo} ${showName ? "" : styles["only-logo"]}`}
/>
</div>
{showName ? team : ""}
</div>
);
};
The teamBanner.module.css file is like so
.container {
margin: 0.25em;
align-items: center;
cursor: pointer;
top: 0;
z-index: 2;
background-color: hsl(var(--color-background));
padding: 0.1em 0.25em;
border-radius: 0.5em;
box-shadow: 0.05rem 0.05rem 0.2rem rgb(0 0 0 / 50%);
font-family: var(--ff-serif);
font-size: var(--fs-200);
}
.logo {
display: inline-block;
vertical-align: middle;
width: 3vmax;
height: 3vmax;
}
.container:hover {
outline: 0.15em solid hsl(240, 90%, 67%);
}
.no-name {
border-radius: 0.25em;
}
.only-logo {
width: 5vmax;
height: 5vmax;
}
I am using it to create a list of team of a page & this works just fine.
However, I want to use it in another place also. In the place, the to now want the .container:hover effect & I want the font properties of the .contaner and width & height properties of the .logo changed.
How can I accomplish this? only changing these items of the module.css? Can any one help? Thanks
I am working on an input type range slider. I found out that the Chrome version of input[type=range]::-moz-range-thumb is input[type=range]::-webkit-slider-thumb .
Now, I want the same for input[type=range]::-moz-range-progress.
I have tried input[type=range]::-webkit-slider-progress , input[type=range]::-webkit-slider-runnable-progress .
Still not working so far. Any alternative?
It is totally possible with CSS only.
This dude has done it: https://codepen.io/ShadowShahriar/pen/zYPPYrQ
HTML:
<main>
<input type="range" class="win10-thumb" />
<input type="range" class="win10-thumb" min="0" max="100" value="25" step="5" />
<input type="range" class="win10-thumb" disabled value="64" />
<input type="range" />
<input type="range" min="0" max="100" value="40" step="5" />
<input type="range" disabled value="80" />
</main>
CSS:
html,
body {
height: 100%;
}
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
body {
display: grid;
place-items: center;
}
main {
display: flex;
flex-direction: column;
gap: 2.2em;
padding: 1em 0;
}
html::before {
content: "";
position: fixed;
left: 0;
top: 0;
width: 100vw;
height: 100vh;
background: radial-gradient(circle at center, #fff, #fafafa);
display: block;
}
/* === range theme and appearance === */
input[type="range"] {
font-size: 1.5rem;
width: 12.5em;
}
input[type="range"] {
color: #ef233c;
--thumb-height: 1.125em;
--track-height: 0.125em;
--track-color: rgba(0, 0, 0, 0.2);
--brightness-hover: 180%;
--brightness-down: 80%;
--clip-edges: 0.125em;
}
input[type="range"].win10-thumb {
color: #2b2d42;
--thumb-height: 1.375em;
--thumb-width: 0.5em;
--clip-edges: 0.0125em;
}
#media (prefers-color-scheme: dark) {
html {
background-color: #000;
}
html::before {
background: radial-gradient(circle at center, #101112, #000);
}
input[type="range"] {
color: #f07167;
--track-color: rgba(255, 255, 255, 0.1);
}
input[type="range"].win10-thumb {
color: #3a86ff;
}
}
/* === range commons === */
input[type="range"] {
position: relative;
background: #fff0;
overflow: hidden;
}
input[type="range"]:active {
cursor: grabbing;
}
input[type="range"]:disabled {
filter: grayscale(1);
opacity: 0.3;
cursor: not-allowed;
}
/* === WebKit specific styles === */
input[type="range"],
input[type="range"]::-webkit-slider-runnable-track,
input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
transition: all ease 100ms;
height: var(--thumb-height);
}
input[type="range"]::-webkit-slider-runnable-track,
input[type="range"]::-webkit-slider-thumb {
position: relative;
}
input[type="range"]::-webkit-slider-thumb {
--thumb-radius: calc((var(--thumb-height) * 0.5) - 1px);
--clip-top: calc((var(--thumb-height) - var(--track-height)) * 0.5 - 0.5px);
--clip-bottom: calc(var(--thumb-height) - var(--clip-top));
--clip-further: calc(100% + 1px);
--box-fill: calc(-100vmax - var(--thumb-width, var(--thumb-height))) 0 0
100vmax currentColor;
width: var(--thumb-width, var(--thumb-height));
background: linear-gradient(currentColor 0 0) scroll no-repeat left center /
50% calc(var(--track-height) + 1px);
background-color: currentColor;
box-shadow: var(--box-fill);
border-radius: var(--thumb-width, var(--thumb-height));
filter: brightness(100%);
clip-path: polygon(
100% -1px,
var(--clip-edges) -1px,
0 var(--clip-top),
-100vmax var(--clip-top),
-100vmax var(--clip-bottom),
0 var(--clip-bottom),
var(--clip-edges) 100%,
var(--clip-further) var(--clip-further)
);
}
input[type="range"]:hover::-webkit-slider-thumb {
filter: brightness(var(--brightness-hover));
cursor: grab;
}
input[type="range"]:active::-webkit-slider-thumb {
filter: brightness(var(--brightness-down));
cursor: grabbing;
}
input[type="range"]::-webkit-slider-runnable-track {
background: linear-gradient(var(--track-color) 0 0) scroll no-repeat center /
100% calc(var(--track-height) + 1px);
}
input[type="range"]:disabled::-webkit-slider-thumb {
cursor: not-allowed;
}
/* === Firefox specific styles === */
input[type="range"],
input[type="range"]::-moz-range-track,
input[type="range"]::-moz-range-thumb {
appearance: none;
transition: all ease 100ms;
height: var(--thumb-height);
}
input[type="range"]::-moz-range-track,
input[type="range"]::-moz-range-thumb,
input[type="range"]::-moz-range-progress {
background: #fff0;
}
input[type="range"]::-moz-range-thumb {
background: currentColor;
border: 0;
width: var(--thumb-width, var(--thumb-height));
border-radius: var(--thumb-width, var(--thumb-height));
cursor: grab;
}
input[type="range"]:active::-moz-range-thumb {
cursor: grabbing;
}
input[type="range"]::-moz-range-track {
width: 100%;
background: var(--track-color);
}
input[type="range"]::-moz-range-progress {
appearance: none;
background: currentColor;
transition-delay: 30ms;
}
input[type="range"]::-moz-range-track,
input[type="range"]::-moz-range-progress {
height: calc(var(--track-height) + 1px);
border-radius: var(--track-height);
}
input[type="range"]::-moz-range-thumb,
input[type="range"]::-moz-range-progress {
filter: brightness(100%);
}
input[type="range"]:hover::-moz-range-thumb,
input[type="range"]:hover::-moz-range-progress {
filter: brightness(var(--brightness-hover));
}
input[type="range"]:active::-moz-range-thumb,
input[type="range"]:active::-moz-range-progress {
filter: brightness(var(--brightness-down));
}
input[type="range"]:disabled::-moz-range-thumb {
cursor: not-allowed;
}
On Internet Explorer you can use ::-ms-fill-lower to do this thing and firefox supports ::-moz-range-progress, but on chrome this is not possible only using css.
However, there is a good example below using JS.
It changes the background of the range element using linear-gradient.
https://codepen.io/duplich/pen/qjYQEZ
I made a pop-up window and used transition animation in CSS.
When I open the pop-up window, there is no problem with the transition animation, but when the pop-up window is closed, there will be residual border lines on the page.
This happens in Google Chrome.
Please click here for details:
https://codepen.io/lianflower/pen/zYKRPJb
<button data-modal-target="#modal">Open Modal</button>
<div class="modal" id="modal">
<div class="modal-header">
<div class="title">Example Modal</div>
<button data-close-button class="closebutton">×</button>
</div>
<div class="modal-body">
A wiki (/ˈwɪki/ (About this soundlisten) WIK-ee) is a hypertext publication collaboratively edited and managed by its own audience directly using a web browser. A typical wiki contains multiple pages for the subjects or scope of the project and may be either open to the public or limited to use within an organization for maintaining its internal knowledge base
</div>
</div>
<div id="overlay"></div>
*,*::after, *::before {
box-sizing: border-box;
}
.modal {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) scale(0);
transition: 500ms ease-in-out;
border: 1px solid black;
border-radius: 10px;
z-index: 10;
background-color: white;
width: 800px;
max-width: 80%;
}
.modal.active {
transform: translate(-50%, -50%) scale(1);
}
.modal-header {
padding: 10px 15px;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid black;
}
.modal-header .title {
font-size: 1.25rem;
font-weight: bold;
}
.modal-header .close-button {
cursor: pointer;
border: none;
outline: none;
background: none;
font-size: 1.25rem;
font-weight: bold;
}
.modal-body {
padding: 10px 15px;
}
#overlay {
position: fixed;
opacity: 0;
transition: 200ms ease-in-out;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, .5);
pointer-events: none;
}
#overlay.active {
opacity: 1;
pointer-events: all;
}
var openModalButtons = document.querySelectorAll('[data-modal-target]');
var closeModalButtons = document.querySelectorAll('[data-close-button]');
var overlay = document.getElementById('overlay');
openModalButtons.forEach(button => {
button.addEventListener('click', () => {
var modal = document.querySelector(button.dataset.modalTarget);
openModal(modal)
})
});
closeModalButtons.forEach(button => {
button.addEventListener('click', () => {
var modal = button.closest('.modal');
closeModal(modal)
})
});
overlay.addEventListener('click', () => {
var modals = document.querySelectorAll('.modal.active');
modals.forEach(modal => {
closeModal(modal)
});
});
function openModal(modal) {
if (modal == null) return;
modal.classList.add('active');
overlay.classList.add('active')
}
function closeModal(modal) {
if (modal == null) return;
modal.classList.remove('active');
overlay.classList.remove('active')
}
You modal has a border, border: 1px solid black; That is causing this thing to happen. Put border on modal.active class instead and you are good to go.
Update: Set your borders only when the modal is active on any of the children components of modal in order to avoid these extra lines.
Codepen:https://codepen.io/emmeiWhite/pen/MWjQrJd
Full Code:
var openModalButtons = document.querySelectorAll('[data-modal-target]');
var closeModalButtons = document.querySelectorAll('[data-close-button]');
var overlay = document.getElementById('overlay');
openModalButtons.forEach(button => {
button.addEventListener('click', () => {
var modal = document.querySelector(button.dataset.modalTarget);
openModal(modal)
})
});
closeModalButtons.forEach(button => {
button.addEventListener('click', () => {
var modal = button.closest('.modal');
closeModal(modal)
})
});
overlay.addEventListener('click', () => {
var modals = document.querySelectorAll('.modal.active');
modals.forEach(modal => {
closeModal(modal)
});
});
function openModal(modal) {
if (modal == null) return;
modal.classList.add('active');
overlay.classList.add('active')
}
function closeModal(modal) {
if (modal == null) return;
modal.classList.remove('active');
overlay.classList.remove('active')
}
*,*::after, *::before {
box-sizing: border-box;
}
.modal { /* Removed border from is selector */
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) scale(0);
transition: 500ms ease-in-out;
border-radius: 10px;
z-index: 10;
background-color: white;
width: 800px;
max-width: 80%;
}
.modal.active {
transform: translate(-50%, -50%) scale(1);
border: 1px solid black; /*--- Added border here ---*/
}
.modal-header {
padding: 10px 15px;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid black;
}
.modal-header .title {
font-size: 1.25rem;
font-weight: bold;
}
.modal-header .close-button {
cursor: pointer;
border: none;
outline: none;
background: none;
font-size: 1.25rem;
font-weight: bold;
}
.modal-body {
padding: 10px 15px;
}
.modal-body.active{ /* Add border on active class only */
border:1px solid blue;
}
#overlay {
position: fixed;
opacity: 0;
transition: 200ms ease-in-out;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, .5);
pointer-events: none;
}
#overlay.active {
opacity: 1;
pointer-events: all;
}
<button data-modal-target="#modal">Open Modal</button>
<div class="modal" id="modal">
<div class="modal-header">
<div class="title">Example Modal</div>
<button data-close-button class="closebutton">×</button>
</div>
<div class="modal-body">
A wiki (/ˈwɪki/ (About this soundlisten) WIK-ee) is a hypertext publication collaboratively edited and managed by its own audience directly using a web browser. A typical wiki contains multiple pages for the subjects or scope of the project and may be either open to the public or limited to use within an organization for maintaining its internal knowledge base
</div>
</div>
<div id="overlay"></div>
I am trying to create a custom cursor that changes when hovering over a <div>, but there is a flicker when moving left to right across it, but not when moving right to left. Why this is happening and what I can do to fix it?
document.addEventListener('mousemove', (ev) => cursorMove(ev));
function cursorMove(ev) {
let circle = document.getElementById('circle');
let posY = ev.clientY;
let posX = ev.clientX;
circle.style.top = posY + 'px';
circle.style.left = posX + 'px';
}
body {
margin: 0;
height: 100vh;
background-color: #acd1d2;
position: relative;
display: flex;
justify-content: center;
align-items: center;
font-family: monospace;
}
#wrapper {
position: relative;
width: 70%;
height: 80%;
}
.box {
height: 25%;
margin: 0;
display: flex;
justify-content: center;
align-items: center;
}
#box-1 {
background-color: #e8edf3;
}
#box-1:hover ~ #circle {
background-color: #e6cf8b;
box-shadow:inset 0em -0.3em 0.4em 0.2em #ca9e03a6;
}
#box-2 {
background-color: #e6cf8b;
}
#box-2:hover ~ #circle {
background-color: transparent;
border: 3px solid #E91E63;
}
#box-3 {
background-color: #b56969;
}
#box-3:hover ~ #circle {
height: 1em;
width: 1em;
background-color: #e6cf8b;
}
#box-4 {
background-color: #22264b;
color: white;
}
#box-4:hover ~ #circle {
background-image: linear-gradient(to top, #fbc2eb 0%, #a6c1ee 100%);
}
#circle {
position: fixed;
border-radius: 50%;
z-index: 5;
height: 32px;
width: 32px;
background-color: white;
}
<div id="wrapper">
<div id="box-1" class="box">Sphere</div>
<div id="box-2" class="box">Circle outline</div>
<div id="box-3" class="box">Circle pin</div>
<div id="box-4" class="box">Circle color gradient</div>
<div id="circle"></div>
</div>
That's because your mouse moves faster than the circle and you hover over it, so the styles that apply to it are the same ones than when the cursor is on the background green/blue-ish area of the page.
You can fix that by adding pointer-events: none to the circle so that it feels a bit like this:
Ok, where were we? Oh yes... So you should use position: fixed instead of absolute (as you really want your cursor to be positioned relative to the top-left corner of the viewport) and probably window.requestAnimationFrame to get a smoother animation and translate3d(0, 0, 0) to promote the element to its own layer and enable hardware-accelerated rendering, which will also contribute to make it feel smoother.
You could also hide the default cursor with cursor: none and center the circle where the arrowhead of the cursor is to make it feel just like a real cursor.
const circle = document.getElementById('circle');
const circleStyle = circle.style;
document.addEventListener('mousemove', e => {
window.requestAnimationFrame(() => {
circleStyle.top = `${ e.clientY - circle.offsetHeight/2 }px`;
circleStyle.left = `${ e.clientX - circle.offsetWidth/2 }px`;
});
});
body {
margin: 0;
height: 100vh;
background-color: #acd1d2;
position: relative;
display: flex;
justify-content: center;
align-items: center;
font-family: monospace;
cursor: none;
}
#wrapper {
position: relative;
width: 70%;
height: 80%;
}
#circle {
position: fixed;
border-radius: 50%;
z-index: 5;
height: 32px;
width: 32px;
background-color: white;
pointer-events: none;
transition:
background ease-in 10ms,
box-shadow ease-in 150ms,
transform ease-in 150ms;
/* Promote it to its own layer to enable hardware accelerated rendering: */
transform: translate3d(0, 0, 0);
}
.box {
height: 25%;
margin: 0;
display: flex;
justify-content: center;
align-items: center;
}
#box-1 {
background-color: #e8edf3;
}
#box-1:hover ~ #circle {
background-color: #e6cf8b;
box-shadow: 0 0 0 0 transparent, inset 0em -0.3em 0.4em 0.2em #ca9e03a6;
}
#box-2 {
background-color: #e6cf8b;
}
#box-2:hover ~ #circle {
background-color: transparent;
/* Use box-shadow instead of border to avoid changing the dimensions of the
cursor, which will make it be off-center until the mouse moves again: */
aborder: 3px solid #E91E63;
box-shadow: 0 0 0 3px #E91E63;
}
#box-3 {
background-color: #b56969;
}
#box-3:hover ~ #circle {
background-color: #e6cf8b;
/* Change its size with scale() instead of width and height for better
performance performance: */
transform: scale(0.5) translate3d(0, 0, 0);
}
#box-4 {
background-color: #22264b;
color: white;
}
#box-4:hover ~ #circle {
background-image: linear-gradient(to top, #fbc2eb 0%, #a6c1ee 100%);
}
<div id="wrapper">
<div id="box-1" class="box">Sphere</div>
<div id="box-2" class="box">Circle outline</div>
<div id="box-3" class="box">Circle pin</div>
<div id="box-4" class="box">Circle color gradient</div>
<div id="circle"></div>
</div>
Here you can see another cool example I made of a custom cursor using CSS that resembles a torch: How to darken a CSS background image but keep area around cursor brighter.
Also, you can check out the cursor on my website, which is quite similar to what you have done as it has animations/transitions between its different shapes or states.
🚀 Check it out here: https://gmzcodes.com/.
👨💻 Check the code here: https://github.com/Danziger/gmzcodes