Prevent iOS Safari from capitalizing the first letter of inputs - html

I have a case sensitive username field in my web app. In most instances, it works fine. Unfortunately, Safari on iOS and Chrome (sometimes) on Android want to "help" by capitalizing the first letter of any text entered into the input.
Since this is an <input type="text"> the first input letter is uppercase on those devices. This is driving users nuts as it takes a lot of effort to override and some don't even notice the change but it causes login to fail.
I can't simply say string.toLowercase() in my javascript since users are allowed to have mixed case logins. I just want the browsers to stop deciding which letters to make uppercase...

As I was typing this a friend pointed me to HTMLInputElement Autocapitalize="off" and that seems to do the trick very easily.
Turns out that this can be included with autocomplete="off" to mostly control how mobile browsers deal with inputs.
So basically <input type="text" autocapitalize="off" required placeholder="username" /> solves my specific problem.
According to iOS and Android docs this doesn't always work but it should solve the majority of problems.
Bonus: This isn't an all or nothing setting like allowing zoom. You can apply it selectively to inputs where it's needed and allow inputs that need more of a "copy" style content to continue helping the user.

Related

Disable the browser autofill on input fields (All browsers)

I have a simple html form, i am using "google autofill" on a field that autofill data on two fields.
The issue is that the browser address autofill is overlapping the google autofill.
How to disable the browser autofill on fields on every browser ?
Feel free to share thoughts on this.
Thankyou.
Here's the universal solution that will work in all browsers as of May 2021!
TL;DR
Rename your input field names and field ids to something non-related like 'data_input_field_1'. Then add the ‌ character into the middle of your labels. This is a non-printing character, so you won't see it, but it tricks the browser into not recognizing the field as one needing auto-completing, thus no built-in auto-complete widget is shown!
The Details
Almost all browsers use a combination of the field's name, id, placeholder, and label to determine if the field belongs to a group of address fields that could benefit from auto-completion. So if you have a field like <input type="text" id="address" name="street_address"> pretty much all browsers will interpret the field as being an address field. As such the browser will display its built-in auto-completion widget. The dream would be that using the attribute autocomplete="off" would work, unfortunately, most browsers nowadays don't obey the request.
So we need to use some trickery to get the browsers to not display the built-in autocomplete widget. The way we will do that is by fooling the browser into believing that the field is not an address field at all.
Start by renaming the id and the name attributes to something that won't give away that you're dealing with address-related data. So rather than using <input type="text" id="city-input" name="city">, use something like this instead <input type="text" id="input-field-3" name="data_input_field_3">. The browser doesn't know what data_input_field_3 represents. But you do.
If possible, don't use placeholder text as most browsers will also take that into account. If you have to use placeholder text, then you'll have to get creative and make sure you're not using any words relating to the address parameter itself (like City). Using something like Enter location can do the trick.
The final parameter is the label attached to the field. However, if you're like me, you probably want to keep the label intact and display recognizable fields to your users like "Address", "City", "State", "Country". Well, great news: YOU CAN! The best way to achieve that is to insert a Zero-Width Non-Joiner Character ‌ as the second character in the label. So replacing <label>City</label> with <label>C‌ity</label>. This is a non-printing character, so your users will see City, but the browser will be tricked into seeing C ity and not recognize the field!
Mission accomplished! If all went well, the browser should not display the built-in address auto-completion widget on those fields anymore!
Hope this helps you in your endeavors!
This is not so easy to implement cross-browser.
Many browsers, in particular Google Chrome has pushed very hard on having a tool that helps users auto-fill their forms, but for developers this has been just been painful.
I could list tons of different ways that could or could not work depending on different factors, but I will post this one solution that finally does the trick. So if you have been looking for this answer all over the internet, leave me a comment below and tell me if it worked.
First of all, due to browser compatibility, we need to add these attributes as eventually things will work properly:
autocorrect="off" spellcheck="false" autocomplete="off"
This is supposed to be enough, BUT IT IS NOT! and we all know that. so the next thing to do is to add a little bit of JS in case the browser managed to ignore these attributes. For this example I will just use jQuery and assume that we are dealing here with inputs, but you can chose any selector you want.
$('form').attr('autocomplete', 'off');
$('input').attr('autocomplete', 'off');
Finally, this will work 50% of the times, but if the browser has previously detected that this form was filled up in the past it might judt ignore it, so let's add a final step.
There is another popular trick that involves adding a dummy password field, but I don't like adding dummy content, and I don't find this solution elegant so I will just skip it, besides it doesn't work.
To be honest this final step is the one that makes everything work, but as I said it is better if our attributes are ready for future compatibility. Keep in mind that the browser will never attempt to autocomplete a readonly input, so for this last step we need to make it readonly and on focus bring it back to normal, so add the following JS in the onfocus attribute:
readonly onfocus="this.removeAttribute('readonly');"
BINGO! it should work now.
So the final input looks like this:
<input type="text" name="email" required autocorrect="off" spellcheck="false" autocomplete="off" readonly onfocus="this.removeAttribute('readonly');" />
<script>
$('input').attr('autocomplete', 'off');
</script>
It seems like a lot, but this works 100% of the times. as I said probably with readonly onfocus="this.removeAttribute('readonly'); is enough, but browser compatibility is changing and eventually things will work properly, so it is good to have it there.
If this worked (or did not work) leave a comment!
Thanks

