Compartir en Twitter
Go to Homepage

CONSTRUYE TU PROPIO CLON DE WORDLE USANDO JAVASCRIPT PURO

January 5, 2026

Introducción al desarrollo de un clon de Wordle en JavaScript

El juego Wordle se convirtió en un fenómeno global por su simplicidad y adicción. Consiste en adivinar una palabra de cinco letras en un máximo de seis intentos, recibiendo retroalimentación visual sobre la corrección de cada letra. En este tutorial, exploraremos cómo construir un clon completo utilizando tecnologías web estándar: HTML para la estructura, CSS para el estilo y JavaScript para la lógica del juego. Este enfoque permite entender los fundamentos del desarrollo frontend sin depender de frameworks complejos.

El resultado será un juego funcional que incluye un tablero de intentos, un teclado en pantalla, manejo de entradas del usuario, validación de palabras, colores indicativos y animaciones básicas. Al finalizar, tendrás un proyecto práctico que puedes ampliar o desplegar en tu portafolio.

Configuración inicial del proyecto

Comienza creando una carpeta principal para el proyecto. Dentro de ella, genera los archivos necesarios: index.html, style.css y script.js. Esta estructura simple facilita el mantenimiento y la ejecución local.

Para visualizar los cambios en tiempo real, utiliza un servidor de desarrollo ligero. Aunque en entornos modernos puedes abrir directamente el archivo HTML, un servidor evita problemas con módulos JavaScript.

En index.html, define la estructura básica:

<!DOCTYPE html>
<html lang="es">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Clon de Wordle</title>
        <link rel="stylesheet" href="style.css" />
    </head>
    <body>
        <h1>Clon de Wordle</h1>
        <div id="game-board"></div>
        <div id="keyboard-cont"></div>
    </body>
</html>

Este código establece un contenedor para el tablero y otro para el teclado. Más adelante se llenarán dinámicamente.

En style.css, agrega estilos iniciales:

h1 {
    text-align: center;
}

#game-board {
    display: flex;
    align-items: center;
    flex-direction: column;
}

.letter-box {
    border: 2px solid gray;
    border-radius: 3px;
    margin: 2px;
    font-size: 2.5rem;
    font-weight: 700;
    height: 3rem;
    width: 3rem;
    display: flex;
    justify-content: center;
    align-items: center;
    text-transform: uppercase;
}

.letter-row {
    display: flex;
}

Estos estilos centran el contenido y definen la apariencia de las casillas.

Preparación de la lista de palabras y variables globales

El juego requiere una lista de palabras válidas de cinco letras. Crea un archivo words.js con un array exportado:

export const WORDS = [
    "casa",
    "perro",
    "gato",
    "arbol",
    "luz" /* agrega cientos de palabras de 5 letras */,
    // ... más palabras en español para mayor variedad
];

En script.js, importa el array y define variables globales:

import { WORDS } from "./words.js";

const NUMBER_OF_GUESSES = 6;
let guessesRemaining = NUMBER_OF_GUESSES;
let currentGuess = [];
let nextLetter = 0;
let rightGuessString =
    WORDS[Math.floor(Math.random() * WORDS.length)].toLowerCase();

La palabra objetivo se selecciona aleatoriamente cada vez que se carga la página. Para depuración temporal, puedes console.log la palabra, pero remuévelo en producción.

Enfócate en usar palabras en minúsculas para simplificar comparaciones.

Construcción dinámica del tablero de juego

El tablero consta de seis filas con cinco casillas cada una. Crea una función para generarlo dinámicamente:

function initBoard() {
    let board = document.getElementById("game-board");

    for (let i = 0; i < NUMBER_OF_GUESSES; i++) {
        let row = document.createElement("div");
        row.className = "letter-row";

        for (let j = 0; j < 5; j++) {
            let box = document.createElement("div");
            box.className = "letter-box";
            row.appendChild(box);
        }

        board.appendChild(row);
    }
}

