Prevent page jump on Button click? ReactJS - css

I have a ShowcaseMovie component which fetches data on componentDidMount() and sets it to state. The component renders Card components to display the data as well as four button elements upcoming, top_rated, popular and now_playing which allow the user to toggle between the relevant data. Each button has an onClick event which calls changeFilter and sets state currentFilter to the selected key.
The problem: When the filter buttons are clicked, sometimes the page will jump to the top (if it's not already there). I've tried to find solutions to this but I can't seem to understand what is happening. Any suggestions will be a great help, thank you in advance.
Update: This issue seems to happen when there is no height set to an element with dynamic children. If I set the height on ShowcaseMovie to something large like height: 200vh it goes away.
I believe I've solved my problem but would love to hear other thoughts as to why this happens and some other ways to fix it. It's difficult to set a height to a parent when you don't know how much content is going to be rendered (or the height of that content). min-height would help but still kind of a quick fix.
ShowcaseMovie.js
import React, { Component } from "react";
import Card from "./Card";
import "../css/ShowcaseMovie.css";
import { v4 as uuidv4 } from "uuid";
import { formatString, buildMovieState } from "../utilities";
class ShowcaseMovie extends Component {
static defaultProps = {
filterNames: ["upcoming", "popular", "now_playing", "top_rated"]
};
constructor(props) {
super(props);
this.state = {
upcoming: [],
now_playing: [],
popular: [],
top_rated: [],
currentFilter: this.props.filterNames[0]
};
}
changeFilter = e => {
e.preventDefault();
const type = e.target.name;
this.setState({ currentFilter: type });
};
componentDidMount() {
this.props.filterNames.map(name => this.fetchMovies(name));
// setInterval(() => {
// this.timeoutFilter();
// }, 10000);
}
async fetchMovies(type) {
try {
const res = await fetch(
`url`
);
const data = await res.json();
if (data) {
this.setState(state => ({
...state,
[type]: buildMovieState(data)
}));
}
} catch (error) {
console.log(error);
}
}
render() {
const { currentFilter } = this.state;
const movies = this.state[currentFilter].map((movie, i) => (
<Card key={uuidv4()} movie={movie} index={i} />
));
const buttons = this.props.filterNames.map(name => (
<button
type="button"
key={name}
name={name}
className={`ShowcaseMovie-btn ${
currentFilter === name ? "active" : ""
}`}
disabled={currentFilter === name}
onClick={this.changeFilter}>
{formatString(name)}
</button>
));
return (
<section className="ShowcaseMovie">
<div className="ShowcaseMovie-container">
<h2 className="ShowcaseMovie-header">Movies</h2>
<div className="ShowcaseMovie-btn-container">{buttons}</div>
</div>
<div className="ShowcaseMovie-grid">{movies}</div>
</section>
);
}
}
ShowcaseMovie.css
.ShowcaseMovie {
padding: 4rem 10%;
}
.ShowcaseMovie-container {
position: relative;
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 2rem;
}
.ShowcaseMovie-button-container {
display: flex;
justify-content: center;
align-items: center;
}
.ShowcaseMovie-container::after {
content: "";
background-color: #64b5f6;
height: 80%;
width: 6px;
left: 0;
position: absolute;
border-radius: 1px;
}
.ShowcaseMovie-header {
font-size: 3rem;
font-weight: 200;
margin: 0 5rem;
}
.ShowcaseMovie-btn {
outline: none;
border: none;
background-color: transparent;
font-size: 1.6rem;
font-weight: 500;
letter-spacing: 1px;
padding: 1rem;
margin-left: 4rem;
color: white;
opacity: 0.5;
cursor: pointer;
transition-property: opacity;
transition-duration: 300ms;
transition-timing-function: ease;
}
.ShowcaseMovie-btn:hover {
opacity: 1;
transition-property: opacity;
transition-duration: 300ms;
transition-timing-function: ease;
}
.ShowcaseMovie-btn.active {
opacity: 1;
cursor: auto;
color: #64b5f6;
}
.ShowcaseMovie-grid {
display: grid;
gap: 3rem;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
}
Card.js
import React, { Component } from "react";
import "../css/Card.css";
class Card extends Component {
render() {
const { title, poster_path } = this.props.movie;
const style = { animationDelay: `${80 * this.props.index}ms` };
return (
<div className="Card">
<div className="Card-inner" style={style}>
<img
src={`https://image.tmdb.org/t/p/w500/${poster_path}`}
alt=""
className="Card-img"
/>
<p className="Card-name">{title}</p>
</div>
</div>
);
}
}
export default Card;
Card.css
.Card {
display: block;
transition: transform 300ms ease;
}
.Card:hover {
transform: translateY(-5px);
transition: transform 300ms ease;
}
.Card-inner {
position: relative;
display: block;
cursor: pointer;
height: 100%;
opacity: 0;
animation-name: moveUp;
animation-duration: 500ms;
animation-delay: 50ms;
animation-timing-function: ease;
animation-fill-mode: forwards;
}
.Card-inner::after {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-image: linear-gradient(transparent, rgba(33, 47, 61, 0.8));
border-bottom-left-radius: 2px;
border-bottom-right-radius: 2px;
z-index: 100;
opacity: 1;
transition: opacity 300ms ease;
}
.Card-inner:hover::after {
opacity: 0;
transition: opacity 300ms ease;
}
.Card-inner::before {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-image: linear-gradient(transparent, rgba(100, 180, 246, 0.6));
border-bottom-left-radius: 2px;
border-bottom-right-radius: 2px;
z-index: 100;
opacity: 0;
transition: opacity 300ms ease;
}
.Card-inner:hover::before {
opacity: 1;
transition: opacity 300ms ease;
}
.Card-img {
display: block;
position: relative;
object-fit: cover;
max-width: 100%;
min-height: 100%;
z-index: 0;
border-radius: 2px;
}
.Card-name {
position: absolute;
bottom: 0;
left: 0;
margin: 0 2rem 2rem 2rem;
z-index: 150;
font-weight: 400;
text-transform: uppercase;
font-size: 1.4rem;
letter-spacing: 2px;
}
#keyframes moveUp {
0% {
transform: translateY(5rem);
}
100% {
transform: translateY(0);
opacity: 1;
}
}
utilities.js
export const formatString = name => {
return name
.replace("_", " ")
.split(" ")
.map(w => w[0].toUpperCase() + w.slice(1))
.join(" ");
};
export const buildMovieState = data => {
if (data.results) {
const movies = data.results.filter(
d => d.backdrop_path && d.id && d.title && d.poster_path
);
return movies.length > 10 ? movies.slice(0, 10) : movies;
} else {
return [];
}
};

