Stupid jQuery and CSS tricks: Move a hidden element to the end of the parent

I just came up with a solution so simple, yet so stupid, that I had to share it.

The scenario is this: my client has some third-party JavaScript to inject a form into a page. I’ve been writing some of my own CSS to style the forms, including some crafty use of :nth-of-type(2n) and :nth-of-type(2n-1) to apply styles conditionally to adjacent fields in a two-up layout. (These are just sequential <div> tags, and I have to work with what I’ve got.) Specifically, I’m adding some right margin on the “left” element, and no right margin on the “right” element.

I noticed an instance where my margins were flipped for two fields, and when inspecting the code, I discovered why: the client has set up their form with a hidden field tucked in there before the “left” element. That’s throwing off the value for 2n in my CSS. I was going to contact them and ask them to update their form to put the hidden element at the end, but I realized this is a problem that is likely to recur, so I should just write in a workaround. (Yeah, yeah. But it’s the lesser of two evils.)

Fortunately, the site is already using jQuery, so a fix was super simple. I’m leaving the CSS class names here as they are in the actual site, but you may need to change them to suit your particular form.

jQuery('.form_container .form_page .form_question.hidden').each(function() {
    jQuery(this).appendTo(jQuery(this).parent());
});

Since the hidden field has the .hidden CSS class, it’s really easy to use the jQuery .appendTo() method to just take all of the hidden fields and shove them to the end of the container element. I used the parent and ancestor CSS classes in my jQuery selector just to be sure I’m isolating this action to these particular forms. Then of course I have to tell the page when to execute this functionality, which is ideally on the load event:

jQuery(window).on('load', function() { /* Code goes here */ });

It works!

On web browsers ignoring autocomplete="off" for passwords (and, on devbros ignoring the messiness of reality)

A couple of frustrating things have occupied much of my afternoon: unexpected web browser behavior, and annoying devbro behavior.

The unexpected web browser behavior was a stubborn, persistent refusal to honor the autocomplete="off" attribute for passwords. The annoying devbro behavior was a stubborn, persistent refusal to honor the legitimacy of a question. In this thrilling post, I’ll be looking at both.

tl;dr

If you’re just trying to find a simple way to get browsers to honor autocomplete="off" on password fields, here you go: THERE ISN’T ONE. Browsers ignore it for a legitimate reason, but I feel they’re overzealous in their implementation.

However… if you’re trying to do what I was trying to do — basically using a password field as a write-only input — it’s never going to work, for a completely different reason. Why? View source and get back to me.

The only way to really create a write-only input is to not pass the value into the form at all, and have some other mechanism on the back end to detect whether or not the user entered a new value.

I was working on an admin page for a site I built; specifically, a page for editing some low-level configuration settings on the site.

One setting is the “client secret” for authenticating with an external API. I realized having that visible on-screen (even if it’s only on pages that require an administrator-level login) was a bit of a security issue, so I thought I’d quickly solve it by changing the input from type="text" to type="password".

Well, not so fast. Because while it worked, it also triggered Safari’s autocomplete feature, replacing the value in that field with my password for the site, and, maddeningly, replacing the value in the field before it with my username.

Then I remembered an attribute I almost never use: autocomplete="off". I figured I’d just stick that on those fields and, boom, problem solved. Only then I realized, Safari (and as it turns out, every other modern browser) completely ignores autocomplete="off" on passwords.

I set off for StackOverflow in search of an answer to my conundrum, and as is often the case, I stumbled upon another maddening thing: a devbro offering a “You’re doing it wrong” answer. (Seriously… I mean, I know nothing about the author of this post, so I wouldn’t use that epithet, but he literally said this:

It is so wrong that browsers are intentionally ignoring anyone who tries to do it. Those people should stop doing the wrong thing.™

This was at the end of a 600+ word answer that demonstrated classic devbro reasoning:

  1. Rejecting plausibly legitimate use cases as invalid.
  2. Denying obvious design flaws in the existing solution.
  3. Blaming the user for “doing the wrong thing.™”

Back to the specific matter of browsers ignoring autocomplete="off", there are some real problems here:

The autocomplete attribute is standard HTML that browser developers have deliberately chosen to ignore. I understand that browsers are constantly evolving, especially in response to unscrupulous web developers who find ways of exploiting features, and there are definitely ways this feature could be exploited. But!

Browsers are absurdly overzealous in their rejection of autocomplete="off". I was in a situation where the password field was in the middle of a form with 9 text inputs and 5 sets of radio buttons. How often does a login form have all of that? And, none of the fields had “username” or “password” anywhere near them… not in the name or id attributes, nor in their associated <label> fields. AND, there were already prefilled values in the form that got overwritten by autocomplete. AND, Safari is even programmed to aggressively fight any efforts at a workaround, such as extra password fields, hidden with CSS.

It was the last bit that really irked me, because my experimentation showed that Safari is programmed to detect very specific CSS attributes being applied to other fields in the form to determine whether or not there’s a second password field (i.e. that this is a form for resetting your password). If it detects any of various ways of making the field invisible, like display: none; or visibility: hidden; or position: absolute; left: -9999px;, then it will still autocomplete the password. The only CSS I was able to fool it with was opacity: 0; but I suspect that will change soon too.


It’s fine to argue that web developers shouldn’t use autocomplete="off" on password fields, and I even agree, to an extent, for login forms. But if browsers are going to ignore it, and have intricate means of detecting efforts at circumventing that, then they should also recognize that there are legitimate uses for <input type="password"> outside of login forms, and in those cases, honor autocomplete="off".

Here are some suggestions:

Don’t ignore autocomplete="off" if the form contains more than three or four visible input fields. Most login forms only contain two fields. I’ve seen some with more, so I’m being generous here. But how often does a login form contain ten or more fields? Come on.

Look for additional context before autocompleting login fields. Yes, developers can find ways to circumvent this, but if the only clue that this is a login form is the presence of a single password field, then maybe it’s not a login form. Look at the name and id attributes, the <label> tag, and the form’s action attribute. If it really, really doesn’t look like a login form, especially if the developer has also added autocomplete="off", maybe give them the benefit of the doubt and settle down with the autocomplete. At least, maybe in these cases ask the user if they want to autocomplete instead of just doing it. I mean, in some cases the form may be long enough that the autocompleted fields are off screen and the user didn’t even notice they turned yellow.

Don’t replace prefilled values with autocomplete values. I would sincerely appreciate if someone could explain to me the logic behind this one. If a form already has values in the fields, then autocomplete should never overwrite those values. Maybe it’s because I mostly work with HTML forms that are really data editing screens, rather than submission forms, so my perspective is skewed. But the fact that web-based data editing screens are a common thing makes this a valid use case. If a form loads with most or all of the values prefilled, a browser should not presume that it’s OK to autocomplete any of the values.

Check for an indication that the user is already logged in. I suppose there’s a murky security issue here somewhere, but if the browser could detect a cookie with a session ID, or a “log out” link on the page, it would be a way of indicating that the user might already be logged in, and so autocompleting passwords wouldn’t make sense.

Implement support for autocomplete="new-password". Apparently Chrome supports this already, and admittedly it reeks of workaround, but at least it’s something.

With all of these suggestions, I am not saying browsers shouldn’t autocomplete password fields… I’m just suggesting that they look for signs that a password field is not part of a login form, and in those cases, honor autocomplete="off" on password inputs.