CSS Animation

Floating label

Credit - Frontend Master Phuoc Nguyen

TailwindCSS + ReactJS version of https://phuoc.ng/collection/css-animation/floating-label/

Please read the original blog for the rationale behind these solutions.

Markup

export default function App() {
  return (
    <div className='w-64 relative'>
      <label className='bg-white absolute top-0 left-0 translate-x-4 -translate-y-2/4 transition-transform ease-out duration-200' htmlFor="emailAddress">Email Adress</label>
      <input className="border rounded py-2 px-1 h-10 w-full" id="emailAddress" type="text"/>
    </div>
  );
}

Floating Label Animation

import React from 'react';
import clsx from 'clsx/lite';

export default function App() {
  const [shouldFloat, setShouldFloat] = React.useState(false);

  return (
    <div className='w-64 relative'>
      <label 
        className={clsx(shouldFloat ? '-translate-y-full translate-x-0 text-sm' : '-translate-y-2/4 translate-x-4', 'bg-white absolute top-0 left-0 transition-transform ease-out duration-200')} 
        htmlFor="emailAddress"
      >
        Email Adress
      </label>
      <input 
        className="border rounded py-2 px-1 h-10 w-full" id="emailAddress" type="text"
        onFocus={() => { setShouldFloat(true) }} 
        onBlur={() => { setShouldFloat(false) }} 
      />
    </div>
  );
}

CSS only solution

Using: https://tailwindcss.com/docs/hover-focus-and-other-states#styling-based-on-sibling-state

peer-focus:-translate-y-full peer-focus:translate-x-0
import React from 'react';
import clsx from 'clsx/lite';

export default function App() {
  return (
    <div className='w-64 relative'>
      <input className="peer border rounded py-2 px-1 h-10 w-full" id="emailAddress" type="text"/>
      <label className='peer-focus:-translate-y-full peer-focus:translate-x-0 bg-white absolute top-0 left-0 translate-x-4 -translate-y-2/4 transition-transform ease-out duration-200' htmlFor="emailAddress">Email Adress</label>
    </div>
  );
}

Using the placeholder attribute

Using https://tailwindcss.com/docs/hover-focus-and-other-states#arbitrary-peers

peer-[:not(:placeholder-shown)]:opacity-100 peer-[:not(:placeholder-shown)]:-translate-y-full
export default function App() {
  return (
    <div className='w-64 relative'>
      <input 
        className="peer border rounded py-2 px-1 h-10 w-full" 
        id="emailAddress" 
        type="text"
        placeholder="Email address"
      />
      <label className='opacity-0 peer-[:not(:placeholder-shown)]:opacity-100 peer-[:not(:placeholder-shown)]:-translate-y-full bg-white absolute top-0 left-0 transition-transform ease-out duration-200' htmlFor="emailAddress">Email Adress</label>
    </div>
  );
}
Last Update: 11:49 - 22 April 2024

On this page