I have a simple form. When the user focuses on an input, the label should move up. It works fine in Firefox (as can be seen in video), but not in Chrome. In chrome, the text is stuck in the end position. When I change text color in the :focus + span code block, it applies automatically, which tells me that the elements are constantly focused.
import React from 'react'
import styled from 'styled-components'
import { useState, useEffect } from 'react';
function PersonalInfo() {
const [firstAndLastName, setfirstAndLastName] = useState(JSON.parse(sessionStorage.getItem('FirstAndLastName' ?? '')));
const [email, setEmail] = useState(JSON.parse(sessionStorage.getItem('email' ?? '')));
const [companyName, setCompanyName] = useState(JSON.parse(sessionStorage.getItem('companyName' ?? '')));
const [companyIndustry, setCompanyIndustry] = useState(JSON.parse(sessionStorage.getItem('companyIndustry' ?? '')));
const handleNameChange = (e) => {
// console.log(firstAndLastName)
sessionStorage.setItem('FirstAndLastName', JSON.stringify(e.target.value));
setfirstAndLastName(e.target.value)
}
const handleEmailChange = (e) => {
// console.log(email)
sessionStorage.setItem('email', JSON.stringify(e.target.value));
setEmail(e.target.value)
}
const handleCompanyNameChange = (e) => {
// console.log(companyName)
sessionStorage.setItem('companyName', JSON.stringify(e.target.value));
setCompanyName(e.target.value)
}
const handleCompanyIndustryChange = (e) => {
// console.log(companyIndustry)
sessionStorage.setItem('companyIndustry', JSON.stringify(e.target.value));
setCompanyIndustry(e.target.value)
}
return (
<PersonalInfoContainer>
<InputContainer>
<Input
name="user_name"
type='text'
value={firstAndLastName}
onChange={handleNameChange}
placeholder=''/>
<Label>First and Last Name</Label>
</InputContainer>
<InputContainer>
<Input
name='user_email'
type='email'
value={email}
onChange={handleEmailChange}
placeholder=''/>
<Label>Email</Label>
</InputContainer>
<InputContainer>
<Input
name='user_companyName'
type='text'
value={companyName}
onChange={handleCompanyNameChange}
placeholder=''/>
<Label>Company Name</Label>
</InputContainer>
<InputContainer>
<Input
name='user_companyIndustry'
type='text'
value={companyIndustry}
onChange={handleCompanyIndustryChange}
placeholder=''/>
<Label>Company Industry</Label>
</InputContainer>
</PersonalInfoContainer>
)
}
const PersonalInfoContainer = styled.div`
display: flex;
flex-direction: column;
justify-content: space-between;
height: 30vh;
margin-bottom: 3rem;
`;
const InputContainer = styled.div`
position: relative;
display: flex;
justify-content: center;
align-items: center;
`;
const Label = styled.span`
position: absolute;
left: 0;
padding-left: .2rem;
font-size: 1rem;
color: #e6e5e5;
pointer-events: none;
transition: 0.6s;
`;
const Input = styled.input`
width: 100%;
padding: .6rem 1.2rem;
border: none;
font-size: .9rem;
font-size: 1rem;
outline-color: transparent;
background-color: transparent;
border-bottom: 2px solid #e6e5e5;
color: white;
&:focus {
border-bottom: 2px solid #fff;
}
&:not(:placeholder-shown) + span,
&:focus + span {
color: white;
transform: translateX(10px);
transform: translateY(-25px);
font-size: 0.75rem;
}
`;
export default PersonalInfo
Sandbox: https://codesandbox.io/s/personal-info-form-component-h9652x
2
Answers
The issue seems to be from:
It works as intended if written as:
The standard at 13.1.3. The Placeholder-shown Pseudo-class: :placeholder-shown says:
In your case, however, you have
placeholder=''
as a placeholder which displays nothing. Firefox and Chrome right now don’t agree on if "displaying" an empty placeholder counts as displaying. I believe that Chrome is right in that case and not Firefox.A solution to your problem is to set
placeholder
to an actual value (which you should do anyways) and make the placeholder text transparent.