initBoard();

Llama a esta función al final de script.js. Esto asegura que el tablero esté listo antes de cualquier interacción.

Agrega estilos adicionales para casillas llenas:

.filled-box {
    border: 2px solid black;
}

Implementación del teclado virtual en pantalla

El teclado facilita la interacción en dispositivos táctiles. Agrega el HTML correspondiente dentro del div #keyboard-cont en index.html:

<div id="keyboard-cont">
    <div class="first-row">
        <button class="keyboard-button">q</button>
        <button class="keyboard-button">w</button>
        <button class="keyboard-button">e</button>
        <!-- continuar con r t y u i o p -->
    </div>
    <div class="second-row">
        <button class="keyboard-button">a</button>
        <button class="keyboard-button">s</button>
        <!-- d f g h j k l -->
    </div>
    <div class="third-row">
        <button class="keyboard-button">Del</button>
        <button class="keyboard-button">z</button>
        <!-- x c v b n m -->
        <button class="keyboard-button">Enter</button>
    </div>
</div>

Completa las letras según el teclado QWERTY estándar.

Estilos para el teclado:

#keyboard-cont {
    margin: 1rem 0;
    display: flex;
    flex-direction: column;
    align-items: center;
}

#keyboard-cont div {
    display: flex;
}

.second-row {
    margin: 0.5rem 0;
}

.keyboard-button {
    font-size: 1rem;
    font-weight: 700;
    padding: 0.5rem;
    margin: 0 2px;
    cursor: pointer;
    text-transform: uppercase;
}

Este diseño asegura responsividad básica.

Manejo de entrada del usuario mediante teclado físico

Captura eventos de teclas para insertar letras, borrar y enviar intentos:

document.addEventListener("keyup", (e) => {
    if (guessesRemaining === 0) {
        return;
    }

    let pressedKey = String(e.key);

    if (pressedKey === "Backspace" && nextLetter !== 0) {
        deleteLetter();
        return;
    }

    if (pressedKey === "Enter") {
        checkGuess();
        return;
    }

    let found = pressedKey.match(/[a-z]/gi);
    if (!found || found.length > 1) {
        return;
    } else {
        insertLetter(pressedKey);
    }
});

La función insertLetter agrega la letra a la casilla actual:

function insertLetter(pressedKey) {
    if (nextLetter === 5) {
        return;
    }

    pressedKey = pressedKey.toLowerCase();

    let row =
        document.getElementsByClassName("letter-row")[6 - guessesRemaining];
    let box = row.children[nextLetter];
    box.textContent = pressedKey;
    box.classList.add("filled-box");
    currentGuess.push(pressedKey);
    nextLetter += 1;
}

Para borrar:

function deleteLetter() {
    let row =
        document.getElementsByClassName("letter-row")[6 - guessesRemaining];
    let box = row.children[nextLetter - 1];
    box.textContent = "";
    box.classList.remove("filled-box");
    currentGuess.pop();
    nextLetter -= 1;
}

Estas funciones mantienen el estado sincronizado con la interfaz.

Validación y retroalimentación del intento

La lógica central reside en evaluar el intento. La función checkGuess verifica longitud, validez y asigna colores:

function checkGuess() {
    let row =
        document.getElementsByClassName("letter-row")[6 - guessesRemaining];
    let guessString = currentGuess.join("");
    let rightGuess = Array.from(rightGuessString);

    if (guessString.length != 5) {
        alert("No hay suficientes letras");
        return;
    }

    if (!WORDS.includes(guessString)) {
        alert("Palabra no válida");
        return;
    }

    for (let i = 0; i < 5; i++) {
        let letterColor = "";
        let box = row.children[i];
        let letter = currentGuess[i];

        let letterPosition = rightGuess.indexOf(letter);

        if (letterPosition === -1) {
            letterColor = "grey";
        } else {
            if (letter === rightGuess[i]) {
                letterColor = "green";
            } else {
                letterColor = "yellow";
            }
            rightGuess[letterPosition] = "#";
        }

        let delay = 250 * i;
        setTimeout(() => {
            box.style.backgroundColor = letterColor;
            shadeKeyBoard(letter, letterColor);
        }, delay);
    }

    if (guessString === rightGuessString) {
        alert("¡Adivinaste correctamente!");
        guessesRemaining = 0;
        return;
    } else {
        guessesRemaining -= 1;
        currentGuess = [];
        nextLetter = 0;

        if (guessesRemaining === 0) {
            alert(
                "Se acabaron los intentos. La palabra era: " + rightGuessString
            );
        }
    }
}