How to improve browser autocomplete suggestions without turning them off?

There are ten gazillion threads on here re. how to disable browser autocomplete behavior, e.g. How do you disable browser Autocomplete on web form field / input tag?. I do not want to set autocomplete="off" for my form fields. As the MDN documentation for how to do that states:
It is important to know that if you turn off autocomplete, you are breaking [WCAG rule 1.3.5]
So as an alternative to disabling autocomplete, I want to understand whether as a developer I can help the browser make its suggestions for my form fields more relevant.
As it is, I can see why many developers (or their bosses/clients) do end up wanting to be rid of the feature entirely. For example, when I added an <input name="title"> to a completely unrelated website I was developing locally, my browser suddenly started offering me a random sampling of questions I'd asked/edited across several StackExchange sites over several years:
How can I help the browser improve the user experience here? What factors do browsers use when choosing what text to suggest?
clearly the domain is not taken into consideration, unless my testing via localhost is triggering more promiscuous autocomplete than normal?
apparently at least one browser considers the field's name attribute to have universal semantic meaning, since Chrome is suggesting content I typed into other sites which happened to also use name="title" within their forms.
does any metadata on the form itself affect the suggestions? E.g. if I wrapped this input in a <form id="my-particular-form-has-nothing-to-do-with-qa-sites-btw"> might some browsers scope their autocomplete to only suggest previous name="title" entries into my-particular-form…?
Again, I am not looking for answers that tell me how to disable autocomplete or complaints that this is a duplicate of questions asking how to do that. I am happy to let the browser help the user fill in my form fields, but I want to help that help be more…helpful.
(Or, do I misunderstand the purpose of autocomplete to begin with? Is it only intended to be used for use cases like login credentials, shipping addresses, credit card number, etc. and I should be using autocomplete="off" for everything else?)
Current Auto Complete Behaviour is a mess!
Browser use various methods to determine if a field should be auto-complete.
For example the typical username, password combo a browser will look for two fields, one of which is type email and the other type password.
They also look at the name attribute as well as the type attribute to further try and determine whether a field should be auto-completed.
Finally depending on the browser they also look for fields that they expect to see together and use associated labels to work out what fields are which (which is why it is important to properly link labels with form fields!).
A prime example of this would be credit cards where they would expect to see cardholder name, credit card number, expiry etc.
Without at least 2 of these items auto-complete won't work (yet again depends on which browser you use).
Because each browser has a unique way of implementing this feature it is sometimes difficult to prevent 'cross site contamination' of results.
Domain is not a consideration as you already suspected.
However there are a couple of things you can do:-
The 'old' way (current way)
Give the input an unusual name attribute (i.e. name="xA123IIasd") .
As this is one of the primary factors in determining what a field is for (as far as a browser is concerned) and does not interfere with the user experience in any way it is a great option.
It won't work on username and password fields though as browsers have optimised for that. It also doesn't guarantee success but it will improve 'cross site contamination' for most fields.
You may also want to try giving the field a slightly different label than standard, as long as it doesn't impact usability (i.e. "Your First Name" instead of "First Name").
The new (better) way [not fully supported]
Use the new autocomplete options, part of the latest 'living standard'.
Support is unclear (i.e. can't find these on caniuse.com, only 'off') but I know it works in Google Chrome and Opera, kinda works in Safari (some items supported, some not), it is better than nothing!
Here is a list of the full 53 options you can use.
By adding these to your inputs you can control what the browser will expose as options for autocomplete.
For every other browser, choice is yours, browser sniff and switch autocomplete off or just leave it as it is 'expected behaviour' (even if it is not a great experience).
One more interesting feature
One final feature that the new autocomplete has is 'sections'.
This allows you to 'scope' the auto complete to a particular set of fields.
For example:-
<fieldset>
<legend>Package One Ship To</legend>
<label> Address: <textarea name="pack1Add1" autocomplete="section-packageone shipping street-address"></textarea> </label>
<label> City: <input name="pack1Add2" autocomplete="section-packageone shipping address-level2"> </label>
<label> Post Code: <input name="pack1Postcode" autocomplete="section-packageone shipping postal-code"> </label>
</fieldset>
<fieldset>
<legend>Package Two Ship To:</legend>
<label> Address: <textarea name="pack2Add1" autocomplete="section-packagetwo shipping street-address"></textarea> </label>
<label> City: <input name="pack2Add2" autocomplete="section-packagetwo shipping address-level2"> </label>
<label> Postal Code: <input name="pack2Postcode" autocomplete="section-packagetwo shipping postal-code"> </label>
</fieldset>
This means you can use auto complete twice on one page as each group is treated seperately from the other groups!
You will also note I use 'shipping' within the auto-complete to dictate to use the shipping address, the other option here is 'billing' (those are the only two options for address types at time of writing).

Is it possible to truly disable autofill and autocomplete for password fields for modern browsers?

In modern browsers the standard of autofill and autocomplete is to completely ignore autocomplete="off" for password fields that are placed in a form. And insert saved passwords, even if it's in a user management page. Although the reason is in the right place, it makes creating a user management page a huge pain.
My team's web application runs with angular 7 and currently only supports chrome. But there's a big possibility that we will need support other browsers like internet explorer, edge, firefox, etc.
I know this is a largely touched subject, and that I can find many questions with answers similar to this question (like this, or this). But every solution I've found so far has at least one big flaw.
What I've tried so far on chrome:
1) Use autocomplete="new-password"
It seems that chrome/chromium developers ignores even this for type="password".
2) Use type="text" autocomplete="new-password" with asterisk font family
This disables chrome from auto-filling the input field and hides the letters. But the big flaw is that the value is still there and can be copy-pasted in a different font family. The input field also loses the security of type="password" and any hacker can easily get the value.
3) Use -webkit-text-security
This is pretty much the same solution as the one before but this isn't even css standard and few browsers support it.
4) Replace value with *
This is the trickiest solution I've tried so far. When input value is changed I call a function in typescript that: Adds the new character to a local string, Change DOM value to * equal to the amount of characters, Return the locally saved value on (blur).
This leaves me with a large amount of problems to deal with including: Erasing any character in the string removes the last character always, In addition to the last problem the first character will always stay the same even if the value is completely erased, Having to know where in the string to remove characters.
This solution is less than ideal.
5) Disable password management for domain in browser settings
This really isn't a solution to the problem as it means that I expect the users to turn off password management for domain. It would also result in not saving the password on the login page as many users may need.
6) Randomise [name] and [autocomplete] values
By one way binding said values to a randomised string based on current time, I can ensure that the password field doesn't match any fields saved by the browser. Although many has reported that this works between all browsers, this doesn't seem to work for me at all when using chrome. For me chrome shows recommended password as long as the input is of type="password".
Solutions I've seen so far:
1) Use two input fields
This seems to me to work the same as my own solution 4). And will probably be just as troublesome to work with.
2) Use jQuery Disable Auto Fill Plugin
This seem to be very close to what I'm looking for but the problem is that it uses jQuery. All I can say is that I've been told that we're not using jQuery and that I probably won't be able to use the plugin directly.
I'm currently looking for a way to implement this using angular and would love any help or directions on this.
If you know of any solution that I haven't mentioned above, please post an answer or drop me a link in comments.
The best solution I've found so far is to use type="text" on password field and use autocomplete="off" on the form and every input field in it.
I won't mark this as an answer however as it still has the great flaw of losing the type="password" security functionality. Text fields also allows spell check which can be disabled with spellcheck="false". But I've read that it's possible to override this with browser settings.
This question will remain unanswered until a better solution is proposed.

