10

After a long struggle, I've finally found the only way to clear autofill styling in every browser:

$('input').each(function() {
    var $this = $(this);
            
    $this.after($this.clone()).remove();
});

However, I can’t just run this in the window load event; autofill applies sometime after that. Right now I’m using a 100ms delay as a workaround:

// Kill autofill styles
$(window).on({
    load: function() {
        setTimeout(function() {
            $('.text').each(function() {
                var $this = $(this);
                
                $this.after($this.clone()).remove();
            });
        }, 100);
    }
});

and that seems safe on even the slowest of systems, but it’s really not elegant. Is there some kind of reliable event or check I can make to see if the autofill is complete, or a cross-browser way to fully override its styles?

Ry-
  • 218,210
  • 55
  • 464
  • 476

4 Answers4

13

If you're using Chrome or Safari, you can use the input:-webkit-autofill CSS selector to get the autofilled fields.

Example detection code:

setInterval(function() {
    var autofilled = document.querySelectorAll('input:-webkit-autofill');
    // do something with the elements...
}, 500);
Ry-
  • 218,210
  • 55
  • 464
  • 476
Tyilo
  • 28,998
  • 40
  • 113
  • 198
  • I'm aware of that selector. However, I neither want any `setInterval` nor `setTimeout` in my code. – Ry- Mar 17 '12 at 18:11
  • 1
    This is BY FAR the best solution I have seen to the problem of Chrome and autofill inputs. input:-webkit-autofill is way better than polling and setTimeout(), etc. THANK YOU so much for actually providing an answer to this long-standing issue! – ChrisN Jun 04 '15 at 21:17
  • 3
    @ChrisN, this answer uses `setInterval`. – Ry- Jul 07 '15 at 16:47
2

There's a bug open over at http://code.google.com/p/chromium/issues/detail?id=46543#c22 relating to this, it looks like it might (should) eventually be possible to just write over the default styling with an !important selector, which would be the most elegant solution. The code would be something like:

input {
    background-color: #FFF !important;
}

For now though the bug is still open and it seems like your hackish solution is the only solution for Chrome, however a) the solution for Chrome doesn't need setTimeout and b) it seems like Firefox might respect the !important flag or some sort of CSS selector with high priority as described in Override browser form-filling and input highlighting with HTML/CSS. Does this help?

Community
  • 1
  • 1
conartist6
  • 417
  • 4
  • 15
  • Unfortunately, it does actually need `setTimeout`, and Firefox has the same problem. Believe me, I'm continuing to try variations of them both as we speak :) – Ry- Mar 17 '12 at 19:13
  • The thread I tacked on at the end also has a solution that has been noted as working, which is to use the input:focus selector and use onload javascript to focus each form element in turn. – conartist6 Mar 18 '12 at 16:15
  • I did see that, but oddly, it doesn't seem to work for me. I'm using Chrome Canary, so maybe *that* "bug" was fixed :) – Ry- Mar 18 '12 at 16:54
0

I propose you avoiding the autofill in first place, instead of trying to trick the browser

<form autocomplete="off">

More information: http://www.whatwg.org/specs/web-forms/current-work/#the-autocomplete

If you want to keep the autofill behaviour but change the styling, maybe you can do something like this (jQuery):

$(document).ready(function() { 
  $("input[type='text']").css('background-color', 'white');
});
  • 1
    Please read the comments. We have established that I *do not want to turn autocomplete off*. As for setting the `background-color` to `white`, it doesn't work. This is precisely why I need the workaround. – Ry- Apr 02 '12 at 18:30
  • Just read, sorry @minitech i'm sorry i really think you will need the timeout, as the forms gets filled by the browser itself after a bit, not the DOM – Marcos Besteiro López Apr 03 '12 at 09:40
-1
$(window).load(function()
{
    if ($('input:-webkit-autofill'))
    {
        $('input:-webkit-autofill').each(function()
        {
            $(this).replaceWith($(this).clone(true,true));
        });
        // RE-INITIALIZE VARIABLES HERE IF YOU SET JQUERY OBJECT'S TO VAR FOR FASTER PROCESSING
    }
});

I noticed that the jQuery solution you posted does not copy attached events. The method I have posted works for jQuery 1.5+ and should be the preferred solution as it retains the attached events for each object. If you have a solution to loop through all initialized variables and re-initialize them then a full 100% working jQuery solution would be available, otherwise you have to re-initialize set variables as needed.

for example you do: var foo = $('#foo');

then you would have to call: foo=$('#foo');

because the original element was removed and a clone now exists in its place.

  • It's definitely not my preferred solution, though, because a) it uses browser sniffing, which is wrong because Firefox has the same bug and b) it still doesn't work, because there is no timeout. – Ry- Feb 15 '13 at 14:54
  • What version of Firefox has the bug? So I can edit my comment accordingly, because my current version doesn't exhibit that behavior. If you don't like browsing sniffing just run an if statement to see if that element exists. The main reason you need a check of some sort is because some variables might need to be re-initialized since the original copies are no longer present. Also, if you need a timeout it's easy to plug in, but mine has worked flawlessly without one being present which is why I left it out from my response. – Richard Vannauker Feb 16 '13 at 14:35