Puede usar < table > para eso para estructurar su texto:
let numbers = "<tbody>"; for (let i = 1; i <= 13; i++){ numbers += '</tr>'; for (let j = 1; j<= 13; j++){ numbers += `<td>${i*j}</td>`; } numbers += '</tr>'; } numbers += "</tbody>" const element = document.querySelector("#element"); element.innerHTML = numbers; td { text-align: right; width: 2em; } <table id="element">Podrías ser ambicioso y, como dijo David, usar CSS para tomar el peso de cómo deben mostrarse los datos. He usado CSS grid en este ejemplo, lo que significa que solo necesita tener un bucle y el CSS se encarga del resto.
const arr = []; const size = 13; const limit = size * size; // Push an HTML template string into // the array for (var i = 1; i <= limit; i++) { arr.push(`<div>${i}</div>`); } // Add the joined array (it makes an HTML string // to the element with the `grid` class const grid = document.querySelector('.grid'); grid.innerHTML = arr.join(''); .grid { display: grid; grid-template-columns: repeat(13, 30px); grid-gap: 0.2em; } .grid div { border: 1px solid #cdcdcd; font-size: 0.8em; background-color: #efefef; text-align: center; padding: 0.5em 0; } <div class="grid"></div>Documentación adicional
Editar: incluso puede crear una función que acepte un número y, utilizando variables CSS , la función calculará el tamaño de la cuadrícula requerida y devolverá el HTML.
function createGrid(columns) { const arr = []; const grid = columns * columns; document.documentElement.style.setProperty('--columns', columns) // Push an HTML template string into // the array for (var i = 1; i <= grid; i++) { arr.push(`<div>${i}</div>`); } return arr.join(''); } const grid = document.querySelector('.grid'); grid.innerHTML = createGrid(5); :root { --columns: 13; } .grid { display: grid; grid-template-columns: repeat(var(--columns), 40px); grid-gap: 0.2em; } .grid div { border: 1px solid #cdcdcd; font-size: 0.8em; background-color: #efefef; text-align: center; padding: 0.5em 0; } <div class="grid"></div>Puede usar el enfoque de grid con algunas variables de CSS para crear elementos de celda; para obtener más detalles, consulte los comentarios en el fragmento de código:
También puede representar los encabezados de las celdas.
const gridSize = 13; // get grid element const grid = document.querySelector('.grid'); // create temporary wrapper const fragmentWrapper = document.createDocumentFragment(); const renderTop = () => { for (var i = 0; i <= gridSize; i++) { if (i === 0) { // render mult char renderCell('x'); continue; } renderCell(i, true); } } const renderGrid = () => { // append cells to wrapper for (var i = 1; i <= gridSize; i++) { for (var j = 0; j <= gridSize; j++) { if (j === 0) { // render heading cell const num = i; renderCell(num, true); continue; } // render default cell const num = i * j; renderCell(num); } } } const renderCell = (num, select = false) => { // create temporary cell const cell = document.createElement('div'); cell.className = 'cell'; // if requested to highligh cell select && cell.classList.add('select'); cell.innerText = `${ num }`; // add cell to grid fragmentWrapper.append(cell); } renderTop(); renderGrid(); // set grid size grid.style.setProperty('--grid-size', gridSize); // render grid grid.append(fragmentWrapper); .grid { display: grid; grid-template-columns: repeat(calc(var(--grid-size) + 1), 1fr); /* using CSS grid size (set in JS) */ gap: .25rem; } .cell { display: flex; align-items: center; /* align content */ justify-content: center; /* align content */ aspect-ratio: 1/1; /* make cell square */ border: 1px solid #d4d4d4; /* show cell borders */ } .cell.select { background-color: tomato; color: white; font-weight: bold; } <div class="grid"></div>