Estilizado de elementos

Estiliza los campos seguros del Bridge SDK de Tokeflow con la API ElementStyle y refleja el estado en vivo del elemento en tu propio contenedor mediante CSS.

Los campos seguros de Tokeflow se ejecutan dentro de iframes aislados y de origen cruzado; los datos de la tarjeta se cifran en el navegador y nunca llegan a tus servidores. Debido a que los inputs viven en otro origen, no puedes acceder a su interior con el CSS de tu página, por lo que el Bridge SDK te ofrece una API estructurada ElementStyle para estilizar el texto dentro del iframe, y un evento change que usas para estilizar el contenedor alrededor del iframe.

Juntas, estas dos capas permiten que los campos seguros se integren perfectamente con tu marca mientras mantienen los datos del titular de la tarjeta completamente aislados.

El estilizado es puramente presentacional. Nunca cambia cómo se recopilan, cifran o tokenizan los datos; consulta Tokenización para conocer el flujo de datos.

Las dos capas de estilizado

Hay dos superficies distintas, y se estilizan de dos maneras diferentes.

CapaQué estilizaCómo la estilizas
Dentro del iframeEl texto del input, el placeholder y el cursor renderizados por el campo seguroObjeto ElementStyle pasado como style
Alrededor del iframeBordes, relleno, fondo, anillo de foco, estados de validaciónTu propio CSS, controlado por el evento change

La API ElementStyle

Pasa un objeto style cuando creas un elemento. Este mapea reglas de estilo al input renderizado dentro del iframe.

const style = {
  base: {
    color: '#333333',
    fontSize: '16px',
    fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
    fontWeight: '400',
    lineHeight: '24px',
    '::placeholder': { color: '#aaaaaa', fontStyle: 'italic' },
    ':focus': { color: '#000000' },
  },
  complete: { color: '#28a745' }, // input is complete and valid
  invalid: { color: '#dc3545' },  // input is invalid
  empty: { color: '#6c757d' },    // input is empty
};

const cardElement = tokeflow.createCardElement({ style });

Estilos base

El objeto base contiene la apariencia predeterminada, aplicada en todos los estados a menos que sea sobrescrita por un bloque específico de estado. Estas son las propiedades tipográficas fundamentales admitidas.

PropiedadTypeDescripción
colorstringColor del texto del valor del input (cualquier color CSS).
fontSizestringTamaño de fuente del texto del input, p. ej. "16px".
fontFamilystringPila de fuentes para el texto del input. Consulta Carga de fuentes personalizadas.
fontWeightstringGrosor de la fuente, p. ej. "400" o "600".
lineHeightstringAltura de línea del texto del input, p. ej. "24px".

Iguala fontSize, fontFamily y lineHeight a los inputs del formulario que rodean el campo para que el campo seguro sea visualmente indistinguible de tus campos nativos.

Pseudo-selectores

Dentro de base, dos pseudo-selectores te permiten apuntar a sub-estados del input.

SelectorApunta a
::placeholderEl texto del placeholder que se muestra mientras el campo está vacío.
:focusEl input mientras tiene el foco.

Cada uno acepta las mismas propiedades tipográficas que base:

const style = {
  base: {
    color: '#1a1a1a',
    fontSize: '16px',
    '::placeholder': {
      color: '#9aa0a6',
      fontStyle: 'italic',
    },
    ':focus': {
      color: '#000000',
    },
  },
};

Estilos de estado

Más allá de base, puedes proporcionar bloques de estado de nivel superior que sobrescriben el color base (y otras propiedades) a medida que cambia el input del titular de la tarjeta. El SDK los aplica automáticamente según el estado en vivo del elemento.

EstadoAplicado cuandoUso típico
emptyEl campo aún no tiene valorAtenuar el color del cursor/texto antes del input
completeEl valor está completo y es válidoConfirmar el éxito con un tono verde
invalidEl valor actual no supera la validaciónAdvertir con un tono rojo
const style = {
  base: {
    color: '#333333',
    fontSize: '16px',
    lineHeight: '24px',
  },
  empty: { color: '#6c757d' },
  complete: { color: '#28a745' },
  invalid: { color: '#dc3545' },
};

Los estilos de estado solo afectan a las propiedades que puedes establecer en el texto del input (como color). Para reestilizar el marco —bordes, fondo, sombras— controla tu contenedor con el evento change, cubierto en Estilizado del contenedor.

Carga de fuentes personalizadas

Si tu fontFamily hace referencia a una fuente web que no es una fuente del sistema, decláralo mediante el array fonts para que el iframe pueda cargarla. Usa la misma opción en elementOptions (aplicada a cada elemento) o por elemento.