How to stop Chrome from autocompleting text areas?

I am dealing with a text area in part of a contact form that Chrome wants to autofill with the user's address. As a result many contact requests are submitted by users with their address in the comment field. Besides the obvious potential security issues that could be exploited, my concern is that from a user's standpoint we're providing a contact form without an area to type a message. And from a support standpoint, we're having to ask users to send us another message with their actual question.
HTML:
<textarea id="element_10" class="validate[required] floatlabel js-auto-size multiple-lines" name="element_10" placeholder="Message*" rows="10" cols="60" required autocomplete="off"></textarea>
Answering my own question since I did not find the answer on Stack or in any Chrome browser docs.
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"
Since this random value is not a valid one, the browser will give up.
https://developer.mozilla.org/en-US/docs/Web/Security/Securing_your_site/Turning_off_form_autocompletion
I tried all the suggestions and nothing really worked consistently.
If I set one input to autocomplete="nope" it works.
If I set two or more it breaks them all.
If I set two to autocomplete="nope" and autocomplete="no" it works on those two but breaks again if I do anything to a 3rd.
My form only has 3 inputs. I just set email and phone and left name alone. That pretty much solves my problem.
I have some jquery validation that pretty much does not work with autocomplete and this client really does not want to be bothered with junk emails.
Also Chrome treats a one row textarea exactly the same as a input.