La función shadeKeyBoard actualiza colores en el teclado virtual:

function shadeKeyBoard(letter, color) {
    for (const elem of document.getElementsByClassName("keyboard-button")) {
        if (elem.textContent.toLowerCase() === letter) {
            let oldColor = elem.style.backgroundColor;
            if (oldColor === "green") {
                return;
            }
            if (oldColor === "yellow" && color !== "green") {
                return;
            }
            elem.style.backgroundColor = color;
            break;
        }
    }
}

Esto proporciona retroalimentación visual persistente en el teclado.

Integración del teclado en pantalla

Haz que los botones generen eventos equivalentes al teclado físico:

document.getElementById("keyboard-cont").addEventListener("click", (e) => {
    const target = e.target;

    if (!target.classList.contains("keyboard-button")) {
        return;
    }

    let key = target.textContent;

    if (key === "Del") {
        key = "Backspace";
    }

    document.dispatchEvent(new KeyboardEvent("keyup", { key: key }));
});

Esto reutiliza la lógica existente, manteniendo el código limpio.

Adición de animaciones para mayor inmersión

Las animaciones mejoran la experiencia del usuario. Aunque originalmente se usaban bibliotecas externas, puedes implementar efectos simples con CSS transitions o keyframes.

Por ejemplo, agrega una clase para pulso al insertar letra:

@keyframes pulse {
    0% {
        transform: scale(1);
    }
    50% {
        transform: scale(1.1);
    }
    100% {
        transform: scale(1);
    }
}

.pulse {
    animation: pulse 0.3s ease;
}

Modifica insertLetter:

// En insertLetter, después de agregar la clase filled-box
box.classList.add("pulse");
setTimeout(() => box.classList.remove("pulse"), 300);

Para el volteo al revelar colores, define otro keyframe y aplícalo con delay similar.

Estas animaciones hacen que el juego se sienta más dinámico y profesional.

Mejoras adicionales y consideraciones modernas

En 2026, considera aspectos como accesibilidad: agrega atributos aria-label a casillas y botones. Implementa almacenamiento local para guardar estadísticas de partidas anteriores.

Para palabras en español, amplía el array WORDS con un conjunto robusto de términos comunes. Puedes obtener listas públicas de palabras válidas.

El manejo de acentos y ñ puede requerir ajustes adicionales en la validación y teclado.

Prueba el juego en diferentes dispositivos para asegurar responsividad. Ajusta tamaños de fuente y márgenes según sea necesario.

La lógica de colores prioriza verde sobre amarillo, y gris para ausentes, replicando fielmente el comportamiento original.

Conclusiones

Has completado la construcción de un clon funcional de Wordle utilizando solo HTML, CSS y JavaScript puro. Este proyecto demuestra conceptos clave como manipulación del DOM, manejo de eventos, lógica condicional y estado de aplicación.

Puedes extenderlo agregando modos oscuro, estadísticas persistentes, compartir resultados o incluso multiplayer. Lo importante es que ahora posees las herramientas para crear juegos interactivos en el navegador de manera autónoma.

Este tipo de proyectos fortalecen habilidades frontend y son excelentes para portafolios. Experimenta, modifica y comparte tu versión única. El desarrollo de juegos web sigue siendo un campo fértil para la creatividad técnica. ¡Disfruta jugando y programando!