Hey everybody! About a week ago I was faced with a development dilemma. I needed a search field that toggled open (via jQuery width animation) in my site header. After toggling open, the field would get focus; upon toggling shut, the field would blur and the value would be reset.

This seems pretty straightforward, right? Fortunately, it did turn out to be a simple implementation. HOWEVER. For the life of me, and a few fellow teammates, we could not get this toggling to work right in IE8. Naturally. The field would toggle open below where it should’ve been placed, pushing all subsequent content down, then as soon as you hovered over any of the elements surrounding the input – the field would jump back up into place. WTF, right? Hmfph.

Well, the decision was made to stop wasting time on it and just have the field open at all times in IE8. This is a fine solution. However, we’re relying on HTML5 placeholder text to display a “Search…” label. IE8 doesn’t support this attribute, and due to the styling of our header and search, there was then no clear indication of where the input was, or that it was even open. So we needed to either change the search styles entirely, or find a way to get that placeholder text working so the user could at least see where to click to enter their term.

It crossed my mind to just pull in one of the age-old JavaScript placeholder libraries, but it seemed like overkill for this one input. Then I had a smart idea. Let’s just fake it with CSS – a combination of :before content, background colors, and z-indexing. Here’s the code and demo of what I came up with:

See the Pen Faking Placeholder Text by Julie Cameron (@jewlofthelotus) on CodePen.

Let’s take a look at what’s going on here. In our Haml markup, we’ve got an .inputWrapper element with a data-placeholder value that wraps our actual input element. The data-placeholder attribute would hold the same value as your input element’s HTML5 placeholder value. For this demo, I’ve left the input placeholder out to mock legacy browser behavior.

If we take a look at the CSS, which I of course composed in Sass, we’ve got a few things going on here.

  1. .inputWrapper creates a new stacking context via position: relative;
  2. .inputWrapper:before grabs our data-placeholder value and sets it as the displayed content value.
  3. .inputWrapper:before also positions itself absolutely over the wrapper and places it self at the bottom of the stack via z-index: 0;
  4. Next up, we take our input and reset enough styles to basically make it invisible.
  5. The problem with this “invisible” input, is that IE8 basically pretends it’s not there when you click on it. To get around this, we need to trick IE8 into thinking our input isn’t actually invisible by giving it a background – in this case, containing a simple transparent image.
  6. Next up, we make sure our input is positioned above our faked placeholder text with z-index: 1;
  7. Allowing us to, when we click into the input and :focus it, apply a background color that conceals the placeholder text visible in the wrapper’s :before content

The last piece of the puzzle is using a tiny bit of JS to clear the input when the field is blurred.

And that’s it! I’ve, of course, IE8 conditionally loaded all of this code in my actual implementation so as not to interfere with the nicely functioning intended version.

A teammate made a nice comment to me about this, saying it was “the single best implementation” of faked placeholder text that he’d seen. That gave me the warm dev feels, and so I decided to share this solution with all of you. May your IE8 hacks now be less painful. Cheers!