DEV Community

Jon Kao
Jon Kao

Posted on

How I defeated the iOS Autofill 'Paint Monster' with 5 invisible boxes.

The Problem:
When using secureTextEntry on iOS with the New Architecture (Fabric), the "Strong Password" autofill often triggers a permanent yellow background highlight. Because Fabric recycles native UITextField views to save memory, this yellow "infected" state carries over to unrelated TextInput fields on completely different screens—even if those fields have textContentType="none" or autoComplete="off".

The "Sacrificial Buffer" Solution:
iOS maps its autofill heuristics to the first few inputs it finds in the view hierarchy. By placing 5 invisible "sacrificial" inputs at the very top of your root layout, you shift the iOS "Form Map." The OS targets these dummy fields with the yellow highlight, leaving your actual UI clean.

The "Sacrifice" Component (NativeWind/React Native) -
Create this component to house your dummy targets.

import React from 'react';
import { TextInput, View } from 'react-native';

export const AutofillProtector = () => (
  <View 
    className="absolute h-0 w-0 overflow-hidden"
    pointerEvents="none" 
    aria-hidden={true}
    importantForAccessibility="no-hide-descendants"
  >
    {/* 5 inputs absorb the 'yellow hit' so your real fields don't have to */}
    {[...Array(5)].map((_, i) => (
      <TextInput 
        key={`sacrifice-${i}`}
        className="h-0 w-0 opacity-0"
        textContentType="username"
        editable={false}
      />
    ))}
  </View>
);
Enter fullscreen mode Exit fullscreen mode

How to use it -
Just drop it at the top of any screen that has TextInput fields you want to protect from the bleed:

import { AutofillProtector } from './components/AutofillProtector';

export default function YourScreen() {
  return (
    <View style={{ flex: 1 }}>
      <AutofillProtector />

      {/* Your actual inputs below */}
      <TextInput placeholder="Username" />
      <TextInput placeholder="Password" secureTextEntry />
    </View>
  );
}
Enter fullscreen mode Exit fullscreen mode

Why this works:
Unlike native patches to isReusable or canHaveDisplayList (which can be flaky across different RN versions), this addresses the root cause: iOS's internal mapping of the screen. By the time the "Yellow Paint Monster" gets to your real fields, it has already "spent" its highlight on the sacrificial inputs.

Top comments (0)