I was able to stop this from happening by returning false from the onClick call. Like this:
onClick={
doSomething()
return false
}

The page jumping could be from components unnecessarily re-rendering. Try wrapping all your components with React.memo( component name)

Related

transform shows old and new position instead of only new one

the transform works fine, but not only the new positions of the dashes are shown also the old positions are shown on click.
i want the horizontal dashes to disappear on transform.
open === false
open === true
what I expect on open === true
const StyledBar = styled.span`
width: 2rem;
height: 0.25rem;
background: ${({ theme }) => theme.colors.primary};
border-radius: 10px;
transition: all 0.3s linear;
position: relative;
transform-origin: 1px;
`;
const StyledBurgerButton = styled.button`
position: absolute;
top: 24px;
right: 24px;
display: flex;
flex-direction: column;
justify-content: space-around;
width: 2rem;
height: 2rem;
background: transparent;
border: none;
cursor: pointer;
padding: 0;
z-index: 10;
${StyledBar} {
:first-child {
transform: ${({ open }) => (open ? "rotate(45deg)" : "rotate(0)")};
}
:nth-child(2) {
opacity: ${({ open }) => (open ? "0" : "1")};
transform: ${({ open }) => (open ? "translateX(20px)" : "translateX(0)")};
}
:nth-child(3) {
transform: ${({ open }) => (open ? "rotate(-45deg)" : "rotate(0)")};
}
}
`;
const BurgerButton = ({ open, setOpen }) => {
return (
<StyledBurgerButton open={open} onClick={() => setOpen(!open)}>
<StyledBar />
<StyledBar />
<StyledBar />
</StyledBurgerButton>
);
};

In React, is there a way to have a toggle switch, onChange or onClick, switch to either the first function (thirtyDays) or the second function (year)?

