Floated Label Pattern with CSS Only
I came across Brad Frost's post about the Floated Label Pattern and instantly thought, "I think you can do this in CSS" and set out to prove it.
It turned out to be a little trickier than expected but I created a quick proof of concept:
The Example
How it works
I use the :valid
pseudo class along with the pattern
attribute on the input to style the associated label accordingly.
.field { position:relative; font-family: Arial; text-transform:uppercase; font-weight:bold; display:inline-block; }
label { position:absolute; left:0; top:0; transition: all .2s linear; color:#999; font-size:10px; }
input { margin-top:15px; border:1px solid #999; padding:3px 2px; }
input:invalid + label { top:3px; opacity:0; }
input:valid + label { opacity:1; top:0; }
input:focus { outline:none; }
input:focus + label { color:#33A; }
Problems with this
- The label has to appear after the input. I'm using CSS trickery to get it into place. I'd love to be able to put the label first in the content but there's no way to style an element based on the content that comes after it.
- It relies on the pattern attribute and the :valid pseudo class, which means that they can't be used for other things like validating email addresses. It'd be nice if there were a different pseudo class that I could use that detected presence of content.
Conversation
Very cool. Problem one will be solved by the subject select in CSS level 4. At least I think that's what this is talking about:
CSS Selectors4 Subject
As I understand that, it would let you put the label first and then write:
Which, would be much nicer, though of course there's no browser support and it appear the
!
syntax is still up for debate.why not using input:empty / input:not(:empty) instead?
I like the general hacky approach. Of course, a few caveats on top of your own:
- from an accessibility point of view, you should explicitly associate your label with the relevant input. Although screenreaders may be able to use heuristics (by looking for adjacent text and announcing the placeholder attribute, although the spec clearly states that it's not a substitute for a more explicit label) to error-correct and try and announce the fields anyway.
- screenreaders will also generally announce that a field is "required" when the attribute is present. this may be confusing when the field is not, in fact, required. Additionally, some screenreaders will also announce that an input with validation constraints (such as "required") is currently "invalid".
So, with the above two points in mind, JAWS/Firefox for instance announces your first input as "First name edit invalid required entry...type in text"
- in actual use, this will also require the novalidate attribute on the form to suppress the browser's built-in validation if those required fields are actually optional.
@GREGOR: CSS only recognizes the initial value of the input and doesn't update when the value changes.
Couldn't you use the sibling selector '~' instead of '+', and thus be able to put the label before the input? You'd have to wrap each label and input in a span or div. Browser support is less good for sibling selector I think though
sorry, my fault, :empty is to select empty HTML nodes, not to select empty input tags. They way Jonathan did it seems the only way to do it in CSS-only
Hey Lu, the ~ selector is siblings after the element, not before it - would have been great!
Ach. Bummer
good!you NB!
If designers weren't so silly we wouldn't have this problem to start with...