const tokeflow = new TokeflowBridge({
  publicKey: 'pk_live_mer_xxxxxxxx',
  elementOptions: {
    fonts: ['https://fonts.example.com/inter.css'],
    style: {
      base: {
        fontFamily: '"Inter", sans-serif',
        fontSize: '16px',
      },
    },
  },
});

Las claves públicas (pk_live_…) son seguras para incluir en el código del navegador. Nunca coloques una clave secreta (sk_live_…) en el código del lado del cliente; consulta Autenticación.

Estilizado del contenedor

El iframe se ubica dentro de un elemento contenedor que tú controlas. Estiliza ese contenedor con CSS común para manejar todo lo que el iframe no puede: bordes, relleno, fondo, anillos de foco y estados de validación.

Dos técnicas funcionan juntas:

  1. :focus-within — una pseudo-clase nativa de CSS que coincide con tu contenedor siempre que el foco esté dentro de él (incluido dentro del iframe). Úsala para el anillo de foco sin necesidad de JavaScript.
  2. Clases de estado del evento change — alterna tus propias clases (p. ej. invalid, complete) en el contenedor en respuesta al estado en vivo del elemento.

CSS

.card-element-container {
  border: 1px solid #dddddd;
  border-radius: 8px;
  padding: 12px;
  background: #fafafa;
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

/* Focus ring — pure CSS, fires when focus is inside the iframe */
.card-element-container:focus-within {
  border-color: #0066ff;
  box-shadow: 0 0 0 3px rgba(0, 102, 255, 0.15);
}

/* Validation states — toggled from the change event */
.card-element-container.invalid {
  border-color: #dc3545;
}
.card-element-container.complete {
  border-color: #28a745;
}

JavaScript

Monta el elemento en el contenedor y luego refleja su estado en el contenedor desde el evento change.

const cardElement = tokeflow.createCardElement({ style });
cardElement.mount('.card-element-container');

const container = document.querySelector('.card-element-container');

cardElement.on('change', (event) => {
  // event.error is singular; event.empty / event.complete are booleans
  container.classList.toggle('invalid', !!event.error && !event.empty);
  container.classList.toggle('complete', event.complete);
});

El payload del evento change expone únicamente estado y metadatos no sensibles, nunca los datos brutos de la tarjeta:

interface ElementChangeEvent {
  elementType: ElementType;
  empty: boolean;
  complete: boolean;
  error?: ElementError;   // singular — there is no `errors` array
  value?: {               // non-sensitive metadata only
    type?: string;
    brand?: string;       // e.g. 'visa', 'mastercard'
    bin?: string;
    last4?: string;
  };
}

También puedes leer el mismo estado de forma síncrona en cualquier momento con element.getState(), que devuelve { empty, focused, valid, invalid, complete, error? }. El evento change es ideal para la UI en vivo; getState() es ideal para comprobaciones puntuales (por ejemplo, antes de tokenizar).

Juntándolo todo

Un campo de tarjeta mínimo y totalmente estilizado:

<div class="card-element-container"></div>
const tokeflow = new TokeflowBridge({ publicKey: 'pk_live_mer_xxxxxxxx' });
await tokeflow.init();

const cardElement = tokeflow.createCardElement({
  style: {
    base: {
      color: '#1a1a1a',
      fontSize: '16px',
      fontFamily: '"Inter", sans-serif',
      lineHeight: '24px',
      '::placeholder': { color: '#9aa0a6' },
    },
    complete: { color: '#28a745' },
    invalid: { color: '#dc3545' },
  },
  placeholder: {
    cardNumber: '1234 5678 9012 3456',
    cardExpirationDate: 'MM/YY',
    cardSecurityCode: 'CVC',
  },
});

cardElement.mount('.card-element-container');

const container = document.querySelector('.card-element-container');
cardElement.on('change', (event) => {
  container.classList.toggle('invalid', !!event.error && !event.empty);
  container.classList.toggle('complete', event.complete);
});

Objeto theme avanzado

ElementStyle cubre los casos comunes. Para un control más detallado, puedes pasar un objeto theme de nivel más bajo en su lugar, con un mapa styles indexado por selectores internos. Esta es una vía de escape para diseños avanzados y no es necesaria para la mayoría de las integraciones.

const cardElement = tokeflow.createCardElement({
  theme: {
    styles: {
      '.field input': { fontSize: 16, color: '#333333' },
    },
  },
});

Los selectores de theme apuntan a la estructura interna del elemento y son menos estables entre versiones del SDK que ElementStyle. Prefiere ElementStyle por portabilidad, y recurre a theme solo cuando necesites una regla que ElementStyle no expone.

Próximos pasos

En esta página