The idea is for these text fields is not original, but it made for a nice exercise and research project. I avoided looking up other implementations.
I worked out three methods, all of which change the style on focus and when the text field is not blank. Having the change in style for a non-blank field was the tricky part. Ideally we could use the
:blank CSS selector, if only it was actually developed and supported. That leaves us with several options. Two methods use only CSS by using the
- The basics, the HTML and CSS used for all 3 methods
- Method 1, using the placeholder attribute
- Method 2, using the required attribute
Links to documentation: In the HTML examples the opening tags link to the relevant MDN web docs page for those elements, while in the CSS examples the property names, and pseudo classes and elements link to their MDN web docs pages.
The aim was to keep the HTML as simple and accessible as possible. What I ended up with was simply an
input element wrapped in a
label, with a
span element for the label text which we'll position using CSS.
The CSS is where the magic happens. We have our
span to provide basic style and (very important in this case) position.
First we define our label style. The height defines the height of our entire element, if we change this, we will need to change the height and / or padding of our
input element, and the position of our
span element. A cursor is defined to ensure the expected cursor for an
input element is shown wherever we hover on the element.
We are going to fill out our entire
label element with our
input using a combination of height and padding. The width we apply here determines the width of our entire element. Lastly we provide a bottom border and apply a transition value, to make style changes appear more smoothly.
input element filling out our
label, we need to position our helpful
span element. We move its relative position up, and make the initial text size a bit larger for when the
input value is still empty. To make our transition smooth and consistent, we give it the same value as we gave our
To make it clear we are hovering over the
input element we'll make the background a tad lighter. We'll keep this lighter background when it has focus too.
We want to move our label text out of the way when we start typing, to do that we reposition our
span element and resize the text when the
input has focus. As an extra focus indicator we'll also change the text color.
Lastly we define a text and border color on our
input to indicate focus. I disabled the standard outline, you should only do that when you provide adequate alternative focus indicators.
With this we get this text field that's pretty nice already, but after we type something things get ugly when we lose focus (isn't that a universal truth?).
Losing focus with style
Method one: the placeholder attribute
For this method we use the
placeholder attribute with a space, because we don't actually want a visible placeholder text. When an
input isn't blank, any placeholder text it has is hidden from view.
To directly target our
span when the
input isn't showing the placeholder, we use a combination of the
:placeholder-shown selectors in our CSS. Here we move the
span up, and resize the text.
This method is not recommended because screen readers may announce the value of the
placeholder attribute as "blank", which might lead to confusion. Aside from that, placeholders in general have accessibility considerations as the information they convey disappears when you start typing in the field. It also appears that the CSS selector is not supported in IE11 and Edge at the time of writing.
Method two: the required attribute
For this method we use the required attribute on the
input element. This will make it so we can apply a style using the
:valid selector in CSS. When no additional requirements are given, a required field will be deemed valid as long as it is not empty.
To directly target our
span when the
input isn't blank, we use the following bit of CSS.
This method is not recommended unless every field in your form is required. In that case you should make sure this is communicated to the user in a clear way, and you'll want to provide adequate error messages.
onkeyup event like this.
Our function is going to check if the value is empty. If it's not empty we add a class to the text field, if it is empty we simply remove the class.
Notes on accessibility
While this element is accessible in a technical and semantical sense using methods 2 or 3, you should always consider the text sizes and color contrast, and provide adequate label text. If a field is required, be sure to signal this clearly to the user with explanation of any requirements.