(please have a look at the pages-source for the source-code)

This first example is fully CSS (no JS).

The only requirement is that the input element must be placed right before the label.

An issue arises when you fill a field that was empty: as you can see the label does not stay above, even by specifying input:not([value=""]). Same problem with an already filled flied that you would empty. This is because CSS only sees the input's value attribute (in the HTML code) and not the node's value property. In order to make it work as one would expect, we have to use JavaScript.

JavaScript would fill a data-* attributes, forming a "flag" that would tell to CSS if the label should stay at the top. Demo:

And with some textareas: