DEV Community

Felix Guerin
Felix Guerin

Posted on

19 9

Floating input placeholders with HTML/CSS

Here is a cool way to make the placeholders "become" labels as the input receives focus.

Here is a pen with the final result.

First, you have to put the label AFTER the input in the HTML.

<form action="">
  <input type="text" id="fullName" name="fullName">
  <label for="fullName">Full Name</label>
</form>

This will ensure that we can target the label with our CSS.

Then, instead of giving the input a placeholder directly in the HTML, we will use our label as the placeholder. In order for the label to be inside the input, we can use transform: translate(). We can also use a lighter color to really make it look like a native placeholder.

Here is the relevant CSS for the initial state (the values used for the translation can vary depending on font size, positioning, etc.).

    label {
      color: #999;
      transform: translate(0.25rem, -1.5rem);
      transition: all 0.2s ease-out;
    }

Now, to position it on top of the text when the input is in focus, use the following.

    input:focus + label {
      color: #111;
      transform: translate(0, -2.75rem);
    }

It works!

But we still have a problem. The styles are are only applied to the label when the input is in focus. This means that if you type something in the input then focus elsewhere, the label will come back to it's original position.

To fix this, we will have to use the :placeholder-shown selector. This selector allows to style an element whenever an input's placeholder is, well, shown. In our case, we actually want to style the label when the placeholder is NOT shown, so we will also have to use the :not() selector. Finally, for this to work, your input has to have a placeholder. Since we want to use our label as the placeholder text, we can simply write an empty space as the placeholder value (an empty string "" will not work).

<form action="">
  <input type="text" id="fullName" name="fullName" placeholder=" ">
  <label for="fullName">Full Name</label>
</form>
    input:focus + label,
    input:not(:placeholder-shown) + label  {
      color: #111;
      transform: translate(0, -2.75rem);
    }

Now everything works like we want it to.

The :placeholder-shown selector is relatively new, but browser support is pretty good. The only browser to not recognize it is Edge. To remedy this, we can use a @supports query hack to check if the code is run in Edge (you can find more hacks like this at http://browserhacks.com/).

Usually, this hack is used write code that is only supported in Edge. Since we want the opposite, we can add not in front of the condition of the query.

We should also apply the final position to the label before anything else. This way, the Edge browser will display the labels on top of the inputs like a normal form, and the other browsers will apply the 'placeholder' styling to it.

label {
  display: block;
  transform: translate(0, -2.75rem);
}

@supports (not (-ms-ime-align:auto)) {
    label {
      color: #999;
      transform: translate(0.25rem, -1.5rem);
      transition: all 0.2s ease-out;
    }

    input:focus + label,
    input:not(:placeholder-shown) + label {
      color: #111;
      transform: translate(0, -2.75rem);
    }
}

Another possibility for this cool form style is to only move the label when a user types something. For this, you can simply remove the input:focus + label selector. Here is the result.

I hope you found this useful! Let me know in the comments.

Heroku

Amplify your impact where it matters most — building exceptional apps.

Leave the infrastructure headaches to us, while you focus on pushing boundaries, realizing your vision, and making a lasting impression on your users.

Get Started

Top comments (3)

Collapse
 
eugenman profile image
Eugen

Real hack without js. Thanks.

Collapse
 
titanhero profile image
Lex

Very cool...animus..Peace && Love

Collapse
 
flashfrozen profile image
flash-frozen

it's possible to use position:absolute; to prevent the label from taking up space on the page.

Playwright CLI Flags Tutorial

5 Playwright CLI Flags That Will Transform Your Testing Workflow

  • 0:56 --last-failed: Zero in on just the tests that failed in your previous run
  • 2:34 --only-changed: Test only the spec files you've modified in git
  • 4:27 --repeat-each: Run tests multiple times to catch flaky behavior before it reaches production
  • 5:15 --forbid-only: Prevent accidental test.only commits from breaking your CI pipeline
  • 5:51 --ui --headed --workers 1: Debug visually with browser windows and sequential test execution

Learn how these powerful command-line options can save you time, strengthen your test suite, and streamline your Playwright testing experience. Click on any timestamp above to jump directly to that section in the tutorial!

Watch Full Video 📹️

👋 Kindness is contagious

If you found this post useful, please drop a ❤️ or leave a kind comment!

Okay