[html] Disabling Chrome Autofill

I have been running into issues with the chrome autofill behavior on several forms.

The fields in the form all have very common and accurate names, such as "email", "name", or "password", and they also have autocomplete="off" set.

The autocomplete flag has successfully disabled the autocomplete behavior, where a dropdown of values appear as you start typing, but has not changed the values that Chrome auto-populates the fields as.

This behavior would be ok except that chrome is filling the inputs incorrectly, for example filling the phone input with an email address. Customers have complained about this, so it's verified to be happening in multiple cases, and not as some some sort of result to something that I've done locally on my machine.

The only current solution I can think of is to dynamically generate custom input names and then extract the values on the backend, but this seems like a pretty hacky way around this issue. Are there any tags or quirks that change the autofill behavior that could be used to fix this?

This question is related to html forms google-chrome autocomplete autofill

The answer is


Finally I think I came with a decent solution. Understanding better how the dropdown works with Chrome helped :) Basically, the dropdown will be displayed when you focus the input and when you generate a mouse down event when you are typing an entry which matches with what Chrome has in memory. Keeping that in mind, and that Chrome does it for certain inputs when they have default names like "name", "email", etc. then we just need to remove the name when the dropdown is going to be displayed and add it back after :) I wanted to use a solution which can make it work just by adding the attribute autocomplete off. I thought it made sense. This is the code:

Solution 1

jQuery('body').on('mousedown','[name="name"][autocomplete="off"], [name="email"][autocomplete="off"]',function(e){
    e.stopImmediatePropagation();
    if(typeof this.currentName =="undefined")
        this.currentName=jQuery(this).attr('name');
    jQuery(this).attr('name','');
});

jQuery('body').on('blur','[autocomplete="off"]',function(e){
    e.stopImmediatePropagation();
    jQuery(this).attr('name',this.currentName);
});

Solution 2 (My Favourite One)

The solution I described above will remove the name of the input until we remove the focus (blur), in that moment it will put the original name back. But might happen that we are interested on having access to the input through its name attribute while we are typing. Which means that we need to put the name back right after each input. This solution, basically is based on the first solution. In this case, we will add the name on key down, and put it back on keyup. I think this is more neat for compatibility with what the "autocomplete off" behaviour should be. Anyway this is the code:

jQuery('body').on('mousedown keydown','[name="name"][autocomplete="off"], [name="email"][autocomplete="off"]',function(e){
    e.stopImmediatePropagation();
    if(typeof this.currentName =="undefined")
        this.currentName=jQuery(this).attr('name');
    jQuery(this).attr('name','');
});
jQuery('body').on('blur keyup','[autocomplete="off"]',function(e){
    e.stopImmediatePropagation();
    if(typeof this.currentName !="undefined")
        jQuery(this).attr('name',this.currentName);
});

Please notice that for Solution 1 and 2, I just took the cases where the input name is "name" and "email". For any other case where this attribute makes Chrome generate the dropdown you will have to add it in the selector for the mouse down event.

Solution 3

This solution is a lot more messy. I did not realize that the behaviour we are trying to correct is just based on those inputs with a specific name like "name, email, etc". The approach of this solution was for that case that Chrome display for other names that we don't know a priori. It would be a very generic solution. I do not like as much as the other 2, basically because there could be a small flicker when we press on the delete key. I will explain that bellow.

I found out that the dropdown was appearing after a second click on the input but not on the first click when you focus the first time on the input. I bind a "mousedown" event for all this elements where the handler basically detect if it is already focused on the input and in case it detects another "mouse down", force a .blur() and then .focus() after, preventing the dropdown on the second click once it is focused. I hope, it is clear, just in case here is the code that I used:

jQuery('body').on('mousedown','[autocomplete="off"]',function(e){
    e.stopImmediatePropagation();
    if(jQuery(this).is(':focus')) {
        jQuery(this).blur();
        jQuery(this).focus();
    }
});

In the other hand, in order to prevent the dropdown while you are typing in case it matches with Chrome suggestions... This is a little bit tricky. I just decided to replace the default behaviour of an input while user types. The dropdown evaluates the input on mouse down, so I prevent the default behaviour for alphanumerics, space, etc. The only problem is with Command,Ctrl and delete. For this case I had to bind also an event on mouse up. It allows the default behaviour in the first two cases so you can make copy, and paste, or select all. In the case of the delete, I have to allow the default behaviour, but if after deleting a character the input matches with Chrome suggestions, then again it was showing the dropdown. For this case I had to use the same trick of blur and focus. The only inconvenience I found on this is that since we are cancelling the behaviour on keyup, and chrome tries to show it on keydown, there is a small flicker. Anyway, this is the best I could do. Probably it will require for filtering of characters at one point. I just added the conditions made more sense for now. This is the second part of the code:

