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.
| Capa | Qué estiliza | Cómo la estilizas |
|---|---|---|
| Dentro del iframe | El texto del input, el placeholder y el cursor renderizados por el campo seguro | Objeto ElementStyle pasado como style |
| Alrededor del iframe | Bordes, relleno, fondo, anillo de foco, estados de validación | Tu 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.
| Propiedad | Type | Descripción |
|---|---|---|
color | string | Color del texto del valor del input (cualquier color CSS). |
fontSize | string | Tamaño de fuente del texto del input, p. ej. "16px". |
fontFamily | string | Pila de fuentes para el texto del input. Consulta Carga de fuentes personalizadas. |
fontWeight | string | Grosor de la fuente, p. ej. "400" o "600". |
lineHeight | string | Altura 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.
| Selector | Apunta a |
|---|---|
::placeholder | El texto del placeholder que se muestra mientras el campo está vacío. |
:focus | El 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.
| Estado | Aplicado cuando | Uso típico |
|---|---|---|
empty | El campo aún no tiene valor | Atenuar el color del cursor/texto antes del input |
complete | El valor está completo y es válido | Confirmar el éxito con un tono verde |
invalid | El valor actual no supera la validación | Advertir 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:
: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.- 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
- Descripción general del Bridge SDK — instala el SDK y crea elementos.
- Tokenización — convierte los datos de tarjeta recopilados en una referencia de token.
- Autenticación — claves públicas vs. secretas y dónde pertenece cada una.