Requirement:

Suppose that there is a requirement such that when I click on a text field, its placeholder will move from inside that field to on top of it, becoming its label instead of the placeholder. This is a common requirement nowadays as this comes under the hood of User Experience.

Concept:

The common way is to wrap the input field inside a label, in HTML. This kind of HTML structure will actually associate with the parent label with the child input field. That means whenever you click on the label, the input field inside will get active. This kind of structure is not useful until another element inside the label is added like a DIV or SPAN. See the example below:

<label>
    <input type="text"></input>
    <span>Hello</hello>
<label>

Now, from the above HTML example, even if we click on the SPAN with hello text in it, the input field will get active because the click will propagate to its parent element LABEL which is associated with input field.

Note: This kind of approach is also useful to create custom checkboxes, radio buttons, dropdown (SELECT), datepicker etc..

Approach:

So as per above requirement, we need a label which acts as placeholder and when the input is active, it should act as a label. For that, lets place a SPAN element after INPUT field. This SPAN element will be positioned inside the INPUT field and style it to look as a placeholder and when the INPUT field is active, the positioning from the SPAN is removed and placed it above the INPUT field. Also, we should consider that when the INPUT field is not active and it has some value in it, the SPAN element should still be a label instead of placeholder.

Solution 1 (Using JavaScript):

See the Pen zEYadL by venkateshwar (@Mr_Green) on CodePen.

Solution 2 (Using only CSS)

The same solution can be achieved using just CSS by using :placeholder-shown pseudo selector. This pseudo selector is only supported in Modern browsers at the time of this writing.

Since, in CSS, we can style related to preceding adjacent selectors, lets place the SPAN after the INPUT element and then reverse their positioning by using flexbox and flex-direction: column-reverse. Here is the code:

See the Pen NaGVRm by venkateshwar (@Mr_Green) on CodePen.