⏱️ Lectura: 14 min
Programaste un atajo con Ctrl+S y en Mac tu usuario presiona Cmd+S sin que pase nada: ese bug silencioso aparece en casi cualquier editor web que no distingue entre plataformas. Los atajos de teclado no son solo una preferencia de cada sistema operativo, sino un conjunto de nombres, teclas físicas y propiedades de evento que cambian entre Windows, macOS y Linux, y que tu código tiene que manejar explícitamente.
📑 En este artículo
- TL;DR
- ¿Qué son los atajos de teclado?
- Por qué importa
- Cómo funciona el mapeo de teclas entre sistemas
- Ejemplos prácticos de manejo de teclado en JavaScript
- Cómo empezar a probar atajos en tu navegador
- Casos de uso reales
- Errores comunes y buenas prácticas
- Comparativa de teclas entre Windows, Mac y Linux
- Profundizando: key vs code, dead keys e IME
- Preguntas frecuentes
- ¿Por qué las combinaciones de teclas como Ctrl+V no funcionan igual en Mac?
- ¿Qué diferencia hay entre event.key y event.code en un atajo de teclado?
- ¿Cómo detecto si el usuario está en Mac o Windows desde JavaScript?
- ¿Los atajos de teclado funcionan igual en Linux que en Windows?
- ¿Qué es la tecla Globe/Fn en los teclados de Apple?
- ¿Por qué Backspace se comporta distinto en Mac y Windows?
- Referencias
Esta guía repasa esas diferencias desde cero: qué tecla hace qué en cada sistema, cómo las ve JavaScript a través de KeyboardEvent, y cómo escribir una función que funcione igual sin importar dónde corra tu aplicación.
TL;DR
- metaKey se activa con Cmd en Mac y ctrlKey con Control en Windows: son dos propiedades distintas del mismo evento.
- Backspace en Windows equivale a Delete en Mac, y Delete en Windows equivale a Forward Delete en Mac.
- event.code identifica la tecla física sin importar el idioma del teclado; event.key cambia según el layout.
- Fn+Return simula la tecla Enter numérica en los MacBook que no tienen esa tecla física.
- Cmd+Q, Cmd+Tab y Ctrl+Alt+Supr nunca llegan a JavaScript porque el sistema operativo los intercepta antes.
¿Qué son los atajos de teclado?
Los atajos de teclado son combinaciones de una tecla modificadora (Ctrl, Alt o Cmd) y una tecla principal que disparan una acción en una aplicación. En la web no hay una sola combinación universal: Windows, macOS y Linux asignan nombres y funciones distintas a teclas como Control, Alt o Suprimir.
La causa de fondo es histórica. Apple diseñó su teclado alrededor de la tecla Comando (⌘) para evitar chocar con los atajos que el sistema reservaba para sí mismo, mientras que Windows heredó la convención de Control de los terminales Unix y DOS. Décadas después, ninguno de los dos layouts es más correcto que el otro: son dos soluciones distintas al mismo problema de reservar teclas para el sistema operativo.
Por qué importa
Para un desarrollador que nunca tocó código multiplataforma, esto puede sonar a detalle cosmético, pero no lo es. Una aplicación que solo revisa event.ctrlKey ignora por completo a los usuarios de Mac, porque en ese sistema el modificador real es Cmd y Control casi no se usa fuera de la terminal. Los atajos de teclado mal implementados generan tickets de soporte, reseñas negativas y, en apps colaborativas como editores de texto u hojas de cálculo, pérdida de confianza: el usuario asume que su Cmd+Z no deshizo nada, cuando en realidad el evento nunca llegó a dispararse.
Hay además un argumento de accesibilidad. Usuarios que dependen de lectores de pantalla o de teclados adaptados navegan aplicaciones enteras sin mouse, así que cada combinación de teclas rota es, para ellos, una función que simplemente no existe en esa plataforma.
Cómo funciona el mapeo de teclas entre sistemas
Windows ofrece tres modificadores para aplicaciones: Ctrl, Alt y Shift. macOS ofrece cuatro: Cmd (⌘), Option (⌥), Control (⌃) y Shift (⇧), más la tecla Globe/Fn que el sistema operativo reserva para sí mismo. Esa cuarta tecla le da a las apps de Mac un modificador extra: muchos programas usan Option para variantes de un atajo, por ejemplo Option+flecha para moverse por palabras en vez de por caracteres.
Los nombres también cambian. Lo que Windows llama Backspace, macOS lo llama Delete; lo que Windows llama Delete, macOS lo llama Forward Delete. Decir simplemente «presioná Delete» en una guía de usuario es ambiguo si no aclarás la plataforma. Algo similar pasa con Enter: Windows tiene una sola tecla Enter, pero Mac distingue entre Return (la tecla principal) y Enter (una tecla secundaria que solo existe en teclados con teclado numérico). En la mayoría del software de Mac ambas hacen lo mismo, salvo excepciones como Photoshop, donde Return agrega un salto de línea y Enter confirma la acción.
Para el navegador, cada tecla produce un objeto KeyboardEvent con varias propiedades relevantes: key (el carácter o nombre lógico, afectado por el layout), code (la posición física de la tecla, igual en cualquier layout) y los booleanos ctrlKey, metaKey, altKey y shiftKey, que indican qué modificadores estaban presionados en ese instante. El diagrama siguiente resume cómo viaja esa información desde que el usuario presiona una tecla hasta que tu código la recibe.
sequenceDiagram
participant U as Usuario
participant T as Teclado
participant N as Navegador
U->>T: presiona Cmd+K
T->>N: envia keydown
N->>N: lee metaKey y key
N-->>U: ejecuta el atajo
La pieza clave para el manejo del teclado multiplataforma es metaKey. En Windows y Linux, metaKey corresponde a la tecla Windows o Super y casi ninguna app la usa; en Mac, metaKey es Cmd, el modificador que los usuarios esperan para casi todo. Por eso la convención estándar en bibliotecas de atajos es tratar «metaKey en Mac» y «ctrlKey en Windows/Linux» como el mismo modificador lógico, al que suele llamarse Mod o Primary.
Ejemplos prácticos de manejo de teclado en JavaScript
Veamos cómo se traduce todo esto en código, de lo más simple a un caso que podrías pegar hoy en un proyecto real.
Primero, detectar en qué plataforma corre tu app:
function esMac() {
return navigator.userAgentData
? navigator.userAgentData.platform === 'macOS'
: /Mac/.test(navigator.platform);
}
console.log(esMac());
Esta función devuelve true en un Mac y false en Windows o Linux, usando la API moderna userAgentData cuando existe y navigator.platform como respaldo en navegadores que no la implementan.
Ahora, escuchemos qué llega realmente al evento cuando alguien presiona un atajo:
document.addEventListener('keydown', (event) => {
console.log({
key: event.key,
code: event.code,
ctrlKey: event.ctrlKey,
metaKey: event.metaKey,
});
});
Al presionar Cmd+K en Mac, la consola imprime literalmente:
{ key: "k", code: "KeyK", ctrlKey: false, metaKey: true }
Al presionar Ctrl+K en Windows, la misma función imprime:
{ key: "k", code: "KeyK", ctrlKey: true, metaKey: false }
El valor de code no cambia entre sistemas porque identifica la posición física de la tecla; lo que cambia es cuál booleano se activa. A partir de esa diferencia se construye una función de atajo real:
function esAtajoPrimario(event, letra) {
const modificador = event.metaKey || event.ctrlKey;
return modificador && event.key.toLowerCase() === letra;
}
document.addEventListener('keydown', (event) => {
if (esAtajoPrimario(event, 's')) {
event.preventDefault();
guardarDocumento();
}
});
Esta función trata Cmd (Mac) y Ctrl (Windows/Linux) como el mismo modificador lógico, el patrón estándar para implementar algo como «Guardar» con un solo bloque de código en lugar de ramificar por plataforma en cada atajo.
flowchart TD
A["Usuario presiona una tecla"] --> B{"event.metaKey es true?"}
B -->|"Si"| C["Tratar como Mod (Mac)"]
B -->|"No"| D{"event.ctrlKey es true?"}
D -->|"Si"| E["Tratar como Mod (Windows/Linux)"]
C --> F["Comparar event.key con el atajo"]
E --> F
💡 Tip: usá
event.codeen vez deevent.keycuando el atajo dependa de la posición física de la tecla, como en juegos con WASD, porqueevent.codeno cambia con el idioma del teclado mientras queevent.keysí.
Cómo empezar a probar atajos en tu navegador
No necesitás instalar nada para experimentar con esto. Abrí las herramientas de desarrollador de tu navegador (F12 en Windows y Linux, Cmd+Option+I en Mac), entrá a la pestaña Console, pegá el listener de keydown de la sección anterior y presioná Enter.
Con el listener activo, hacé clic en cualquier parte de la página para que tenga el foco y probá distintas combinaciones: Ctrl+K, Cmd+K, Alt+Flecha, Option+Flecha. Cada pulsación imprime un objeto en la consola con los valores exactos de key, code, ctrlKey y metaKey para esa tecla en tu sistema, que podés comparar directamente contra los ejemplos de este artículo.
Casos de uso reales
Editores web como los de Google Docs o Notion implementan su propia capa de normalización de atajos: internamente traducen «Mod+B» a Cmd+B en Mac y Ctrl+B en Windows antes de registrar el listener, en vez de escribir cada combinación dos veces. Las bibliotecas de atajos más usadas en frontend (Mousetrap, hotkeys-js) siguen el mismo principio con un alias «mod» que resuelve en tiempo de ejecución según la plataforma detectada.
En videojuegos del navegador el problema es distinto: ahí lo que importa es la posición física del teclado, no el carácter. Un juego que mapea WASD usando event.key se rompe en un teclado AZERTY francés, porque en esa distribución las teclas físicas W, A, S y D producen los caracteres Z, Q, S y D. Usar event.code («KeyW», «KeyA», etc.) resuelve esto porque identifica la tecla física, no el símbolo impreso.
En aplicaciones bancarias o de formularios con validación estricta, el manejo del teclado también define accesibilidad legal: un usuario que navega solo con teclado necesita que Tab, Shift+Tab y Enter funcionen de forma predecible en cualquier plataforma, sin que el foco se pierda al cambiar de Windows a Mac.
Errores comunes y buenas prácticas
El error más frecuente es revisar solo event.ctrlKey y asumir que cubre a todos los usuarios; en Mac eso deja afuera a quien usa Cmd, que es el modificador esperado ahí. La solución es siempre combinar metaKey || ctrlKey para el modificador primario, salvo que tengas una razón explícita para distinguirlos.
Otro error es asumir que todos los teclados son QWERTY en inglés. Los layouts en español de Latinoamérica usan teclas muertas para tildes: al presionar ´ seguido de «a» se compone una á, y durante ese proceso el navegador dispara eventos de composición en vez de un keydown normal con la letra final. Un atajo que escucha cada keydown sin revisar event.isComposing puede disparar acciones no deseadas mientras el usuario todavía está escribiendo un acento.
También es común olvidar que ciertas combinaciones están reservadas por el sistema operativo y nunca van a llegar a tu código, sin importar qué tan bien esté escrito el listener.
⚠️ Ojo: no podés interceptar Cmd+Q, Cmd+Tab ni Ctrl+Alt+Supr desde JavaScript: el sistema operativo las captura antes de que lleguen al navegador, así que cualquier atajo que dependa de esas combinaciones nunca va a funcionar en la web.
Comparativa de teclas entre Windows, Mac y Linux
La tabla siguiente resume las equivalencias más relevantes para quien escribe código multiplataforma.
| Windows / Linux | macOS | Qué hace |
|---|---|---|
| Ctrl | Cmd (⌘) | Modificador primario de atajos de aplicación |
| Alt | Option (⌥) | Modificador secundario, variantes de un atajo |
| (tecla Windows) | Globe/Fn | Reservada por el sistema operativo |
| Backspace | Delete | Borra el carácter anterior al cursor |
| Delete | Forward Delete (solo teclados full-size) | Borra el carácter siguiente al cursor |
| Enter | Return | Confirma, envía o agrega una nueva línea |
| (sin equivalente directo) | Enter numérico (⌤, solo teclado numérico) | Acción secundaria en apps como Photoshop |
Profundizando: key vs code, dead keys e IME
La diferencia entre event.key y event.code es la que más confunde a quien recién llega a este tema. key es el valor lógico después de aplicar el layout: en un teclado en español, la tecla física junto a Enter produce «ñ» como key, pero su code siempre es el mismo identificador físico en cualquier distribución. Para atajos de aplicación (Guardar, Copiar, Buscar) conviene usar key, porque el usuario espera que la letra impresa en su teclado dispare la acción. Para controles de juego o posiciones fijas conviene code, porque no depende del idioma.
Las teclas muertas (dead keys) complican esto todavía más en teclados latinoamericanos. Al escribir á, é o ñ usando una tecla muerta, el navegador puede disparar eventos de composición (compositionstart, compositionupdate, compositionend) en lugar de, o además de, los keydown normales, según el navegador y el sistema operativo. Lo mismo pasa a mayor escala con los métodos de entrada (IME) usados para escribir chino, japonés o coreano, donde una secuencia larga de teclas se traduce en un solo carácter final. La propiedad event.isComposing permite a tu código ignorar esos eventos intermedios y reaccionar solo cuando la composición terminó.
Para depurar el estado exacto de las teclas de bloqueo como Caps Lock, el método getModifierState() de KeyboardEvent devuelve si un modificador específico está activo en el momento del evento, útil para casos como advertir a un usuario que Caps Lock está encendido al escribir una contraseña.
Tu próximo paso: pegá el listener de keydown de la sección de ejemplos en la consola de tu navegador, activá Caps Lock y compará qué cambia en el objeto que imprime getModifierState('CapsLock') frente a event.key.
📖 Resumen en Telegram: Ver resumen
Preguntas frecuentes
¿Por qué las combinaciones de teclas como Ctrl+V no funcionan igual en Mac?
Porque en Mac el modificador esperado para pegar es Cmd, no Control. El evento de teclado expone esto como metaKey en vez de ctrlKey, así que un código que solo revisa ctrlKey nunca detecta Cmd+V en una Mac.
¿Qué diferencia hay entre event.key y event.code en un atajo de teclado?
event.key depende del layout e idioma del teclado; event.code identifica la posición física de la tecla sin importar qué carácter imprima. Para atajos de aplicación normalmente conviene key, y para controles de juego o posiciones fijas conviene code.
¿Cómo detecto si el usuario está en Mac o Windows desde JavaScript?
Con navigator.userAgentData.platform en navegadores modernos, o con navigator.platform como alternativa compatible con navegadores más antiguos, comparando si el valor contiene «Mac».
¿Los atajos de teclado funcionan igual en Linux que en Windows?
Casi siempre sí, porque Linux también usa ctrlKey como modificador primario y comparte la mayoría de los nombres de tecla con Windows. Las diferencias aparecen sobre todo en entornos de escritorio específicos que reasignan atajos globales del sistema.
¿Qué es la tecla Globe/Fn en los teclados de Apple?
Es una tecla reservada por macOS para funciones del sistema, como cambiar de idioma de entrada o abrir el panel de emojis. Las aplicaciones web no pueden leerla ni usarla como modificador propio.
¿Por qué Backspace se comporta distinto en Mac y Windows?
No es que se comporte distinto: es que Mac le da ese comportamiento (borrar hacia atrás) a una tecla que llama Delete, mientras Windows reserva el nombre Delete para la tecla que borra hacia adelante, la que Mac llama Forward Delete.
Referencias
- Unsung (Marcin Wichary): artículo original con el detalle exhaustivo de nombres y símbolos de teclas entre Windows y Mac.
- MDN Web Docs: documentación oficial de la interfaz KeyboardEvent y sus propiedades.
- MDN Web Docs: lista de valores estándar para la propiedad key, incluyendo getModifierState().
- Wikipedia: historia y definición general de las teclas modificadoras en distintos sistemas.
📱 ¿Te gusta este contenido? Únete a nuestro canal de Telegram @programacion donde publicamos a diario lo más relevante de tecnología, IA y desarrollo. Resúmenes rápidos, contenido fresco todos los días.
Imagen destacada: Foto de Zulfugar Karimov en Unsplash
¿Te sirvió? ¿Te dio otro error? Contalo abajo: las preguntas se responden y le sirven al siguiente que llegue.
Dejar un comentario
0 Comentarios