I am trying to allow the user to select what will display via a toggle switch. For example, I have two functions: thirtyDays & year. Either onChange or onClick, I would like for the user to be able to switch which function is called. Is there a way to do this? Here is my code for the ToggleButton component:
thirtyDays = (props) => {
console.log("the past 30 days of transactions");
var now = new Date();
now.setDate(now.getDate() - 30);
}
year = (props) => {
console.log("year of transactions");
var now = new Date();
now.setDate(now.getDate() - 365);
}
render() {
return (
<label className="switch">
{
<>
{" "}
<input type="checkbox" id="togBtn" />
<div type="button" className="slider round">
<span className="on">Year</span>
<span className="off">30 Days</span>
</div>
</>
}
</label>
);
}
}
Here is my css:
.switch {
position: relative;
display: inline-block;
width: 175px;
height: 50px;
}
.switch input {display:none;}
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: forestgreen;
-webkit-transition: .4s;
transition: .4s;
}
.slider:before {
position: absolute;
content: "";
height: 50px;
width:50px;
left: 10px;
background-color: white;
-webkit-transition: .4s;
transition: .4s;
}
input:checked + .slider {
background-color: #2ab934;
}
input:focus + .slider {
box-shadow: 0 0 1px rgb(2, 61, 2);
}
input:checked + .slider:before {
-webkit-transform: translateX(100px);
-ms-transform: translateX(100px);
transform: translateX(100px);
}
/*------ ADDED CSS ---------*/
.on
{
display: none;
}
.off, .on
{
color: white;
position: absolute;
transform: translate(-50%,-50%);
top: 50%;
left: 50%;
font-size: 10px;
font-family: Verdana, sans-serif;
font-size: 15px;
}
input:checked+ .slider .on
{display: block;}
input:checked + .slider .off
{display: none;}
/*--------- END --------*/
/* Rounded sliders */
.slider.round {
border-radius: 34px;
}
.slider.round:before {
border-radius: 50%;}
Here is my codesandbox: https://codesandbox.io/s/ancient-rgb-y62rm?file=/src/App.js
You can decide about function which you call checking state of your checkbox inside another function. Example:
const changePeriod = (e) => {
if ( console.log( e.target.checked ) ) {
year( /* your params */ )
} else {
thirtyDays( /* your params */ )
}
}
return (
<div className="App">
<input type="checkbox" onChange={ changePeriod }/>
</div>
);
You would have to maintain the toggle state in your component. Or, if you're willing to use a plugin, you could try react-switch.
Here's a working example - https://codesandbox.io/s/frosty-water-l4pr6

CSS transition animation causes residual border lines on the page

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>

Why isn't my custom CSS transition working when updating the state of a parent React component?