jQuery('body').on('keydown','[autocomplete="off"]',function(e){
    e.stopImmediatePropagation();
    var ctrlKey = 17,cmKey = 91;
    var charCode = e.which || e.keyCode;

    if(charCode!=16 && this.commandDown != true && this.ctrlDown != true && ((charCode>47 && charCode<58)||(charCode>64 && charCode<91)||(charCode>96 && charCode<123)||charCode==0 || charCode==32)){ 
        e.preventDefault();
        var charStr = String.fromCharCode(charCode);
        if(!e.shiftKey)
            charStr = charStr.toLowerCase(charStr);
        $(this).val($(this).val() + charStr);
    }else{
        if (charCode == cmKey) this.commandDown = true;
        if (charCode == ctrlKey) this.ctrlDown = true;
    }
});
jQuery('body').on('keyup','[autocomplete="off"]',function(e){
    e.stopImmediatePropagation();
    var allowed=[8];//Delete
    var ctrlKey = 17,cmKey = 91;
    var charCode = e.which || e.keyCode;

    if (charCode == cmKey) {this.commandDown = false};
    if (charCode == ctrlKey) {this.ctrlDown = false};
    if(allowed.indexOf(charCode)>=0 || (this.commandDown!=false && this.ctrlDown!=false)){
        jQuery(this).blur();
        jQuery(this).focus();
}

As I said this solution is much more messy. It was the first one I used until I realized that the dropdown just appeared for certain input names.

Sorry for writing so much, I just wanted to be sure everything was clear. I hope it helps.


Different solution, webkit based. As mentioned already, anytime Chrome finds a password field it autocompletes the email. AFAIK, this is regardless of autocomplete = [whatever].

To circumvent this change the input type to text and apply the webkit security font in whatever form you want.

.secure-font{
-webkit-text-security:disc;}

<input type ="text" class="secure-font">

From what I can see this is at least as secure as input type=password, it's copy and paste secure. However it is vulnerable by removing the style which will remove asterisks, of course input type = password can easily be changed to input type = text in the console to reveal any autofilled passwords so it's much the same really.


Also have to set the value to empty (value="") besides autocomplete="off" to make it work.


What I have done it to change the input type="text" to a multi line input ie.

 overflow-x:hidden;
 overflow-y:hidden;
 vertical-align:middle;
 resize: none;

A quick explanation of the code: The overflow-x and -y hidden wil disable the scroll buttons on the right of the textarea box. The vertial algin will align the lable vertical middle with the text area and the resize: none will disable the resize grabber at the bottom right of the textarea.

In essance it means that your textarea will appear like a textbox, but with chrome autofill off.


Thought i'd post my fix. Found that you can't use display:none so i came up with a quick and dirty solution to just make the fake input small and move it out of sight. So far so good until they break it again.

_x000D_
_x000D_
                    <input id="FakePassword" type="password" style="float:left;position:relative;height:0;width:0;top:-1000px;left:-1000px;" />
_x000D_
_x000D_
_x000D_


For username password combos this is an easy issue to resolve. Chrome heuristics looks for the pattern:

<input type="text">

followed by:

<input type="password">

Simply break this process by invalidating this:

<input type="text">
<input type="text" onfocus="this.type='password'">

Jan 2021: autocomplete="off" does work as expected now (tested on Chrome 88 macOS).


Sept 2020: autocomplete="chrome-off" disables Chrome autofill.


Original answer, 2015:

For new Chrome versions you can just put autocomplete="new-password" in your password field and that's it. I've checked it, works fine.

Got that tip from Chrome developer in this discussion: https://bugs.chromium.org/p/chromium/issues/detail?id=370363#c7

P.S. Note that Chrome will attempt to infer autofill behavior from name, id and any text content it can get surrounding the field including labels and arbitrary text nodes. If there is a autocomplete token like street-address in context, Chrome will autofill that as such. The heuristic can be quite confusing as it sometimes only trigger if there are additional fields in the form, or not if there are too few fields in the form. Also note that autocomplete="no" will appear to work but autocomplete="off" will not for historical reasons. autocomplete="no" is you telling the browser that this field should be auto completed as a field called "no". If you generate unique random autocomplete names you disable auto complete.

If your users have visited bad forms their autofill information may be corrupt. Having them manually go in and fix their autofill information in Chrome may be a necessary action from them to take.


Answer of Jobin Jose gave me a start. Here is what works for me:

<input type="password" name="password" id="password_fake" style="display:none;" />
<input type="password" name="password"/>

Be sure to not have autocomplete="off", which spoils the solution.


The most recent solution of adding autocomplete="new-password" to the password field works great for preventing Chrome from autofilling it.

However, as sibbl pointed out, this doesn't prevent Chrome from asking you to save the password after the form submission completes. As of Chrome 51.0.2704.106, I found that you can accomplish this by adding a invisible dummy password field that also has the attribute autocomplete="new-password". Note that "display:none" does not work in this case. e.g. Add something like this before the real password field:

<input type="password" autocomplete="new-password" 
style="visibility:hidden;height:0;width:1px;position:absolute;left:0;top:0">`

This only worked for me when I set the width to a non-zero value. Thanks to tibalt and fareed namrouti for the original answers.


I don't know why, but this helped and worked for me.

<input type="password" name="pwd" autocomplete="new-password">

I have no idea why, but autocomplete="new-password" disables autofill. It worked in latest 49.0.2623.112 chrome version.


Sometimes even autocomplete=off won't prevent filling in credentials into wrong fields.

A workaround is to disable browser autofill using readonly-mode and set writable on focus:

 <input type="password" readonly onfocus="this.removeAttribute('readonly');"/>

The focus event occurs at mouse clicks and tabbing through fields.

Update:

Mobile Safari sets cursor in the field, but does not show virtual keyboard. This new workaround works like before, but handles virtual keyboard:

<input id="email" readonly type="email" onfocus="if (this.hasAttribute('readonly')) {
    this.removeAttribute('readonly');
    // fix for mobile safari to show virtual keyboard
    this.blur();    this.focus();  }" />

Live Demo https://jsfiddle.net/danielsuess/n0scguv6/

// UpdateEnd

Explanation: Browser auto fills credentials to wrong text field?

filling the inputs incorrectly, for example filling the phone input with an email address

Sometimes I notice this strange behavior on Chrome and Safari, when there are password fields in the same form. I guess, the browser looks for a password field to insert your saved credentials. Then it autofills username into the nearest textlike-input field , that appears prior the password field in DOM (just guessing due to observation). As the browser is the last instance and you can not control it,

This readonly-fix above worked for me.


With chrome, if you surround an input with a label and within the label, put the words street, address or both, it will ignore any attempt at disabling autofill.

<label for="searchAddress" class="control-label"> Street Address <input type="text" class="form-control" name="searchAddress></label>

Chrome detects keywords within the label to figure out the input type. It likely does this with other key words as well.


If you're having issues with keeping placeholders but disabling the chrome autofill I found this workaround.

Problem

HTML

<div class="form">
    <input type="text" placeholder="name"><br>
    <input type="text" placeholder="email"><br>
    <input type="text" placeholder="street"><br>
</div>

http://jsfiddle.net/xmbvwfs6/1/

The above example still produces the autofill problem, but if you use the required="required" and some CSS you can replicate the placeholders and Chrome won't pick up the tags.

Solution

HTML

<div class="form">
    <input type="text" required="required">
    <label>Name</label>  
    <br>
    <input type="text" required="required">
    <label>Email</label>    
    <br>
    <input type="text" required="required">
    <label>Street</label>    
    <br>
</div>

CSS

input {
    margin-bottom: 10px;
    width: 200px;
    height: 20px;
    padding: 0 10px;
    font-size: 14px;
}
input + label {
    position: relative;
    left: -216px;
    color: #999;
    font-size: 14px;
}
input:invalid + label { 
    display: inline-block; 
}
input:valid + label { 
    display: none; 
}

http://jsfiddle.net/mwshpx1o/1/


After months and months of struggle, I have found that the solution is a lot simpler than you could imagine:

Instead of autocomplete="off" use autocomplete="false" ;)

As simple as that, and it works like a charm in Google Chrome as well!


August 2019 update (credit to @JonEdiger in comments)

Note: lots of info online says the browsers now treat autocomplete='false' to be the same as autocomplete='off'. At least as of right this minute, it is preventing autocomplete for those three browsers.

Set it at form level and then for the inputs you want it off, set to some non-valid value like 'none':

<form autocomplete="off"> 
  <input type="text" id="lastName" autocomplete="none"/> 
  <input type="text" id="firstName" autocomplete="none"/>
</form>

In case display: none doesn't work this is also possible and it seems to be working (Chrome v60.0.3112.113):

.hidden-fields {
    opacity: 0;
    float: left;
    height: 0px;
    width: 0px;
}

<input type="text" name="username" class="hidden-fields"> 
<input type="password" name="password" class="hidden-fields">

<your actual login fields></your actual login fields>

Previously entered values cached by chrome is displayed as dropdown select list.This can be disabled by autocomplete=off , explicitly saved address in advanced settings of chrome gives autofill popup when an address field gets focus.This can be disabled by autocomplete="false".But it will allow chrome to display cached values in dropdown.

On an input html field following will switch off both.

Role="presentation" & autocomplete="off"

While selecting input fields for address autofill Chrome ignores those input fields which don't have preceding label html element.

To ensure chrome parser ignores an input field for autofill address popup a hidden button or image control can be added between label and textbox. This will break chrome parsing sequence of label -input pair creation for autofill. Checkboxes are ignored while parsing for address fields

Chrome also considers "for" attribute on label element. It can be used to break parsing sequence of chrome.


<input readonly onfocus="this.removeAttribute('readonly');" type="text">

adding readonly attribute to the tag along with the onfocus event removing it fixes the issue


In 2016 Google Chrome started ignoring autocomplete=off though it is in W3C. The answer they posted:

The tricky part here is that somewhere along the journey of the web autocomplete=off become a default for many form fields, without any real thought being given as to whether or not that was good for users. This doesn't mean there aren't very valid cases where you don't want the browser autofilling data (e.g. on CRM systems), but by and large, we see those as the minority cases. And as a result, we started ignoring autocomplete=off for Chrome Autofill data.

Which essentially says: we know better what a user wants.

They opened another bug to post valid use cases when autocomplete=off is required

I haven't seen issues connected with autocomplete throught all my B2B application but only with input of a password type.

Autofill steps in if there's any password field on the screen even a hidden one. To break this logic you can put each password field into it's own form if it doesn't break your own page logic.

<input type=name >

<form>
    <input type=password >
</form>

The only way that works for me was:(jQuery required)

$(document).ready(function(e) {
    if ($.browser.webkit) {
        $('#input_id').val(' ').val('');
    }
});

My workaround since none of the above appear to work in Chrome 63 and beyond

I fixed this on my site by replacing the offending input element with

<p class="input" contenteditable="true">&nbsp;</p>

and using jQuery to populate a hidden field prior to submission.

But this is a truly awful hack made necessary by a bad decision at Chromium.


I've tried all the mentioned advises but none of them worked. I'm using a google places autocomplete on the specifik input, and it is quite ugly if there is a google chrome autofill above the google places autocomplete list. Even setting autocomplete="anything" is useless because the autocomplete plugin itself setf this attr to "off" and it is totally ignored by chrome.

so my sollution is:

var fixAutocomplete = window.setInterval(function(){
    if ($('#myinput').attr('autocomplete') === 'false') {
        window.clearInterval(fixAutocomplete);  
    }

    $('#myinput').attr('autocomplete', 'false');
}, 500);

last time I checked Google updated their autofill in JAN 2017, the solution that worked for me was adding another input and hiding it after it has been populated.

 <input type="text" id="phone_number" name="phone_number" value="">
 <input type="text" id="dummy_autocomplete">


<script type="text/javascript">
        $('#dummy_autocomplete').hide();
</script>

try whit a blank space in the value :

<input type="email" name="email" value="&nbsp;">
<input type="password" name="password" value="&nbsp;">

chrome 54.0.2840.59


On Chromium 53.0.2785.92 (64-bit) the following worked

<div style="visibility:hidden">
    <input type="text" name="fake_username_remembered">
    <input type="password" name="fake_password_remembered">
</div>

display:none doesn't work


For me, simple

<form autocomplete="off" role="presentation">

Did it.

Tested on multiple versions, last try was on 56.0.2924.87


Pure HTML solution:

(No javascript needed, no css needed and no hidden inputs needed)

<form autoComplete="new-password" ... >
        <input name="myInput" type="text" autoComplete="off" id="myInput" placeholder="Search field" />
</form>

Notes:

  • form does not necessarily need to be the direct parent of the input element
  • input needs a name attribute

Mike Nelsons provided solution did not work for me in Chrome 50.0.2661.102 m. Simply adding an input element of the same type with display:none set no longer disables the native browser auto-complete. It is now necessary to duplicate the name attribute of the input field you wish to disable auto-complete on.

Also, to avoid having the input field duplicated when they are within a form element you should place a disabled on the element which is not displayed. This will prevent that element from being submitted as part of the form action.

<input name="dpart" disabled="disabled" type="password" style="display:none;">
<input name="dpart" type="password">
<input type="submit">

Use css text-security: disc without using type=password.

html

<input type='text' name='user' autocomplete='off' />
<input type='text' name='pass' autocomplete='off' class='secure' />

or

<form autocomplete='off'>
    <input type='text' name='user' />
    <input type='text' name='pass' class='secure' />
</form>

css

input.secure {
    text-security: disc;
    -webkit-text-security: disc;
}

Instead of "this is what worked for me" answers and other answers that look like complete hacks... This is currently how chrome (and the latest spec) will handle the autocomplete attributes on your input elements:

https://developers.google.com/web/fundamentals/design-and-ui/input/forms/label-and-name-inputs?hl=en

TLDR: Add autocomplete='<value>' on your inputs, where <value> should be any string that defines what the field is for. This works similarly to the name attribute. Use the suggested values on the link above where possible.

Also, remove the autocomplete attribute from your form


Jan 20 chrome update

None of the solutions above, including adding fake fields or setting autocomplete=new-password works. Yes with these chrome will not autocomplete but when you enter the password field it will suggest the password again.

I found that if you remove the password field and then add it again without an id then chrome does not autofill it and does not suggest the password on entry.

Use a class to get get the password value instead of an id.

For firefox there is still a need to add a dummy element.

This solution also allows allowing/forbidding autocomplete based on a flag:

html:

<!-- form is initially hidden, password field has a dummy id and a class 'id' -->
<form id="loginForm" style="display:none;">
   <span>email:</span><input type="text" placeholder="Email" id="loginEmailInputID"/>
   <span>Password:</span><input class="loginPasswordInput" type="password" placeholder="Password" id="justForAutocomplete"/>
</form>

page load:

function hideAutoComplete(formId) {
    let passwordElem=$('#'+formId+' input:password'), prev=passwordElem.prev();
    passwordElem.remove();
    prev.after($('<input type="password" style="display:none">'), passwordElem.clone().val('').removeAttr('id'));
}

if (!allowAutoComplete) hideAutoComplete('loginForm');
$('#loginForm').show();

when you need the password:

$('.loginPasswordInput').val();

In some cases, the browser will keep suggesting autocompletion values even if the autocomplete attribute is set to off. This unexpected behavior can be quite puzzling for developers. The trick to really forcing the no-autocompletion is to assign a random string to the attribute, for example:

autocomplete="nope"

Try this. I know the question is somewhat old, but this is a different approach for the problem.

I also noticed the issue comes just above the password field.

I tried both the methods like

<form autocomplete="off"> and <input autocomplete="off"> but none of them worked for me.

So I fixed it using the snippet below - just added another text field just above the password type field and made it display:none.

Something like this:

<input type="text" name="prevent_autofill" id="prevent_autofill" value="" style="display:none;" />
<input type="password" name="password_fake" id="password_fake" value="" style="display:none;" />
<input type="password" name="password" id="password" value="" />

Hope it will help someone.


As per Chromium bug report #352347 Chrome no longer respects autocomplete="off|false|anythingelse", neither on forms nor on inputs.

The only solution that worked for me was to add a dummy password field:

<input type="password" class="hidden" />
<input type="password" />

It is so simple and tricky :)

google chrome basically search for every first visible password element inside the <form>, <body> and <iframe> tags to enable auto refill for them, so to disable this you need to add a dummy password element as the following:

    • if your password element inside a <form> tag you need to put the dummy element as the first element in your form immediately after <form> open tag

    • if your password element not inside a <form> tag put the dummy element as the first element in your html page immediately after <body> open tag

  1. You need to hide the dummy element without using css display:none so basically use the following as a dummy password element.

    <input type="password" style="width: 0;height: 0; visibility: hidden;position:absolute;left:0;top:0;"/>
    

The method of hiding it by adding "display: none;" to the input didn’t work for me if the form is generated through javascript.

So instead I made them invisible by placing them out of sight:

<input style="width:0;height:0;opacity:0;position:absolute;left:-10000px;overflow:hidden;" type="text" name="fakeusernameremembered"/>
<input style="width:0;height:0;opacity:0;position:absolute;left:-10000px;overflow:hidden;" type="password" name="fakepasswordremembered"/>

If you are implementing a search box feature, try setting the type attribute to search as follows:

<input type="search" autocomplete="off" />

This is working for me on Chrome v48 and appears to be legitimate markup:

https://www.w3.org/wiki/HTML/Elements/input/search


Like Dvd Franco said, for me only puting automplete='off' in all fields it worked. So I put this jquery rules in $(document).ready(); function on my main .js file

$('form.no_autofill').attr('autocomplete','off');
$('.no_autofill input').attr('autocomplete','off');

This is the most recent solution that I have used.

$('#email').prop('autocomplete', true);

Well since we all have this problem I invested some time to write a working jQuery extension for this issue. Google has to follow html markup, not we follow Google

(function ($) {

"use strict";

$.fn.autoCompleteFix = function(opt) {
    var ro = 'readonly', settings = $.extend({
        attribute : 'autocomplete',
        trigger : {
            disable : ["off"],
            enable : ["on"]
        },
        focus : function() {
            $(this).removeAttr(ro);
        },
        force : false
    }, opt);

    $(this).each(function(i, el) {
        el = $(el);

        if(el.is('form')) {
            var force = (-1 !== $.inArray(el.attr(settings.attribute), settings.trigger.disable))
            el.find('input').autoCompleteFix({force:force});
        } else {
            var disabled = -1 !== $.inArray(el.attr(settings.attribute), settings.trigger.disable);
            var enabled = -1 !== $.inArray(el.attr(settings.attribute), settings.trigger.enable);
            if (settings.force && !enabled || disabled)
                el.attr(ro, ro).focus(settings.focus).val("");
        }
    });
};
})(jQuery);

Just add this to a file like /js/jquery.extends.js and include it past jQuery. Apply it to each form elements on load of the document like this:

$(function() {
    $('form').autoCompleteFix();
});

jsfiddle with tests


I finally solved this by putting in a non duplicate variable in the input field - i used php time() like this:

<input type="text" name="town['.time().']" >

This was interfering mostly n android. All i did on the server side was to do a foreach loop on the input name - the issue is if chrome recognizes the name attribute it WILL auto populate.

Nothing else even worked for me.


Here are my proposed solutions, since Google are insisting on overriding every work-around that people seem to make.

Option 1 - select all text on click

Set the values of the inputs to an example for your user (e.g. [email protected]), or the label of the field (e.g. Email) and add a class called focus-select to your inputs:

<input type="text" name="email" class="focus-select" value="[email protected]">
<input type="password" name="password" class="focus-select" value="password">

And here's the jQuery:

$(document).on('click', '.focus-select', function(){
  $(this).select();
});

I really can't see Chrome ever messing with values. That'd be crazy. So hopefully this is a safe solution.

Option 2 - set the email value to a space, then delete it

Assuming you have two inputs, such as email and password, set the value of the email field to " " (a space) and add the attribute/value autocomplete="off", then clear this with JavaScript. You can leave the password value empty.

If the user doesn't have JavaScript for some reason, ensure you trim their input server-side (you probably should be anyway), in case they don't delete the space.

Here's the jQuery:

$(document).ready(function() {
  setTimeout(function(){
    $('[autocomplete=off]').val('');
  }, 15);
});

I set a timeout to 15 because 5 seemed to work occasionally in my tests, so trebling this number seems like a safe bet.

Failing to set the initial value to a space results in Chrome leaving the input as yellow, as if it has auto-filled it.

Option 3 - hidden inputs

Put this at the beginning of the form:

<!-- Avoid Chrome autofill -->
<input name="email" class="hide">

CSS:

.hide{ display:none; }

Ensure you keep the HTML note so that your other developers don't delete it! Also ensure the name of the hidden input is relevant.


I know this is not exactly relevant but here is what i did. The auto filled fields raise a 'change' event but only if you bind it to them as early as possible.

so i put this inside the head section.

  $(document).ready(function(){
            $('input').on('change',function(){$(this).val('')})
     }); 

and it worked for me.


Here's a dirty hack -

You have your element here (adding the disabled attribute):

<input type="text" name="test" id="test" disabled="disabled" />

And then at the bottom of your webpage put some JavaScript:

<script>
    setTimeout(function(){
        document.getElementById('test').removeAttribute("disabled");
        },100);
</script>

I've faced same problem. And here is the solution for disable auto-fill user name & password on Chrome (just tested with Chrome only)

    <!-- Just add this hidden field before password as a charmed solution to prevent auto-fill of browser on remembered password -->
    <input type="tel" hidden />
    <input type="password" ng-minlength="8" ng-maxlength="30" ng-model="user.password" name="password" class="form-control" required placeholder="Input password">

My problem was that Chrome would autofill postal code, over the Bootstrap autocomplete interface as I was auto suggesting possible values from my database.

Things I had to do:

  • Change input field's id property to something other than "postcode"
  • Change input field's autocomplete value to false
  • After calling $('#postcode_field').autocomplete(...) I had to reset the autocomplete property with $('#postcode_field').prop('autocomplete', 'false'); because Boostrap's autocomplete plugin changes it to off automatically.

I needed some extra fields for it to work properly, as chrome actually fills many fields. And I also needed to hide the fields in a more fancy way than display:none for it to actually work.

<style>.stylish { position:absolute; top:-2000px; }</style>
<input id="_____fake_email_remembered" class="stylish" tabindex="-1"  type="email" name="email_autofill"/> 
<input id="_____fake_userName_remembered" class="stylish" tabindex="-1"  type="text" name="userName_autofill"/>
<input id="_____fake_firstName_remembered" class="stylish" tabindex="-1"   type="text" name="firstName_autofill"/>
<input id="_____fake_lastName_remembered" class="stylish" tabindex="-1"   type="text" name="lastName_autofill"/>
<input id="_____fake_phone_remembered" class="stylish"  tabindex="-1"  type="text" name="phone_autofill"/>
<input id="_____fake_address_remembered" class="stylish"  tabindex="-1"   type="text" name="address_autofill"/>
<input id="_____fake_password_remembered" class="stylish"  tabindex="-1"   type="password" name="password_autofill"/>
<input id="_____fake_password_remembered2" class="stylish"  tabindex="-1"   type="password" name="passwordRepeated_autofill"/>

I really did not like making hidden fields, I think that making it like that will get really confusing really fast.

On the input fields that you want to stop from auto complete this will work. Make the fields read only and on focus remove that attribute like this

<input readonly onfocus="this.removeAttribute('readonly');" type="text">

what this does is you first have to remove the read only attribute by selecting the field and at that time most-likely you will populated with your own user input and stooping the autofill to take over


Try the following jQuery code which has worked for me.

if ($.browser.webkit) {
    $('input[name="password"]').attr('autocomplete', 'off');
    $('input[name="email"]').attr('autocomplete', 'off');
}

There's two pieces to this. Chrome and other browsers will remember previously entered values for field names, and provide an autocomplete list to the user based on that (notably, password type inputs are never remembered in this way, for fairly obvious reasons). You can add autocomplete="off" to prevent this on things like your email field.

However, you then have password fillers. Most browsers have their own built-in implementations and there's also many third-party utilities that provide this functionality. This, you can't stop. This is the user making their own choice to save this information to be automatically filled in later, and is completely outside the scope and sphere of influence of your application.


I was having this problem with a "sign in now or register" modal window, and was a problem if the user had saved their credentials to the browser. Both the sign in and register fields were populated, so I was able to clear them with the following angular js directive:

_x000D_
_x000D_
(function () {_x000D_
    "use strict";_x000D_
_x000D_
    var directive = function ($timeout) {_x000D_
        return {_x000D_
            restrict: "A",_x000D_
            link: function (scope, element, attrs) {_x000D_
                $timeout(function () {_x000D_
                    element.val(" ");_x000D_
                    $timeout(function () {_x000D_
                        element.val("");_x000D_
                    });_x000D_
                });_x000D_
            }_x000D_
        };_x000D_
    };_x000D_
_x000D_
    angular.module("app.directives").directive("autofillClear", ["$timeout", directive]);_x000D_
}());
_x000D_
_x000D_
_x000D_

It's basically the same as some of the previous answers that would use jquery, but done in an angular way.


By setting autocomplete to off should work here I have an example which is used by google in search page. I found this from inspect element.

enter image description here

edit: In case off isn't working then try false or nofill. In my case it is working with chrome version 48.0


So apparently the best fixes/hacks for this are now no longer working, again. Version of Chrome I use is Version 49.0.2623.110 m and my account creation forms now show a saved username and password that have nothing to do with the form. Thanks Chrome! Other hacks seemed horrible, but this hack is less horrible...

Why we need these hacks working is because these forms are generally to be account creation forms i.e. not a login forms which should be allowed to fill in password. Account creation forms you don't want the hassle of deleting username and passwords. Logically that means the password field will never be populated on render. So I use a textbox instead along with a bit of javascript.

<input type="text" id="password" name="password" />

<script>
    setTimeout(function() {
        $("#password").prop("type", "password");
    }, 100); 
    // time out required to make sure it is not set as a password field before Google fills it in. You may need to adjust this timeout depending on your page load times.
</script>

I find this acceptable as a user won't get to a password field within the short period of time, and posting back to the server makes no difference if the field is a password field as it is sent back plain text anyway.

Caveat: If, like me, you use the same creation form as an update form things might get tricky. I use mvc.asp c# and when I use @Html.PasswordFor() the password is not added to the input box. This is a good thing. I have coded around this. But using @Html.TextBoxFor() and the password will be added to the input box, and then hidden as a password. However as my passwords are hashed up, the password in the input box is the hashed up password and should never be posted back to the server - accidentally saving a hashed up hashed password would be a pain for someone trying to log in. Basically... remember to set the password to an empty string before the input box is rendered if using this method.


If you are using Symfony forms, autocomplete=off will not work IF the attribute is applied from the twig template rather than using FormBuilder.

Use this:

....
->add('field-name', TextType::class, array(
  'attr' => array(
      'autocomplete' => 'off'
  )
)
....

Rather than:

....
{{ form_widget(form.field-name, {'attr': {'autocomplete':'off'}})
....

None of the solutions worked for me. Finally, after pulling my hair out for many hours I came up with this solution for ReactJS.

Tested on FireFox 54.0.1, Chrome 61.0.3163.100, Mac OS 10.13

I keep the type="text" and change it to relevant type on onChange event.

ex: HTML:

<input type="text" onChange={this.setAttributes} placeholder="Email" />

JS:

setAttr2: function(e){
    var value = e.target.value;
    if(value.length){
      e.target.setAttribute('type', 'email')
    } else {
      e.target.setAttribute('type', 'text')
    }
  }

I've finally found success using a textarea. For a password field there's an event handler that replaces each character typed with a "•".


My hack — tested in Chrome 48:

Since Chrome tries to find out the type of field it is by looking at stuff like id or name attributes of the <input>, but also at associated <label> content, you just have to find meaningless names for these.

For the id and name, it's easy to choose something else that is not listed here.

For the label, I inserted an invisible <span> in the middle, e.g. for a city (it's messing with my Places autocomplete):

<span>Ci<span style="display:none">*</span>ty</span>

Full working example:

_x000D_
_x000D_
<!DOCTYPE html>_x000D_
<html>_x000D_
  <body>_x000D_
    <form method="post" action="/register">_x000D_
      <div>_x000D_
        <label for="name">Name</label>_x000D_
        <input id="name" type="text" name="name" />_x000D_
      </div>_x000D_
      <div>_x000D_
        <label for="email">Email</label>_x000D_
        <input id="email" type="text" name="email" />_x000D_
      </div>_x000D_
      <div>_x000D_
        <label for="id1">City</label>_x000D_
        <input id="id1" type="text" name="id1" /> <-- STILL ON :(_x000D_
      </div>_x000D_
      <div>_x000D_
        <label for="id2">Ci<span style="display:none">*</span>ty</label>_x000D_
        <input id="id2" type="text" name="id2" /> <-- NOW OFF :)_x000D_
      </div>_x000D_
    </form>_x000D_
  </body>_x000D_
</html>
_x000D_
_x000D_
_x000D_


I've just found that if you have a remembered username and password for a site, the current version of Chrome will autofill your username/email address into the field before any type=password field. It does not care what the field is called - just assumes the field before password is going to be your username.

Old Solution

Just use <form autocomplete="off"> and it prevents the password prefilling as well as any kind of heuristic filling of fields based on assumptions a browser may make (which are often wrong). As opposed to using <input autocomplete="off"> which seems to be pretty much ignored by the password autofill (in Chrome that is, Firefox does obey it).

Updated Solution

Chrome now ignores <form autocomplete="off">. Therefore my original workaround (which I had deleted) is now all the rage.

Simply create a couple of fields and make them hidden with "display:none". Example:

<!-- fake fields are a workaround for chrome autofill getting the wrong fields -->
<input style="display: none" type="text" name="fakeusernameremembered" />
<input style="display: none" type="password" name="fakepasswordremembered" />

Then put your real fields underneath.

Remember to add the comment or other people on your team will wonder what you are doing!

Update March 2016

Just tested with latest Chrome - all good. This is a fairly old answer now but I want to just mention that our team has been using it for years now on dozens of projects. It still works great despite a few comments below. There are no problems with accessibility because the fields are display:none meaning they don't get focus. As I mentioned you need to put them before your real fields.

If you are using javascript to modify your form, there is an extra trick you will need. Show the fake fields while you are manipulating the form and then hide them again a millisecond later.

Example code using jQuery (assuming you give your fake fields a class):

$(".fake-autofill-fields").show();
// some DOM manipulation/ajax here
window.setTimeout(function () {
  $(".fake-autofill-fields").hide();
}, 1);

Update July 2018

My solution no longer works so well since Chrome's anti-usability experts have been hard at work. But they've thrown us a bone in the form of:

<input type="password" name="whatever" autocomplete="new-password" />

This works and mostly solves the problem.

However, it does not work when you don't have a password field but only an email address. That can also be difficult to get it to stop going yellow and prefilling. The fake fields solution can be used to fix this.

In fact you sometimes need to drop in two lots of fake fields, and try them in different places. For example, I already had fake fields at the beginning of my form, but Chrome recently started prefilling my 'Email' field again - so then I doubled down and put in more fake fields just before the 'Email' field, and that fixed it. Removing either the first or second lot of the fields reverts to incorrect overzealous autofill.

Update Mar 2020

It is not clear if and when this solution still works. It appears to still work sometimes but not all the time.

In the comments below you will find a few hints. One just added by @anilyeni may be worth some more investigation:

As I noticed, autocomplete="off" works on Chrome 80, IF there is less than 3 elements in <form>. I don't know what is the logic or where the related documentation about it.

Also this one from @dubrox may be relevant, although I have not tested it:

thanks a lot for the trick, but please update the answer, as display:none; doesn't work anymore, but position: fixed;top:-100px;left:-100px; width:5px; does :)

Update APRIL 2020

Special value for chrome for this attribute is doing the job: (tested on input - but not by me) autocomplete="chrome-off"


My solution depends on three things thing:

  1. keydown event
  2. masking the field name
  3. blanking the fields values on submit

First of all, we need to prevent autocomplete of both username and password, so, initially we will set two flags, i -> username and j -> passowrd with true value, so without any keydown to the fields both i and j will be true.

In may case the field masking is occured at the server side, by passing random string, it could be made easily made using client side too.

This is the code:

$(document).ready(function(){
   i= true; //username flag
   j= true; // password flag
   $("#username{{$rand}}").keydown(function(e){
          // {{$rand}} is server side value passed in blade view
          // keyboard buttons are clicked in the field
            i = false;       
    });
   $("#passowrd{{$rand}}").keydown(function(e){
          // {{$rand}} is server side value passed in blade view
          // keyboard buttons are clicked in the field
            j = false;       
    });
    // Now we will use change event,
   $("#username{{$rand}}").change(function(){
    if($(this).val() != ''){ //the field has value
        if(i){ // there is no keyboard buttons clicked over it
            $(this).val(''); // blank the field value
        }

    }
})
$("#password{{$rand}}").change(function(){
    if($(this).val() != ''){ // the same as username but using flag j
        if(j){
            $(this).val('');
        }

    }
})

   $("#sForm").submit(function(e){ // the id of my form
      $("#password-s").val($("#password{{$rand}}").val());
        $("#username-s").val($("#username{{$rand}}").val());
        // Here the server will deal with fields names `password` and `username` of the hidden fields
       $("#username{{$rand}}").val('');
        $("#password{{$rand}}").val(''); 

 })
})

Here are the HTML:

<form class="form-horizontal" autocomplete="off" role="form" id="sForm" method="POST" action="https://example.com/login">

                        <input type="hidden" name="password" id="password-s">
                        <input type="hidden" name="username" id="username-s">

                            <label for="usernameTDU3m4d3I5" class="col-md-3 control-label" style="white-space: nowrap">Username</label>

                                <input id="usernameTDU3m4d3I5" placeholder="Username" autocomplete="off" style="border-bottom-left-radius: 10px; border-top-right-radius: 10px; font-family: fixed; font-size: x-large;" type="text" class="form-control" name="usernameTDU3m4d3I5" value="" required="required" autofocus="">                                

                            <label for="passwordTDU3m4d3I5" class="col-md-3 control-label" style="white-space: nowrap">Password</label>
                                <input id="passwordTDU3m4d3I5" placeholder="Password" autocomplete="off" type="password" class="form-control" name="pa-TDU3m4d3I5" required="">


                                <button type="submit" class="btn btn-success">
                                    <i class="fox-login" style="text-shadow: 0px 1px 0px #000"></i><strong>Login</strong>&nbsp;&nbsp;
                                </button>

                                </form>

The above solution, indeed, will not eliminate or prevent the autocomplete of the username and password, but it make that autocomplete useless. i.e without hitting keyboard button on the field, the field value will be blank before submit, so the user will be asked to enter them.

Update

We can, also, use click event to prevent autocomplete from users list appeared under the field like the following:

 $("#username{{$rand}}").click(function(){

            $(this).val('');
            i = true;

})
$("#password{{$rand}}").click(function(){

            $(this).val('');
            j = true;

})

Limitations:

This solution may not work as expected in touch screen devices.

Final Update

I have done the following clean implementation like the following:

preventAutoComplete = true; // modifier to allow or disallow autocomplete
trackInputs = {password:"0", username:"0"}; //Password and username fields ids as object's property, and "0" as its their values
// Prevent autocomplete
    if(preventAutoComplete){
        $("input").change(function(e){ // Change event is fired as autocomplete occurred at the input field 
            trackId = $(this).attr('id'); //get the input field id to access the trackInputs object            
            if (trackInputs[trackId] == '0' || trackInputs[trackId] != $(this).val()){ //trackInputs property value not changed or the prperty value ever it it is not equals the input field value
                $(this).val(''); // empty the field
            }
        });
        $("input").keyup(function(e){
            trackId = $(this).attr('id');
            trackInputs[trackId] = $(this).val(); //Update trackInputs property with the value of the field with each keyup.
        });
    } 

Enter a value of ' ' (a blank space) for the username field.

<input type = 'text' value = ' ' name = 'username' />

If you're ever populating the username with a user-entered value, code to enter a ' ' if there's no user-entered value.

Edit: I also had to change 'username' fields to have a name of something else than 'username', e.g. 'nameofuser'


You have to add this attribute :

autocomplete="new-password"

Source Link : Full Article


Since display none doesn't seem to work anymore add the

<input type="text" name="fakeusernameremembered"/>
<input type="password" name="fakepasswordremembered"/>

inside a div with overflow hidden, max-width & max-height 0px

So it becomes something like:

<div style="overflow: hidden; max-width: 0px; max-height: 0px;">
    <input type="text" name="fakeusernameremembered"/>
    <input type="password" name="fakepasswordremembered"/>
</div>

My Solution:

$(function(){
    $("form[autocomplete=off]").find('input').attr('autocomplete', 'false');
});

It sets the attribute 'autocomplete="false"' on all input fields in the forms that have 'autocomplete="off"'.

This works on chrome, firefox and safari.


For Angular users :

Since the autocomplete = 'off' ignore by new chrome versions, chrome developer suggests autocomplete= 'false | random-string', so the google chrome/modern browsers have 2 type of users helpers -

  1. autocomplete='off' (which prevents last cached suggestions).
  2. autocomplete = 'false | random-string' (which prevents autofill setting, since the 'random-string' is not known by the browser).

so what to do, in case of disabling both the annoying suggestions? Here is the trick:-

  1. add autocomplete = 'off' in every input fields. (or simple Jquery).

Example : $("input").attr('autocomplete', 'off');

  1. Remove the <form name='form-name'> tag from HTML code and add ng-form = 'form-name' in your <div> container. Adding ng-form="form-name" will also retain all your validations.

I've found that adding this to a form prevents Chrome from using Autofill.

<div style="display: none;">
    <input type="text" id="PreventChromeAutocomplete" name="PreventChromeAutocomplete" autocomplete="address-level4" />
</div>

Found here. https://code.google.com/p/chromium/issues/detail?id=468153#hc41

Really disappointing that Chrome has decided that it knows better than the developer about when to Autocomplete. Has a real Microsoft feel to it.


None of the other solutions to these question worked for me.

The only think that worked is this one:

It removes "name" and "id" attributes from elements and assigns them back after 1ms. Put this in document get ready.

$(document).ready(function() {
    $('form[autocomplete="off"] input, input[autocomplete="off"]').each(function () {

                var input = this;
                var name = $(input).attr('name');
                var id = $(input).attr('id');

                $(input).removeAttr('name');
                $(input).removeAttr('id');

                setTimeout(function () {
                    $(input).attr('name', name);
                    $(input).attr('id', id);
                }, 1);
            });
});

Boom, Google Chrome and anyone else try defeat this then.

I was able to get this implemented today 7th September 2017, but using a FormCollection of random strings that generated in my MVC View.

I would first get a new random key in my index controller of my login page , encrypt and create a new totally unique random string (i actually used a 256 bit cypher to perform this, and a unique cypher and authentication key), i then append plain text 'Username' and 'Password' on the end of each string to later help me identify from the repsonding view controller the username and password. You could also change that plain string to anything as long as you know the pattern and it's unique.

In my view, I then used these variables appropriately and then in the responding controller - searched through a FormCollection and found my matching variables - and then used the Key-Value of that item as the corresponding Username and Password to process appropriately.

The other issue i had which i think is sneaky of Chrome, is that any

Any thoughts ?

<style>
    @@font-face {
      font-family: 'password';
      font-style: normal;
      font-weight: 400;
      src: url(https://jsbin-user-assets.s3.amazonaws.com/rafaelcastrocouto/password.ttf);
    }
</style>

<input type="text" name="@Model.UsernameRandomNameString" />
<input style="font-family: 'password'" type="text" name="@Model.PasswordRandomNameString" />

LogOnModel model = new LogOnModel()
            {
                UsernameRandomNameString = Cryptography.SimpleEncrypt("Username", UniqueGeneratorKey, UniqueGeneratorKey) + "Username",
                PasswordRandomNameString = Cryptography.SimpleEncrypt("Password", UniqueGeneratorKey, UniqueGeneratorKey) + "Password",
            };

I think it a hell of a workaround, but hey it works, and i think it could also be future proof unless google determines the URL of the page has key words in it, then appropriately just adds its stupid extensions on top on any input field - but that's a little drastic.


Unfortunately none of the solutions seem to work. I was able to blank out email (username) using

                    <!-- fake fields are a workaround for chrome autofill getting the wrong fields -->
                    <input style="display:none" type="text" name="fakeusernameremembered"/>
                    <input style="display:none" type="password" name="fakepasswordremembered"/>

technique, but password still populates.


The autocomplete feature has successfully disabled via this trick. It Works!

[HTML]

<div id="login_screen" style="min-height: 45px;">
   <input id="password_1" type="text" name="password">
</div>

[JQuery]

$("#login_screen").on('keyup keydown mousedown', '#password_1', function (e) {
    let elem = $(this);

    if (elem.val().length > 0 && elem.attr("type") === "text") {
        elem.attr("type", "password");
    } else {
        setTimeout(function () {
            if (elem.val().length === 0) {
                elem.attr("type", "text");
                elem.hide();
                setTimeout(function () {
                    elem.show().focus();
                }, 1);
            }
        }, 1);
    }

    if (elem.val() === "" && e.type === "mousedown") {
        elem.hide();
        setTimeout(function () {
            elem.show().focus();
        }, 1);
    }

});

Examples related to html

Embed ruby within URL : Middleman Blog Please help me convert this script to a simple image slider Generating a list of pages (not posts) without the index file Why there is this "clear" class before footer? Is it possible to change the content HTML5 alert messages? Getting all files in directory with ajax DevTools failed to load SourceMap: Could not load content for chrome-extension How to set width of mat-table column in angular? How to open a link in new tab using angular? ERROR Error: Uncaught (in promise), Cannot match any routes. URL Segment

Examples related to forms

How do I hide the PHP explode delimiter from submitted form results? React - clearing an input value after form submit How to prevent page from reloading after form submit - JQuery Input type number "only numeric value" validation Redirecting to a page after submitting form in HTML Clearing input in vuejs form Cleanest way to reset forms Reactjs - Form input validation No value accessor for form control TypeScript-'s Angular Framework Error - "There is no directive with exportAs set to ngForm"

Examples related to google-chrome

SessionNotCreatedException: Message: session not created: This version of ChromeDriver only supports Chrome version 81 SameSite warning Chrome 77 What's the net::ERR_HTTP2_PROTOCOL_ERROR about? session not created: This version of ChromeDriver only supports Chrome version 74 error with ChromeDriver Chrome using Selenium Jupyter Notebook not saving: '_xsrf' argument missing from post How to fix 'Unchecked runtime.lastError: The message port closed before a response was received' chrome issue? Selenium: WebDriverException:Chrome failed to start: crashed as google-chrome is no longer running so ChromeDriver is assuming that Chrome has crashed WebDriverException: unknown error: DevToolsActivePort file doesn't exist while trying to initiate Chrome Browser How to make audio autoplay on chrome How to handle "Uncaught (in promise) DOMException: play() failed because the user didn't interact with the document first." on Desktop with Chrome 66?

Examples related to autocomplete

twitter bootstrap 3.0 typeahead ajax example How do I stop Notepad++ from showing autocomplete for all words in the file how to get value of selected item in autocomplete .autocomplete is not a function Error Angularjs autocomplete from $http autocomplete ='off' is not working when the input type is password and make the input field above it to enable autocomplete Disabling Chrome Autofill How to add Google Maps Autocomplete search box? Google Maps API - how to get latitude and longitude from Autocomplete without showing the map? twitter bootstrap autocomplete dropdown / combobox with Knockoutjs

Examples related to autofill

Disabling Chrome Autofill Detecting Browser Autofill Disable form autofill in Chrome without disabling autocomplete Prevent textbox autofill with previously entered values Google Chrome form autofill and its yellow background Override browser form-filling and input highlighting with HTML/CSS