19

I'm trying to find a way to make Safari 7 (tested with version 7.0.2, 7.0.3) respect the autocomplete="off" attributes. No matter what I try, it continues to auto-fill.

This is a problem for one of our admin pages where we set up new users. Our users keep saving over with their own username/password.

Here's an abbreviated version of the form we're using. I've tried renaming the fields to "xxu" and "xxp" but the autofill seems to read the label caption. I've fooled with various different labels but it still somehow triggers the auto-fill.

<form novalidate autocomplete="off">
     <div class="control-group">
          <label class="control-label">Username</label>
          <div class="controls">
               <input type="text" name="xxu" autocomplete="off" required="required">
        </div>
     </div>
     <div class="control-group">
          <label class="control-label">Username</label>
          <div class="controls">
               <input type="password" name="xxp" autocomplete="off" required="required">
        </div>
     </div>
</form>

I found this article on Apple's site that describes this problem. https://discussions.apple.com/message/25080203#25080203

Does anyone know of any other method for disabling auto-fill for a form in Safari 7? (Agh, this is the kind of thing we'd expect from IE)

Thanks for the help.

Ender2050
  • 6,912
  • 12
  • 51
  • 55
  • 3
    +1 I'm having the same problem. Safari 7.02 does not respect `autocomplete="off"`. Very frustrating and a UX nightmare for any user account editing! – djoll Apr 02 '14 at 23:40
  • 1
    One thing, it doesn't autofill the password field if you have no ID or NAME property set on that field. So I guess if you REALLY need to. You could have a hidden field called "password" and an `` then JS listen for changes to this field and put them into the hidden one. I know you wouldn't consider that an answer but :P I think it's actually impossible really. I have an "amount" field being populated as though it's a username/email -.- – creamcheese Apr 03 '14 at 16:01
  • Dominic - thanks, I'm desperate enough that I may just try that... ugh, this is such a mess. – Ender2050 Apr 03 '14 at 19:43
  • You could try it through JS? http://stackoverflow.com/questions/582244/is-there-a-w3c-valid-way-to-disable-autocomplete-in-a-html-form –  Apr 04 '14 at 11:25
  • Thank you, that's a really good link with lots of ideas - I hadn't seen that one. I can easily swap out labels and field names, I just need to figure out what is triggering the autofill - I think it's the label name. I'll work on it more and write back here. – Ender2050 Apr 04 '14 at 14:58
  • I believe that this option to toggle auto complete on and off can be set in preferences in safari. Safari ships with these functions toggled on. Therefore having these switched on is technically a user choice and therefor there is the argument that you shouldn't be trying to change a feature a user has chosen to use - even if it does cause design and dev headaches. – Edd Aslin May 02 '14 at 13:27
  • Note that Chrome will be ignoring autocomplete="off" (or already does now? I forget), too (for user name and password fields), so you might just accept it or do the JavaScript jiggles. – PhistucK May 02 '14 at 14:23
  • Quick update: Dominic, a variation of your suggestion to use a hidden field is working for our password field - since we don't need to display the currently stored value. But I'm still searching for a solution to the username field where I need to display the currently stored value - not what the browser thinks should be autofilled. Thanks everyone for your ideas - I'm still searching for a full solution. – Ender2050 May 05 '14 at 20:01
  • We are having the same problem. Slightly more annoying though: when the onBlur event is run we do an AJAX validation of the fields, which triggers the autofill on the Email field. So you fill in the email, press TAB, the email field is changed. – Skurpi Jun 09 '14 at 13:59
  • @Skurpi: and yet the "autocomplete above all else" apologists will insist that that is correct behavior, and how dare you (as the form designer) interfere with the user's wishes. :/ – Martha May 23 '16 at 16:57

10 Answers10

11

We had the same problem recently. On top of that, we had a AJAX validation of our form happening onBlur. For some strange reason, this would trigger safari to autofill our email input field again. So every time you fill in the email that you want, Safari would fill in an email that it preferred instead. Making it impossible to go through our form.

Our solution

was to pretty much break Safaris (and Chromes) autofill algorithm.

HTML:

<div class="douchebag_safari">
    <input class="js-clear_field" tabindex="-1" name="e-mail" type="email">
    <input class="js-clear_field" tabindex="-1" name="Ecom_User_Password" type="password">
</div>

CSS:

.douchebag_safari {
    position: fixed;
    width: 1px;
    left: -50px;
}
.douchebag_safari input {
    width: 1%;
}

JS:

$('#form').on('submit', function () {
    "use strict";
    $('.js-clear_field').attr('disabled', 'disabled');
}

The jist of it is: We put input fields of type email and password with names that will rank higher (or same?) in Safaris autofill algorithm and hide them outside the screen. OnSubmit, the fields will be disabled and will thus be excluded from the POST to our backend.

The downside is that users won't have autocomplete on our form, but we decided that it was worth it in our case.

NOTE (assuming you care): Users with Javascript disabled will still get these fields included in their POSTs. Depending on your setup, you will need to allow these two fields to come through to your backend to prevent errors. Just make sure you don't do anything with these fields for security reasons!

As a bonus, this solved a bug where Chrome (35) assumed the input field above the password field is the username. In our case, it was a number field, giving strange user experience and bugs.

Skurpi
  • 1,000
  • 1
  • 12
  • 22
5

I went with a simplified variation of the douchebag_safari approach that @Skurpi came up with. It's HTML only and goes at the bottom of my form.

<!-- http://stackoverflow.com/questions/22817801/how-to-disable-auto-fill-in-safari-7 -->
<div class="douchebag_safari" style="left: -9999px; position: fixed; width: 1px;">
    <input type="password">
</div>
Shawn Miller
  • 7,082
  • 6
  • 46
  • 54
  • 1
    This does indeed work, but what a hack. What the **** Apple?? I cannot believe THIS kind of kluge job is needed just make Safari do what an HTML form field should be able to do. – cbmtrx Oct 13 '15 at 15:42
3

I found a quicker and simple way to avoid the form autocompleting. It works in FF 27, Chrome 36 and Safari 7.0.5 on a Mac. I still have not tested it in other OS.

I simply put a fake field as the first place in my form, no need for label or id and name attributes. I hid it for instance with an inline style and voilà!

<input type="password" style="display: none">

The email and password fields in my form are filled with the values from the database as expected and not getting autocompleted anymore.

To be honest, I don't like this solution either... I would love to find a compatible and standard solution but seems that autocomplete="off" is not working anymore.

Alex Fuentes
  • 61
  • 2
  • 5
  • Alas, this solution doesn't work on Safari 7.0.6 on Mac. Email still gets autofilled. – Michal Aug 22 '14 at 13:06
  • Maybe it's not about Safari version because I've tested in 7.0.6 and it's still working fine. – Alex Fuentes Aug 23 '14 at 15:56
  • It's probably just a different case. In my example I have a login form (which I want autofilled) and a dialog to add new users (where I certainly do not want new user's email replaced with logged user's email). As long as I have a **visible** `` in the second form, the email is always autofilled here. – Michal Aug 23 '14 at 19:34
  • Wow! I don't know what to think. It's exactly my case... My login form has email and password fields and as in your case I have another form to add/edit users with a visible email and password fields among others. In my case adding an **additional** above them solved the problem. I'm sorry! – Alex Fuentes Aug 24 '14 at 22:22
  • In my case adding `style="display: none"` made Safari to ignore the field and autofill the email. Finally I decided to use `input type="text"` instead of `input type="password"` in the form for adding new users. That stopped autofilling. – Michal Aug 25 '14 at 08:02
2

Had the same issue and tried the first two HTML / CSS only solutions mentioned.

They did not work for me (or Safari 9.0.3 :) ) so I implemented a solution like this

<div style="overflow: hidden;width: 0px;height: 0px;">
  <input id="password" type="password" name="password" />
</div>

on top of the actual form input fields.

Tested on Safari, Firefox (44.0.2) and Chrome (48.0.2564.109) running on OS X El Capitan.

Spielername
  • 106
  • 6
2

The solutions given above did not work for me. After investigation I could evaluate that Safari's decision to enable autofill relies on the following factors:

  • Does the "id" attribute of the input contain "name"?
  • Does the "name" attribute of the input contain "name"?
  • Does the label of the input contain "name"?

I could then disable Safari's autofill with the following code, that I ended with wrapping it into a jQuery plugin, for convenience:

$(document).ready(function () {
 $('input').disableAutoFill();
});

(function($) {

 $.fn.disableAutoFill = function() {

  "use strict";

  var self = {

   /**
    * Disable autofill for one input
    * @param {Object} $input jQuery element
    */
   disableAutoFill: function($input) {
    if (self.isBrowser('safari')) {
     self.alterLabel($input);
     self.alterName($input);
     self.alterId($input);
    }
    $input.attr('autocomplete', 'off');
   },

   /**
    * Change input's name
    * Make sure Safari wont detect the word "name" in the name attribute
    * otherwise Safari will enable autofill
    * @param {Object} $input jQuery element
    */
   alterName: function ($input) {
    $input.attr('data-original-name', $input.attr('name'));

    // Find unique name attribute value
    var new_name = false;
    var iteration = 0;
    while (iteration < 10 && !new_name) {
     new_name = self.random();
     if (self.checkAttributeExists('name', new_name)) {
      new_name = false;
     }
    }

    if (new_name) {
     $input.attr('name', new_name);
     self.setFormSubmitHandler($input);
    }
   },

   /**
    * Change input's id
    * Make sure Safari wont detect the word "name" in the id attribute
    * otherwise Safari will enable autofill
    * @param {Object} $input jQuery element
    */
   alterId: function ($input) {
    $input.attr('data-original-id', $input.attr('id'));

    // Find unique id attribute value
    var new_id = false;
    var iteration = 0;
    while (iteration < 10 && !new_id) {
     new_id = self.random();
     if (self.checkAttributeExists('id', new_id)) {
      new_id = false;
     }
    }

    if (new_id) {
     $input.attr('id', new_id);
     self.setFormSubmitHandler($input);
    }
   },

   /**
    * Reset input's name and id to its initial values before submitting the form
    * @param {Object} $input jQuery element
    */
   setFormSubmitHandler: function ($input) {
    var $form = $input.closest('form');
    if ($form.length > 0) {
     $form.submit(function() {
      var id = $input.attr('data-original-id');
      if (id) {
       $input.attr('id', id);
      }
      var name = $input.attr('data-original-name');
      if (name) {
       $input.attr('name', name);
      }
     });
    }
   },

   /**
    * Make sure Safari wont detect the word "name" in the label
    * otherwise Safari will enable autofill
    * @param {Object} $input jQuery element
    */
   alterLabel: function ($input) {
    var $label = self.findLabel($input);
    if ($label && $label.length > 0) {
     var text = $label.text();
     var array = text.split('');
     text = array.join('<span></span>');
     $label.html(text);
    }
   },

   /**
    * Find label element of an input
    * see http://stackoverflow.com/questions/4844594/jquery-select-the-associated-label-element-of-a-input-field
    * @param $input
    * @returns {*}
    */
   findLabel: function ($input) {
    var $label = $('label[for="'+$input.attr('id')+'"]');

    if ($label.length > 0) {
     return $label;
    }
    var $parentElem = $input.parent();
    var $parentTagName = parentElem.get(0).tagName.toLowerCase();

    if ($parentTagName == "label") {
     return $parentElem;
    }
    return null;
   },

   /**
    * Generate a random string
    * @returns {string}
    */
   random: function () {
    var text = '';
    var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
    for (var i=0; i < 5; i++) {
     text += possible.charAt(Math.floor(Math.random() * possible.length));
    }
    return text;
   },

   /**
    * Check if there is an existing DOM element with a given attribute matching a given value
    * @param {string} attributeName
    * @param {string} attributeValue
    * @returns {boolean}
    */
   checkAttributeExists: function (attributeName, attributeValue) {
    return $('['+attributeName+'='+attributeValue+']').length > 0;
   },

   /**
    * Detect current Web browser
    * @param {string} browser
    * @returns {boolean}
    */
   isBrowser: function (browser) {
    // http://stackoverflow.com/questions/5899783/detect-safari-using-jquery
    var is_chrome = navigator.userAgent.indexOf('Chrome') > -1;
    var is_explorer = navigator.userAgent.indexOf('MSIE') > -1;
    var is_firefox = navigator.userAgent.indexOf('Firefox') > -1;
    var is_safari = navigator.userAgent.indexOf("Safari") > -1;
    var is_opera = navigator.userAgent.toLowerCase().indexOf("op") > -1;
    if ((is_chrome)&&(is_safari)) {is_safari=false;}
    if ((is_chrome)&&(is_opera)) {is_chrome=false;}

    if (browser === 'chrome') {
     return is_chrome;
    }
    if (browser === 'explorer') {
     return is_explorer;
    }
    if (browser === 'firefox') {
     return is_firefox;
    }
    if (browser === 'safari') {
     return is_safari;
    }
    if (browser === 'opera') {
     return is_opera;
    }
    return false;
   }

  };

  self.disableAutoFill(this);

  return this;
 };



}(jQuery));

You can also download or check out the file here

1

I used a random number and incorporated it into each field name so that the browser never recognized the name of the field.

Tim
  • 11
  • 1
  • I love this simple solution. Thanks. – Ender2050 Mar 14 '16 at 19:21
  • This one is smart and I love it too. However it does not work for me in IE and Safari. Actually I didn't find any solution that works for me in IE and Safari. ╮(╯_╰)╭ – shaosh Sep 23 '16 at 23:16
0

I've adopted a simpler solution which suits us where there are admins maintaining user accounts and occasionally setting their password, and that is simply to change the user's password input type to be:

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

Simple but effective.

Jonathon Horsman
  • 2,303
  • 1
  • 20
  • 18
-3

You can try this:

If you're able to use JavaScript and jQuery, you can place this on load of the html (body onload):

$('#theform input').val('');

This question is similar like this: Is autocomplete="off" compatible with all modern browsers?

There are browsers that no longer supports autocomplete="off"

Community
  • 1
  • 1
-3

You can use this javascript code:

if (document.getElementsByTagName) {

var inputElements = document.getElementsByTagName(“input”);

for (i=0; inputElements[i]; i++) {

if (inputElements[i].className && (inputElements[i].className.indexOf(“disableAutoComplete”) != -1)) {

inputElements[i].setAttribute(“autocomplete”,”off”);

}

}

}
rahul dagli
  • 55
  • 1
  • 3
  • 9
-5

I tried everything, got it working, and then a later version of Safari broke my website again. I am about to try the extra form fields (thanks Skurpi). In the mean time, here is my new solution (in PHP)

if(strpos($_SERVER['HTTP_USER_AGENT'],'Safari') !== false)
{
?>
    <div style="background:#ffff66;border:1px solid #ff9900;font-size:1.5em;padding:1em;">
        The Safari browser has a known bug: autocomplete replaces required data in our form with incorrect values. Unfortunately this may prevent you from adding products to the shopping cart. <br /><br />Please try a different browser or go to your browser settings and turn off autocomplete and refresh the page.
    </div>
<?php
}

If enough websites do this, maybe the Safari team will get a hint and fix their browser to obey the autocomplete="off" attribute.

Frank Forte
  • 2,031
  • 20
  • 19