✍️ Adaptive table with N breakpoints
Introduction
In this short article, we will look at the layout of an adaptive table. The layout of the table today can be created in several ways, for example: using:
- html table
- display table
- dispay grid
наверняка есть еще способы. В этом обзоре я буду работать с html table и использовать не очень много javascript, для того чтобы адаптировать макет к трем media breakpoint. У table есть несколько удобных инструментов:
- table.insertRow и row.insertCell - для того чтобы добавить в таблицу строку и ячейку
- table.rows и row.cells - для быстрого доступа по индексу
есть и другие удобные методы таблицы о которых можно прочитать на сайте MDN
Разработка
Я сделал этот пример для ответа в теме Выравнивание карточек товаров в списке. Основное условие поставленной задачи это позиции в соседних блоках, должны находиться на одной горизонтальной линии. Альтернативно предлагался вариант задавать высоту строчек с помощью javascript определяя позицию ссамой большой высотой и под нее подстраивать все остальные. Я предложил использовать табличную верстку которая специально разработана, для того чтобы все ячейки в одной троке имели одинаковую высоту.
Проблема которую предстояло решить это сделать таблицу адаптируемой к различной ширине экрана.
Для начала сделаем триггер который сработает на мену media breakpoint
// media breakpoints
const breakpoints = [0, 500, 600, 700, 800, 900, Infinity];
const viewportChanged = () => {
const w = document.documentElement.clientWidth;
const columnsNew = breakpoints.findIndex((e) => w < e);
if (columnsNew !== columns) {
columns = columnsNew;
fillTable();
}
};
viewportChanged();
window.addEventListener("resize", viewportChanged);
window.addEventListener("orientationChange", viewportChanged);
Следующая задача заполнение таблицы:
// число колонок в таблице на текущем брейкпоинте
let columns;
// ссылка на таблицу с сущностями
const table = document.getElementById("table");
// количество свойств у сущности или подругому сколько строк будет занимать каждая сущность
const entityPropsCount = 3;
// число сущностей в таблице
const entityNum = 120;
/**
* Заполняет таблицу HTML
*/
const fillTable = () => {
table.innerHTML = ``;
// количество строк сущностей при текущем количестве колонок
const rowsCount = Math.ceil(entityNum / columns);
// смещение по строчкам за счет добавления строк пробелов между сущностями
// let offset = 0;
for (let i = 0; i < rowsCount; i++) {
const rows = [];
// создаем строчки для свойств сущности
for (let n = 0; n < entityPropsCount; n++) {
const row = table.insertRow(-1);
row.classList.add("row");
rows.push(row);
}
// добавляем сущности
for (let k = 0; k < columns && i * columns + k < entityNum; k++) {
createEntity({
rows,
gapColumns: k !== columns - 1,
indx: i * columns + k
});
}
// добавляем строку пробел между сущностями
if (i < rowsCount - 1) {
const row = table.insertRow(-1);
row.setAttribute("class", "row gap");
}
}
};
Каждая сущность занимает указанное количество строк в таблице, чтобы изменить это, нужно сделать правки в трех местах.
изменить переменную entityPropsCount
// количество свойств у сущности или подругому сколько строк будет занимать каждая сущность
const entityPropsCount = 3;
в функции генерации данных
const generateData = (entityNum) => {
const array = [];
for (let i = 0; i < entityNum; i++) {
array.push({
name:
"Name Entity " + i + ": " + randomWords({ min: 1, max: 20, join: " " }),
raiting: "Raiting: " + "*".repeat(randomInteger(1, 5)),
props:
"Props Entity " + i + ": " + randomWords({ min: 1, max: 8, join: " " })
});
}
return array;
};
изменить функцию добавления в HTML
const createEntity = ({ rows, gapColumns, indx }) => {
...
switch (i) {
case 0:
cell.innerText = data[indx].name;
break;
case 1:
cell.innerText = data[indx].raiting;
break;
default:
cell.innerText = data[indx].props;
}
...
};
Полный код смотри в примере