So to sum up everything: I am using NextJs, React and Tailwind. I created a floating label code for which I took from https://flowbite.com/docs/forms/floating-label/. In the flowbite example the label is kept on top when the input is not empty, I am trying to achieve the same result with pure tailwind.I assume there are some behind the scenes classes that set the styles for this floating label that actually keep it on top in the flowbite example, but the inline-styles there don't do the trick. I have seen examples of how to solve it with JQuery, but it is irrelevant in my case.
'use client'
import { ChangeEvent } from "react"
type InputFieldProps = {
name: string,
onChange: (e: ChangeEvent<HTMLInputElement>) => void,
id: string,
type: string,
htmlFor: string,
value: string,
}
const InputField: React.FC<InputFieldProps> = ({ name, id, type, htmlFor, value, onChange }) => {
return (
<div className="relative">
<input
type={type}
id={id}
value={value}
onChange={onChange}
className={`font-roboto tracking-body-large w-[360px] h-[40px] px-2 text-base text-gray-900 bg-transparent rounded-[4px] border-[1px] border-[#CAC4D0] focus:outline-none focus:border-[#6750A4] peer`}
required
/>
<label
htmlFor={htmlFor}
className={`absolute text-base text-[#49454F] peer-focus:text-[#6750A4] duration-300 transform scale-75 top-2 z-10 origin-[0] bg-white px-2 peer-focus:px-2 peer-placeholder-shown:scale-100 peer-placeholder-shown:-translate-y-1/2 peer-placeholder-shown:top-1/2 peer-focus:top-[-0.25rem] peer-focus:scale-50 peer-focus:-translate-y-2 start-1 hover:cursor-text ${value ? '' : '' }`}
>
{name}
</label>
</div>
);
};
export default InputField;
Have the peer-placeholder-shown:
and peer-focus:
classes only applied when the value
is empty. When value
is not empty, have the peer-focus:
classes applied but without the peer-focus:
variant attached:
const InputField = ({ name, id, type, htmlFor, value, onChange }) => {
return (
<div className="relative">
<input
type={type}
id={id}
value={value}
onChange={onChange}
className={`font-roboto tracking-body-large w-[360px] h-[40px] px-2 text-base text-gray-900 bg-transparent rounded-[4px] border-[1px] border-[#CAC4D0] focus:outline-none focus:border-[#6750A4] peer`}
required
/>
<label
htmlFor={htmlFor}
className={`absolute text-base text-[#49454F] peer-focus:text-[#6750A4] duration-300 top-2 z-10 origin-[0] bg-white px-2 start-1 hover:cursor-text ${
value ? "top-[-0.25rem] scale-50 -translate-y-2" : "scale-75 peer-placeholder-shown:scale-100 peer-placeholder-shown:-translate-y-1/2 peer-placeholder-shown:top-1/2 peer-focus:top-[-0.25rem] peer-focus:scale-50 peer-focus:-translate-y-2"
}`}
>
{name}
</label>
</div>
);
};
function App() {
const [value, setValue] = React.useState('');
return <InputField
name="foo"
id="foo"
type="text"
htmlFor="foo"
value={value}
onChange={({ target }) => setValue(target.value)}
/>
}
ReactDOM.createRoot(document.getElementById("app")).render(<App />);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js" integrity="sha512-8Q6Y9XnTbOE+JNvjBQwJ2H8S+UV4uA6hiRykhdtIyDYZ2TprdNmWOUaKdGzOhyr4dCyk287OejbPvwl7lrfqrQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js" integrity="sha512-MOCpqoRoisCTwJ8vQQiciZv0qcpROCidek3GTFS6KTk2+y7munJIlKCVkFCYY+p3ErYFXCjmFjnfTTRSC1OHWQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdn.tailwindcss.com/3.3.5"></script>
<div id="app"></div>