I'm using functional components with hooks (state hooks mostly) and when I update the "local" state (state within the same component) my custom css transitions works fine. However, when I move this state to the parent component and update it from the child component the css transistion will not work. Instead the changes will render immediately. What am I doing wrong?
I have tried to search for a while but without success. I am making a navbar with a burger menu that will slide in a navigation list from the right when klicked.
This below will not work
import React, { useState, useEffect } from "react";
import "./navbar.css";
const Navbar = (props) => {
const [scrollState, setScrollState] = useState("top");
const [burgerOpen, setBurgerOpen] = useState(false); //updating this state transistions does not work!
const Burger = () => {
//const [open, setOpen] = useState(false); //updating this state transistions work!
const handleKeyDown = (event) => {
if (event.key === "Enter") {
setBurgerOpen(!burgerOpen);
}
};
return (
<>
<div className={"btn-container"} onKeyDown={handleKeyDown}>
<div
className={burgerOpen ? "navbar-btn open" : "navbar-btn"}
open={burgerOpen}
onClick={() => setBurgerOpen(!burgerOpen)}
>
<div className="navbar-burger" />
</div>
</div>
<Menu open={burgerOpen} key="menu" />
</>
);
};
const Menu = ({ open }) => {
return (
<ul className={open ? "open" : ""}>
<li>
<a to="/projects">Projects</a>
</li>
<li>
<a to="/design">Design</a>
</li>
<li>
<a to="/contact">Contact</a>
</li>
</ul>
);
};
return (
<nav
className={`navbar ${scrollState === "top" ? "dark-nav" : "light-nav"}`}
>
<Burger />
</nav>
);
};
Navbar.propTypes = {};
export default Navbar;
This however works but I need to move the state to the parent because of rerenders that I might add (e.g. I want to keep the menu open...)
import React, { useState, useEffect } from "react";
import "./navbar.css";
const Navbar = (props) => {
const [scrollState, setScrollState] = useState("top");
//const [burgerOpen, setBurgerOpen] = useState(false); //updating this state transistions does not work!
const Burger = () => {
const [open, setOpen] = useState(false); //updating this state transistions work!
const handleKeyDown = (event) => {
if (event.key === "Enter") {
open(!open);
}
};
return (
<>
<div className={"btn-container"} onKeyDown={handleKeyDown}>
<div
className={open ? "navbar-btn open" : "navbar-btn"}
open={open}
onClick={() => setOpen(!open)}
>
<div className="navbar-burger" />
</div>
</div>
<Menu open={open} key="menu" />
</>
);
};
const Menu = ({ open }) => {
return (
<ul className={open ? "open" : ""}>
<li>
<a to="/projects">Projects</a>
</li>
<li>
<a to="/design">Design</a>
</li>
<li>
<a to="/contact">Contact</a>
</li>
</ul>
);
};
return (
<nav
className={`navbar ${scrollState === "top" ? "dark-nav" : "light-nav"}`}
>
<Burger />
</nav>
);
};
Navbar.propTypes = {};
export default Navbar;
And the CSS:
.navbar {
display: flex;
justify-content: space-between;
align-items: center;
position: fixed;
z-index: 999;
width: 100%;
top: 0;
padding: 0.7rem 2rem;
height: 170px;
transition: all 0.8s ease;
background: linear-gradient(
to bottom,
rgba(0, 0, 0, 0.815) 50%,
rgba(0, 0, 0, 0.35) 50%
)
right;
background-size: 100% 200%;
background-position: top;
}
.light-nav {
/*background-color: rgba(0, 0, 0, 0.35);*/
background-position: bottom;
}
.navbar ul {
display: flex;
flex-flow: row nowrap;
}
.navbar li {
padding: 10px 10px;
font-size: 20px;
}
.navbar a {
background: linear-gradient(to right, royalblue, royalblue 50%, #f4f4f4 50%);
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-size: 200% 100%;
background-position: 100%;
transition: background-position 0.5s ease;
}
.navbar a:hover {
background-position: 0 100%;
}
.navbar-logo {
height: auto;
width: 200px;
padding: 2px;
}
.navbar-logo img {
max-width: 100%;
max-height: 100%;
}
.navbar-btn {
visibility: hidden;
display: none;
position: relative;
justify-content: center;
align-items: center;
cursor: pointer;
transition: all 0.5s ease-in-out;
width: 50px;
height: 50px;
padding-top: 10px;
}
.btn-container:focus > .navbar-btn {
border: #f4f4f4 1px solid;
}
.btn-container:focus,
.navbar-btn:focus {
border: none;
}
.navbar-burger {
width: 35px;
height: 3px;
background: #f4f4f4;
border-radius: 5px;
transition: all 0.5s ease-in-out;
}
.navbar-burger::before,
.navbar-burger::after {
content: '';
position: absolute;
width: 35px;
height: 3px;
background: #f4f4f4;
border-radius: 5px;
transition: all 0.5s ease-in-out;
}
.navbar-burger::before {
transform: translateY(-10px);
}
.navbar-burger::after {
transform: translateY(10px);
}
.navbar-btn.open .navbar-burger {
transform: translateX(-50px);
background: transparent;
}
.navbar-btn.open .navbar-burger::before {
transform: rotate(45deg) translate(35px, -35px);
}
.navbar-btn.open .navbar-burger::after {
transform: rotate(-45deg) translate(35px, 35px);
}
.navbar-btn:hover .navbar-burger,
.navbar-btn:hover .navbar-burger::before,
.navbar-btn:hover .navbar-burger::after {
background: royalblue;
}
.navbar-btn.open:hover .navbar-burger {
background: transparent;
}
#media (max-width: 768px) {
.navbar {
height: 110px;
}
.navbar-logo {
width: 140px;
}
.navbar ul {
flex-flow: column nowrap;
position: fixed;
top: 110px;
right: 0;
height: 100vh;
width: 200px;
transform: translateX(100%);
transition: 0.5s ease-in-out;
background-color: rgba(0, 0, 0, 0.815);
}
.navbar ul li {
transform: translateX(100%);
transition: 0.5s ease-in-out;
}
.navbar ul.open li {
transform: translateX(0);
}
.navbar ul li:nth-child(1) {
transition-delay: 0.1s;
}
.navbar ul li:nth-child(2) {
transition-delay: 0.2s;
}
.navbar ul li:nth-child(3) {
transition-delay: 0.3s;
}
.navbar ul.open {
transform: translateX(0);
}
.navbar-btn {
visibility: visible;
display: flex;
padding-bottom: 10px;
}
}
Here is a sandbox of the working example but I need to move out the state of the Burger (resize for burger menu):
Working example (resize!)

Input text disappear while hover and typing

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;
}

Resources