Mobile-friendly input of a digits + spaces string (a credit card number)

I have a credit card number input form that will be used by both mobile and non-mobile browsers.
I want to hint that a keypad should appear on mobile, and to allow (optional) spaces, so either "4111 1234 1234 1234" or "4111123412341234" should be accepted.
From what I've found, the options are:
a) <input type="tel"/> - this seems to behave as I want (with current mobile browsers at least), but it's semantically wrong.
b) <input type="text" pattern="[\d ]*"/> or similar - the iPhone recognises some patterns ([0-9]*, \d*) as working with the keyboard, but this doesn't work as well on Android. Also I'm not sure there are any patterns that the iPhone will give a numpad for that allow spaces, though I don't have an iPhone on hand to check right now.
c) Attempt browser detection with Javascript and use (a) for mobile and (b) for non-mobile. Cludgy, and no real benefit over (a).
<input type="number"/> seems to be a non-starter since Chrome at least will force such input to a number, therefore breaking input with spaces.
Is there a better way of hinting to mobile browsers that they should offer a numpad than using type="tel"?
Edit:
Maybe a -webkit-* property that could be applied to a normal text input field to hint that a numpad should be shown?
The semantically correct markup for a text field that can still contain whitespace and other special characters is <input type="text" inputmode="numeric"/> however as far as I am aware while inputmode is recommended by WhatWG it is not yet supported by any browsers. Its intent is to present the user with a numeric keypad on a device that has it but still behave as a text input.
My suggestion would be to polyfill inputmode with JS and change to type="tel" on touch devices (which is the best solution currently available). Be mindful that differently devices have very different 'tel' and 'number' keypads, iOS 'tel' does not allow spaces while Chrome mobile allows all sorts of special characters. Who knows what custom Android keypads do?
If you don't want to build your own polyfill you can implement Webshim which now polyfills inputmode as of release 1.14.0. This also has has the nice feature of keeping the iOS 'number' keypad invoked by setting pattern="[0-9]*" if you want it (note: this is not the same keypad you get when setting type="number"!)
Here is the analysis I did on input type behavior across browsers and my debate with #aFarkas (the Webshim author) on polyfilling inputmode.
From what I know there is no keyboard layout on the iPhone that allows both numbers and space without at least automatically switching back from numbers to characters. Typing a number with spaces in between will require the user to repeatedly switch back to the numbers keyboard layout after each space.
If you would offer individual input fields for the four blocks of numbers and use some javascript to automatically move over the cursor from one input field to the next once the fourth number has been typed, you could use <input type="number"/> plus you would spare iPhone users from switching between keyboard layouts.