Как сделать прокрутку в таблице html
365 CASH — лучший и быстрый биткоин обменник! Более 10.000 отзывов.
Хостинг Fozzy — недорогой и быстрый хостинг на SSD дисках проверенный годами.
HTML-таблицы используются для логического структурирования контента. Они состоят из строк и ячеек которые можно объединять. В этой статье вы найдете подробное руководство по созданию HTML-таблиц с нуля. Материал рассчитан на новичков — школьников и студентов первых курсов. Рассмотрим как создаются таблицы в HTML.
Если вы не хотите изучать материал, а хотите просто создать таблицу, вы можете воспользоваться генератором html-таблиц.
Как сделать таблицу в HTML?
Таблицы создаются они с помощью тега <table> который имеет закрывающий тег </table>. Код самой простой таблицы из двух строк и столбцов выглядит следующим образом.
Результат выполнения кода будет следующим.
Ячейка 1 | Ячейка 2 |
Ячейка 3 | Ячейка 4 |
Стиль по умолчанию:
display: table;
border-collapse: separate;
box-sizing: border-box;
text-indent: initial;
white-space: normal;
line-height: normal;
font-weight: normal;
font-size: medium;
font-style: normal;
color: -internal-quirk-inherit;
text-align: start;
border-spacing: 2px;
border-color: grey;
font-variant: normal;
Границы таблицы
В стилях таблиц по умолчанию граница отсутствует. Добавить границы можно с помощью HTML-кода и с помощью CSS.
Устанавливает границу равную 1 пикселю, серого цвета. Равнозначным будет CSS-код:
Ячейка 1 | Ячейка 2 |
Ячейка 3 | Ячейка 4 |
Цвет границ задается с помощью bordercolor, а размер с помощью border.
Как убрать внутренние границы таблицы?
Вопрос очень интересный. Есть множество способов как так или иначе убрать внутренние границы в таблице. Но, я считаю, что самый простой способ это убрать все границы в таблице, «завернуть» таблицу в блок с границами. Это будет гораздо проще чем все остальные способы.
ФИО | Должность |
---|---|
Иванов Иван Иванович | Директор |
Петрова Любовь Николаевна | Главный бухгалтер |
Строка таблицы
Как вы уже догадались строка таблицы задается с помощью тега <tr> (от англ. table row — строка таблицы). Элемент <tr> является контейнером содержащим ячейки таблицы. Ячейки вне этого контейнера будут неправильно отображаться на экране.
Ячейки таблицы
Ячейки таблицы создаются с помощью тега <td> (от англ. able data — данные таблицы), который вкладывается в <tr>. Думаю со строками и ячейками все понятно.
Заголовок таблицы
Существует тег для создания заголовка таблицы и тег для создания заголовка столбца.
Для создания заголовка таблицы используется тег <caption>. Он идет сразу после тега <table> и задает название таблицы.
Для создания заголовка столбца используется тег <th> (от англ. table head — заголовок таблицы).
Все это немного запутано, правда? Давайте разбираться на примере.
ФИО | Должность |
---|---|
Иванов Иван Иванович | Директор |
Петрова Любовь Николаевна | Главный бухгалтер |
Таблица по центру
Часто возникает необходимость выровнять таблицу по центру документа. Тут есть два варианта (как и с границей).С помощью HTML-кода добавить атрибут align со значением center тега <table>.
Этот вариант применим если нам нужно выровнять по центру одну таблицу. Если же нам нужно выровнять по центру все таблицы, тогда лучше применить CSS-код.
Размер таблицы
Если вы не указываете размер таблицы, то он определяется количеством текста (или иного контента) внутри. проще говоря таблица растягивается по размеру контейнера в котором она находится.
При этом можно указать размеры таблицы в пикселях, где width — ширина таблицы, height — высота таблицы. Например, сделаем нашу таблицу шириной 400 пикселей.
ФИО | Должность |
---|---|
Иванов Иван Иванович | Директор |
Петрова Любовь Николаевна | Главный бухгалтер |
Более удобно задавать размер таблицы в процентах. В таком случае таблица становиться адаптивной. Изменим значение widthн равным 100%. Длинна будет адаптироваться в зависимости от контента. Результат будет следующим.
ФИО | Должность |
---|---|
Иванов Иван Иванович | Директор |
Петрова Любовь Николаевна | Главный бухгалтер |
Размер шрифта
Размер шрифта в таблице можно измять двумя способами. Наверное вы уже догадались какими.
С помощью HTML-кода можно изменять размер и начертание текста во всей таблице, но я рекомендую делать это с помощью CSS. А с помощью HTML менять шрифт в отдельных частях. Давайте изменим шрифт с помощью тега <span> в отдельной ячейке.
ФИО | Должность |
---|---|
Иванов Иван Иванович | Директор |
Петрова Любовь Николаевна | Главный бухгалтер |
Здесь мы указываем что весь текст в таблице должен быть размером 12px, а шрифт — ‘Times New Roman’.
Выравнивание текста
Выровнять текст в таблице можно несколькими способами. Рассмотрим выравнивание с помощью HTML.
Разбираемся на примере заголовком столбцов. Горизонтальное выравнивание осуществляется с помощью атрибута align. Выровняем заголовки столбцов по центру.
Теперь заголовки столбцов (ФИО и Должность) выровнены по центру.
ФИО | Должность |
---|---|
Иванов Иван Иванович | Директор |
Петрова Любовь Николаевна | Главный бухгалтер |
Аналогичное действие можно выполнить с помощью CSS-кода: text-align:center;
Вертикальное выравнивание осуществляется с помощью тега valign который имеет следующие свойства:
- top — по верхнему краю.
- middle — по середине.
- bottom — по нижнему краю.
- baseline — по базовой линии.
Отступы в таблице
Текст может располагаться довольно близко к границам таблицы, что затрудняет чтение. Для решения этой проблемы нужно увеличить отступы в таблице.
Отступы от границ ячеек. С помощью HTML задать отступы можно используя атрибут cellpadding тега <table>. Давайте увеличим отступ содержимого в ячейках нашей таблицы.
ФИО | Должность |
---|---|
Иванов Иван Иванович | Директор |
Петрова Любовь Николаевна | Главный бухгалтер |
Видите, текст уже не так прижимается к границе. С помощью CSS сделать это можно следующим образом: td
Объединение ячеек
Довольно важный момент в HTML-таблицах это объединение ячеек.
Объединение может быть горизонтальным.
Для горизонтального объединения ячеек используется атрибут colspan. Соответственно если у нас 4 ячейки, а мы объединяем две по горизонтали, то в первой строке у нас будет одна ячейка. Разберемся на примере.
ФИО | Должность |
---|---|
Руководящий состав: | |
Иванов Иван Иванович | Директор |
Петрова Любовь Николаевна | Главный бухгалтер |
Теперь представим ситуацию что на время отпуска главного бухгалтера директор занимает две должности. Для вертикального объединения ячеек будем использовать атрибут rowspan.
ФИО | Должность |
---|---|
Иванов Иван Иванович | Директор |
Главный бухгалтер |
Оформление HTML-таблиц
Под оформлением таблиц я имею ввиду следующие манипуляции:
- Изменить цвет фона.
- Изменить цвет ячейки (или строк).
- Картинки в таблице (в том числе с прозрачностью).
- Кнопки и элементы управления в таблице.
- Скролл (прокрутка) содержимого таблицы.
Изменение цвета фона таблицы
Изменить цвет фона таблицы с помощью HTML можно с помощью атрибута bgcolor. Давайте сделаем фон нашей таблицы не стандартным.
ФИО | Должность |
---|---|
Иванов Иван Иванович | Директор |
Главный бухгалтер |
Изменить цвет ячейки (или строк)
Цвет строки или ячейки изменятся с помощью того же атрибута. Для меня удобно менять цвет фона строки в больших таблицах – тогда визуально таблица воспринимается гораздо лучше.
ФИО | Должность |
---|---|
Иванов Иван Иванович | Директор |
Иванов Иван Иванович | Главный бухгалтер |
Картинки в ячейке
Давайте сделаем вот что. Добавим Справа фото сотрудников. Если фотографии сотрудника нет, то мы сделаем полупрозрачное фоновое изображение и напишем, что фото нет.
Итак, изображение вставляется стандартным способом с помощью тега <img>. Подробнее вы можете почитать тут.
А затем мы применим CSS-код для оформления ячейки в которой не будет фотографии.
ФИО | Должность | Фото |
---|---|---|
Иванов Иван Иванович | Директор | ![]() |
Иванов Иван Иванович | Главный бухгалтер | Нет фото |
Пояснения. В первом случае у нас в ячейку вставляется изображение и ячейка адаптируется под размер картинки.
Во втором случае картинка является фоновым изображением, поэтому я добавил height:200px; — что бы фоновое изображение отобразилось полностью. В этом случае размер ячейки (если не задавать его как это сделал я) зависит не от размера фонового изображения, а от содержимого ячейки (в данном случае — текста).
Кнопки и элементы управления
Кнопки и элементы управления вставляются в таблицу стандартными способами. Создадим справа еще один столбец и вставим туда текстовое поле с кнопкой.
ФИО | Должность | Фото | Написать |
---|---|---|---|
Иванов Иван Иванович | Директор | ![]() | Написать директору |
Иванов Иван Иванович | Главный бухгалтер | Нет фото | Написать бухгалтеру |
Скролл или прокрутка таблицы
Бывают ситуации когда таблицу необходимо сделать фиксированных размеров, но при этом должна быть возможность прокрутки таблицы. Разберемся как это сделать на примере.
ФИО | Должность | Фото | Написать |
---|---|---|---|
Иванов Иван Иванович | Директор | ![]() | Написать директору |
Иванов Иван Иванович | Главный бухгалтер | Нет фото | Написать бухгалтеру |
Думаю что если вы дочитали до конца, то вы сможете разобраться как это реализовано. На этом с HTML-таблицами все. Задавайте ваши вопросы в комментариях.
Генератор HTML-таблиц
Обучаю HTML, CSS, PHP. Создаю и продвигаю сайты, скрипты и программы. Занимаюсь информационной безопасностью. Рассмотрю различные виды сотрудничества.
11 комментариев к записи “ Таблицы HTML ”
Добрый день! Анатолий, скажите пожалуйста «как позиционировать таблицу к правой части страницы. Или вообще расположить две независимые таблицы — одну справа, а другую — слева.
Юрий здравствуйте. Тут есть несколько вариантов, все зависит от более конкретных целей.
Первый самый простой вариант – создаете таблицу, состоящую из двух ячеек. Убираете границы и по сути вы разделили экран на правую и левую часть. Далее в ячейках создаете вложенные таблицы.
Второй вариант. Что бы таблица была справа у нее должен быть ограниченная ширина. Создаете таблицу <table width="250" border="1" align="right"> . align="right" говорит о том, что таблица будет справа, а остальное содержимое, например текст, будет расположен слева (если нет других, препятствующих стилей).
Если же вы используете css- фреймворк то нужно отталкиваться от него.
Здравствуйте, Анатолий!
Есть таблица с каталогом. Хочу сделать отступы между строками.
То есть чтобы строки не сливались, а шли на расстоянии вертикальном друг от друга.
Как правильно сделать отступы между конструкциями 1 и 2?
Дмитрий, приветствую. Оперативность на данный момент не мой конек — почти всегда занят. Вот пример, дальше модернизируйте его под ваши нужды.
Таблицы! Таблицы? Таблицы…
В статье я покажу стандартную табличную разметку, какие у неё есть альтернативы. Дам пример собственной таблицы и разметки, а также опишу общие моменты её реализации.
Стандартная HTML4 таблица
Когда появилась необходимость в HTML разметке показывать таблицы — изобрели тег <table> .
Что же даёт нам таблица в браузере? Вот несколько основных «фич»:
Если мы не указали ширину таблицы/столбцов, то ширина таблицы подстраивается и растягивается, чтобы вместить содержимое любого из столбцов.
В данном случае вычисляется процентное соотношение каждого столбца к общей ширине и каждый столбец растягивается соответственно процентному соотношению.
В первом примере ширина всей таблицы (примерно) = 387px , колонки Company = 206px , колонки Contact = 115px .
В процентах Company = 206px/387px * 100% = 53% , Contact = 115px/387px * 100% = 30% .
Теперь когда содержимое таблицы растянулось, ширина всей таблицы (примерно на моем экране) = 1836px , колонки Company = 982px , колонки Contact = 551px .
В процентах Company = 982px/1836px * 100% = 53% , Contact = 551px/1836px * 100% = 30% .
- Если мы указали ширину таблицы и если указанная ширина меньше чем содержимое, тогда таблица сужается. Но сужается до минимально возможной ширины содержимого.
Можно «дожать» таблицу указав ей CSS свойство table-layout: fixed . Описание к свойству.
Так мы ломаем автоподстройку ширины таблицы и теперь таблица слушается заданных ширин для каждого столбца (или всей таблицы), но зато таблица точно вписывается в указанную ширину.
Если мы не указали ширину столбцов, тогда при «сломанной» таблице, ширина каждого столбца = вся ширина / количество столбцов .
Схлопывание (наложение) границ ячеек/столбцов border-collapse: collapse , если мы указали границы для ячеек. Т.е. в местах соприкосновения ячеек, не будет двойных граничных линий.
Использование стандартной таблицы
Во всех вышеприведенный примерах в разметке таблицы я использовал сокращенную разметку:
Однако можно использовать «каноничную» разметку:
Если нужна таблица без шапки и в то же время нам необходимо контроллировать ширину столбцов:
Чаще всего нам в разметке необходимо получить следующее. У нас есть некий контейнер с заданной шириной или с заданной максимальной шириной. Внутри него мы хотим вписать таблицу.
Если ширина таблицы больше чем контейнер, тогда необходимо показывать скролл для контейнера. Если ширина таблицы меньше чем контейнер, тогда необходимо расширять таблицу до ширины контейнера.
Но ни в коем случае мы не хотим, чтобы таблица сделала наш контейнер шире чем мы задали.
По этой ссылке можно уведеть контейнер с таблицей в действии. Если мы будем сужать контейнер, то в тот момент, когда таблица уже больше не сможет сужаться — появиться скролл.
Подстройка таблицы
Задание ширины таблицы и столбцов
Первая дилемма с которой сталкиваются фронт-энд разработчики — это задавать или не задавать ширину столбцов.
Если не задавать, тогда ширина каждого столбца будет вычисляться в зависимости от содержимого.
Исходя из логики, можно понять, что в этом случае браузеру нужно два прохода. На первом он просто отображает все в таблице, подсчитывает ширину столбцов (мин, макс). На втором подстраивает ширину столбцов в зависимости от ширины таблицы.
Со временем вам скажут что таблица выглядит некрасиво, т.к. один из столбцов слишком широкий и
И самая распространенная «фича»:
- это сокращение текста в ячейке с помощью .
Т.е. если текст в ячейке вылазит за ширину колонки, то его необходимо сокращать и в конце добавлять . .
Первое разочарование, что если не задавать ширину столбцов, то сокращение не работает. В этом есть своя логика, т.к. на первом проходе браузер высчитывает мин/макс ширину колонки без сокращения, а тут мы пытаемся сократить текст. Необходимо либо все пересчитать повторно, либо игнорировать сокращение.
Сокращение реализуется просто, необходимо указать CSS свойства для ячейки:
И соответственно задать ширину колонки. По этой ссылке можно увидеть, что все настроено, но сокращение не работает.
В спецификации есть заметка, немного объясняющая, почему сокращение не работает:
Опять же сужаться таблица будет до минимальной ширины содержимого. Но если применить свойство table-layout: fixed то таблица начнёт «слушаться» и сокращение заработает. Но автоподстройка ширины столбцов уже не работает.
Задание прокрутки таблицы
Вышеприведенный пример будет работать со скроллом и пользоваться этим можно. Однако возникает следующее требование:
Вторая дилемма с которой сталкиваются фронт-энд разработчики:
- задание прокрутки/скролла в таблице
В спецификации таблицы есть прямое указание, что тело таблицы может быть с шапкой и подвалом. Т.е. шапка и подвал всегда видимы.
А есть и указание о том, что тело таблицы можно скроллить, а шапка и подвал будут оставаться на месте:
А по факту браузеры этого не делают и скролл для таблицы необходимо придумывать/настраивать вручную.
Есть много способов это сделать, но все они сводяться к тому, что:
- мы не создаем дополнительную разметку и пытаемся прикрутить скролл к тому что есть (к телу таблицы, или оборачиваем в контейнер, а значение ячеек в шапке делаем абсолютно позиционированным)
Можно задать ограниченную высоту телу таблицы. Следующий пример показывает, что можно попробовать задать высоту тела таблицы.
В результате мы ломаем табличное отображение тела таблицы CSS свойством display: block , и при этом необходимо синхронизировать прокрутку шапки с телом таблицы.
- мы создаём дополнительную разметку (составные таблицы) и тогда при прокрутке оригинала мы синхронизируем дополнительную разметку
Этот вариант, где все предлагают/строят решения.
Примеры составных таблиц
Если нам необходима прокрутка тела таблицы, то без составных разметок не обойтись. Все примеры составных таблиц используют свои пользовательские разметки.
Одна из самых известных таблиц Data Tables использует следующую разметку:
Я намеренно сокращаю разметку, чтобы можно было составить общую картину, как выглядит разметка.
Мы видим в разметке две таблицы, хотя для пользователя это «видится» как одна.
Следующий пример React Bootstrap Table, если посмотреть в разметку, использует тоже две таблицы:
Верхняя таблица отображает шапку, нижняя — тело. Хотя для пользователя кажется как будто бы это одна таблица.
Опять же пример использует синхронизацию прокрутки, если прокрутить тело таблицы, то произойдет синхронизация шапки.
А как же так получается, что тело таблицы (одна таблица) и шапка (другая таблица) подстраиваются под ширину контейнера и они никак не разъезжаются по ширине и совпадают друг с другом?
Тут кто как умеет так и синхронизирует, например, вот функция синхронизации ширины из вышеприведенной библиотеки:
Возникает вполне логичный вопрос, а зачем тогда вообще использовать тег <table> , если используется только автоподстройка ширины из стандартной таблицы?
И тут мы окажемся не первыми, некоторые вообще не используют табличную разметку. Например Fixed Data Table или React Table.
Разметка в примерах примерно такая:
Отсюда название fixed table , т.е. для такой разметки мы должны заранее указать ширину всех столбцов (ширину таблицы, иногда и высоту строки). Хотя если мы хотим сокращение текста, все равно необходимо задавать ширину столбцов, даже в обычной таблице.
Следующая таблица Reactabular использует интересный подход в синхронизации.
Автор пошел дальше и сделал прокручиваемым не только тело, но и шапку таблицы. В браузерах которые показывают ползунок скролла — выглядит ужасно, зато в touch браузерах очень классно и функционально.
Если мы скроллим тело таблицы, то происходит синхронизация шапки, а если мы скроллим шапку, то происходит синхронизация тела.
А как же сделать автоподстройку ширины колонки в составной таблице спросите вы? Вот интересный способ использовать дополнительный проход браузера. Например в этой таблице ag Grid можно автоматически рассчитать подходящую ширину столбца.
Реализация собственной таблицы
Получается, что составная таблица требует дополнительной синхронизации между частями, чтобы для пользователя все вместе казалось как одна таблица.
Все составные таблицы (и моя) страдают недостатком, у них нет стандарта как их кастомизировать/настраивать (и это логично, т.к. при реализации отказались от HTML4 таблицы).
Когда ты начинаешь изучать одну составную таблицу, потом начинаешь тратить время на её кастомизацию.
Затем для другого проекта изучаешь другую таблицу (например при переходе с Angular1 на React, или с jQuery на Vue), а кастомизация совсем другая.
Возникает логичный вопрос, а стоит ли потраченное время того? Стоит ли учить снова и снова связку фреймворк-таблица?
Может легче освоить для себя базовые моменты составной таблицы и тогда вы сможете делать свою таблицу на любом фреймворке (Angular/React/Vue/будущее. )? Например, на свою таблицу вы будете тратить 2 дня на старт, потом в течении 30 мин кастомизировать.
А можно подключить готовую фреймворк-таблицу за 30 мин и потом кастомизировать каждую фичу за 1 день.
К премеру, я покажу как сделать свою составную таблицу на React.
- составной, синхронизировать шапку в зависимости от тела таблицы
- подстраивать свою ширину если она меньше ширины контейнера
Дальше будет объяснение только некоторых аспектов разработки, можете сразу посмотреть результат.
Разметка
Для разметки будем использовать div элементы. Если использовать display: inline-block для ячеек, тогда будет следующая разметка:
Но есть одна проблема — браузер (не все браузеры) интерпретирует пустые места между ячейками как текстовые ноды.
Есть отличная статья, как с этим бороться.
И если мы используем шаблонизатор (EJS, JSX, Angular, Vue), то это легко решить:
Однако уже 2017 год, flexbox давно поддерживается, я делал на нем проекты еще в 2014 для IE11.
А сегодня можно вообще не стесняться его. Это упростит нам задачу, можно будет делать столько пустых нод, сколько нужно:
Общие моменты использования
Таблица должна встраиваться в Redux архитектуру, примеры таких таблиц предалагают подключать свои reducers .
Мне этот подход не нравится. По моему мнению, разработчик должен контроллировать процесс сортировки, фильтрации. Это требует дополнительного кода.
Вместо такого «черного ящика», который потом сложно кастомизировать:
разработчик должен будет писать:
Разработчик должен сам прописывать шаги: вычислить описание колонок, отфильтровать, отсортировать.
Все функции/конструкторы getColumnDescriptions, filterBy, sortBy, TableHeader, TableBody, TableColumn будут импортироваться из моей таблицы.
В качестве данных будет использоваться массив объектов:
Мне понравился подход создания описания колонок в jsx в качестве элементов.
Будем использовать ту же идею, однако, чтобы сделать независимыми шапку и тело таблицы, будем вычислять описание один раз и передавать его и в шапку и в тело:
В функции getTableColumns мы создаем описание колонок.
Все обязательные свойства я могу описать через propTypes , но после того как их вынесли в отдельную библиотеку — это решение кажется сомнительным.
Обязательно указываем row — число, которое показывает индекс строки в шапке (если шапка будет группироваться).
Параметр dataField , определяет какой ключ из объекта использовать для получения значения.
Ширина width тоже обязательный параметр, может задаватся как числом или как массивом ключей от которых зависит ширина.
В примере верхняя строка в таблице row= зависит от ширины двух колонок [«Company», «Cost»] .
Элемент TableColumn «фейковый», он никогда не будет отображаться, а вот его содержимое this.props.children — отображается в ячейке шапки.
Разработка
На основе описаний колонок сделаем функцию, которая будет разбивать описания по рядам и по ключам, а также будет сортировать описания по рядам в результирующем массиве:
Теперь обработанные описания передаём в шапку и в тело для отображения ячеек. Шапка будет строить ячейки так:
Тело таблицы будет строить ячейки тоже на основе обработанных описаний колонок:
Тело таблицы использует описания у которых есть свойство dataField , поэтому описания фильтруются используя функцию getCellDescriptions .
Тело таблицы будет слушать события изменения размеров экрана, а также прокрутки самого тела таблицы:
Подстройка ширины таблицы происходит следующим образом.
После отображения берётся ширина контейнера, сравнивается с шириной всех ячеек, если ширина контейнера больше, увеличивается ширина всех ячеек.
Для этого разработчик должен хранить состояние коэффициента ширины (который будет меняться).
Следующие функции реализованы в таблице, однако разработчик может использовать свои. Чтобы использовать уже реализованные, необходимо их импортировать и прилинковать к текущему компоненту:
Функция подстройки ширины:
Функция синхронизация шапки:
Ключевая особенность таблицы для redux — это то, что она не имеет своего внутреннего состояния (она должна иметь состояние, но только в том месте, где укажет разработчик).
И подстройка ширины adjustBody и синхронизация скролла adjustScroll — это функции которые изменяют состояние у прилинкованного компонента.
Внутрь TableColumn можно вставлять любую jsx разметку. Зачастую используются такие варианты: текст, кнопка сортировки и кнопка фильтрации.
Для массива активных сортировок/фильтраций разработчик должен создать состояние и передавать его в таблицу.
Передаем в таблицу массив активных сортировок/фильтраций:
Компонент сортировки SortButton и компонент фильтрации MultiselectDropdown при изменении «выбрасывают» новые активные фильтры/сортировки, которые разработчик должен заменить в состоянии. Массивы activeSorts и activeFilters как раз и предполагают, что возможна множественная сортировка и множественная фильтрация по каждой колонке.
К сожалению, формат статьи не позволяет описать всех тонкостей, поэтому предлагаю сразу посмотреть результат.
Итого разработчику в таблице необходимо:
- автоподстройка ширины таблицы под ширину контейнера
- прокрутка тела таблицы и синхронизация шапки
- сортировка таблицы (возможна множественная сортировка)
- фильтрация таблицы (возможна множественная фильтрация)
Все это я реализовал в примере. Надеюсь теперь, при переходе на новый фреймворк, у вас как минимум появился выбор — брать готовую или сделать свою таблицу.
Как сделать прокрутку в таблице html
- Open with Desktop
- View raw
- Copy raw contents Copy raw contents
Copy raw contents
Copy raw contents
В статье я покажу стандартную табличную разметку, какие у неё есть альтернативы. Дам пример собственной таблицы и разметки, а также опишу общие моменты её реализации.
Стандартная HTML4 таблица
Когда появилась необходимость в HTML разметке показывать таблицы — изобрели тег <table> . Что же даёт нам таблица в браузере? Вот несколько основных «фич»:
Если мы не указали ширину таблицы/столбцов, то ширина таблицы подстраивается и растягивается, чтобы вместить содержимое любого из столбцов.
Если мы указали ширину таблицы, и если указанная ширина больше чем содержимое, тогда содержимое растягивается. Самое интересное как растягивается содержимое.
В данном случае вычисляется процентное соотношение каждого столбца к общей ширине и каждый столбец растягивается соответственно процентному соотношению.
В первом примере ширина всей таблицы (примерно) = 387px , колонки Company = 206px , колонки Contact = 115px .
В процентах Company = 206px/387px * 100% = 53% , Contact = 115px/387px * 100% = 30% .
Теперь когда содержимое таблицы растянулось, ширина всей таблицы (примерно на моем экране) = 1836px , колонки Company = 982px , колонки Contact = 551px .
В процентах Company = 982px/1836px * 100% = 53% , Contact = 551px/1836px * 100% = 30% .
Если мы указали ширину таблицы и если указанная ширина меньше чем содержимое, тогда таблица сужается. Но сужается до минимально возможной ширины содержимого.
Можно «дожать» таблицу указав ей CSS свойство table-layout: fixed . Описание к свойству.
Так мы ломаем автоподстройку ширины таблицы и теперь таблица слушается заданных ширин для каждого столбца (или всей таблицы), но зато таблица точно вписывается в указанную ширину.
Если мы не указали ширину столбцов, тогда при «сломанной» таблице, ширина каждого столбца = вся ширина / количество столбцов .
Схлопывание (наложение) границ ячеек/столбцов border-collapse: collapse , если мы указали границы для ячеек. Т.е. в местах соприкосновения ячеек, не будет двойных граничных линий.
Группировка шапки. Реализуется атрибутами colspan , rowspan .
Использование стандартной таблицы
Во всех вышеприведенный примерах в разметке таблицы я использовал сокращенную разметку:
Однако можно использовать «каноничную» разметку:
Если нужна таблица без шапки и в то же время нам необходимо контроллировать ширину столбцов:
Чаще всего нам в разметке необходимо получить следующее.
У нас есть некий контейнер с заданной шириной или с заданной максимальной шириной. Внутри него мы хотим вписать таблицу.
Если ширина таблицы больше чем контейнер, тогда необходимо показывать скролл для контейнера. Если ширина таблицы меньше чем контейнер, тогда необходимо расширять таблицу до ширины контейнера.
Но ни в коем случае мы не хотим, чтобы таблица сделала наш контейнер шире чем мы задали.
По этой ссылке можно уведеть контейнер с таблицей в действии. Если мы будем сужать контейнер, то в тот момент, когда таблица уже больше не сможет сужаться — появиться скролл.
Задание ширины таблицы и столбцов
Первая дилемма с которой сталкиваются фронт-энд разработчики — это задавать или не задавать ширину столбцов.
Если не задавать, тогда ширина каждого столбца будет вычисляться в зависимости от содержимого.
Исходя из логики, можно понять, что в этом случае браузеру нужно два прохода. На первом он просто отображает все в таблице, подсчитывает ширину столбцов (мин, макс). На втором подстраивает ширину столбцов в зависимости от ширины таблицы.
Со временем вам скажут что таблица выглядит некрасиво, т.к. один из столбцов слишком широкий и «вот в этом столбце нам надо показать больше текста чем в этом, а у нас наоборот» .
И самая распространенная «фича»:
- это сокращение текста в ячейке с помощью .
Т.е. если текст в ячейке вылазит за ширину колонки, то его необходимо сокращать и в конце добавлять . .
Первое разочарование, что если не задавать ширину столбцов, то сокращение не работает.
В этом есть своя логика, т.к. на первом проходе браузер высчитывает мин/макс ширину колонки без сокращения, а тут мы пытаемся сократить текст. Необходимо либо все пересчитать повторно, либо игнорировать сокращение.
Сокращение реализуется просто, необходимо указать CSS свойства для ячейки:
И соответственно задать ширину колонки. По этой ссылке можно увидеть, что все настроено, но сокращение не работает.
В спецификации есть заметка, немного объясняющая, почему сокращение не работает:
If column widths prove to be too narrow for the contents of a particular table cell, user agents may choose to reflow the table .
Опять же сужаться таблица будет до минимальной ширины содержимого. Но если применить свойство table-layout: fixed то таблица начнёт «слушаться» и сокращение заработает.
Но автоподстройка ширины столбцов уже не работает.
Задание прокрутки таблицы
Вышеприведенный пример будет работать со скроллом и пользоваться этим можно.
Однако возникает следующее требование «здесь нам надо сделать, чтобы шапка таблицы оставалась на месте, а тело прокручивалось» .
Вторая дилемма с которой сталкиваются фронт-энд разработчики:
- задание прокрутки/скролла в таблице
В спецификации таблицы есть прямое указание, что тело таблицы может быть с шапкой и подвалом. Т.е. шапка и подвал всегда видимы.
User agents may exploit the head/body/foot division to support scrolling of body sections independently of the head and foot sections. When long tables are printed, the head and foot information may be repeated on each page that contains table data
А есть и указание о том, что тело таблицы можно скроллить, а шапка и подвал будут оставаться на месте:
Table rows may be grouped into a table head, table foot, and one or more table body sections, using the THEAD, TFOOT and TBODY elements, respectively. This division enables user agents to support scrolling of table bodies independently of the table head and foot
А по факту браузеры этого не делают и скролл для таблицы необходимо придумывать/настраивать вручную.
Есть много способов это сделать, но все они сводяться к тому, что:
- мы не создаем дополнительную разметку и пытаемся прикрутить скролл к тому что есть (к телу таблицы, или оборачиваем в контейнер, а значение ячеек в шапке делаем абсолютно позиционированным)
Можно задать ограниченную высоту телу таблицы. Следующий пример показывает, что можно попробовать задать высоту тела таблицы.
В результате мы ломаем табличное отображение тела таблицы CSS свойством display: block , и при этом необходимо синхронизировать прокрутку шапки с телом таблицы.
- мы создаём дополнительную разметку (составные таблицы) и тогда при прокрутке оригинала мы синхронизируем дополнительную разметку
Этот вариант, где все предлагают/строят решения.
Примеры составных таблиц
Если нам необходима прокрутка тела таблицы, то без составных разметок не обойтись.
Все примеры составных таблиц используют свои пользовательские разметки.
Одна из самых известных таблиц Data Tables использует следующую разметку:
Я намеренно сокращаю разметку, чтобы можно было составить общую картину, как выглядит разметка.
Мы видим в разметке две таблицы, хотя для пользователя это «видится» как одна.
Следующий пример React Bootstrap Table, если посмотреть в разметку, использует тоже две таблицы:
Верхняя таблица отображает шапку, нижняя — тело. Хотя для пользователя кажется как будто бы это одна таблица.
Опять же пример использует синхронизацию прокрутки, если прокрутить тело таблицы, то произойдет синхронизация шапки.
А как же так получается, что тело таблицы (одна таблица) и шапка (другая таблица) подстраиваются под ширину контейнера и они никак не разъезжаются по ширине и совпадают друг с другом?
Тут кто как умеет так и синхронизирует, например, вот функция синхронизации ширины из вышеприведенной библиотеки:
Возникает вполне логичный вопрос, а зачем тогда вообще использовать тег <table> , если используется только автоподстройка ширины из стандартной таблицы?
И тут мы окажемся не первыми, некоторые вообще не используют табличную разметку.
Например Fixed Data Table или React Table.
Разметка в примерах примерно такая:
Отсюда название fixed table , т.е. для такой разметки мы должны заранее указать ширину всех столбцов (ширину таблицы, иногда и высоту строки).
Хотя если мы хотим сокращение текста, все равно необходимо задавать ширину столбцов, даже в обычной таблице.
Следующая таблица Reactabular использует интересный подход в синхронизации.
Автор пошел дальше и сделал прокручиваемым не только тело, но и шапку таблицы. В браузерах которые показывают ползунок скролла — выглядит ужасно, зато в touch браузерах очень классно и функционально.
Если мы скроллим тело таблицы, то происходит синхронизация шапки, а если мы скроллим шапку, то происходит синхронизация тела.
А как же сделать автоподстройку ширины колонки в составной таблице спросите вы?
Вот интересный способ использовать дополнительный проход браузера.
Например в этой таблице ag Grid можно автоматически рассчитать подходящую ширину столбца.
В коде есть функция автоподстройки ширины колонки:
Реализация собственной таблицы
Получается, что составная таблица требует дополнительной синхронизации между частями, чтобы для пользователя все вместе казалось как одна таблица.
Все составные таблицы (и моя) страдают недостатком, у них нет стандарта как их кастомизировать/настраивать (и это логично, т.к. при реализации отказались от HTML4 таблицы).
Когда ты начинаешь изучать одну составную таблицу, потом начинаешь тратить время на её кастомизацию.
Затем для другого проекта изучаешь другую таблицу (например при переходе с Angular1 на React, или с jQuery на Vue), а кастомизация совсем другая.
Возникает логичный вопрос, а стоит ли потраченное время того? Стоит ли учить снова и снова связку фреймворк-таблица?
Может легче освоить для себя базовые моменты составной таблицы и тогда вы сможете делать свою таблицу на любом фреймворке (Angular/React/Vue/будущее. )?
Например, на свою таблицу вы будете тратить 2 дня на старт, потом в течении 30 мин кастомизировать.
А можно подключить готовую фреймворк-таблицу за 30 мин и потом кастомизировать каждую фичу за 1 день.
К премеру, я покажу как сделать свою составную таблицу на React.
Таблица будет:
- составной, синхронизировать шапку в зависимости от тела таблицы
- подстраивать свою ширину если она меньше ширины контейнера
Дальше будет объяснение только некоторых аспектов разработки, можете сразу посмотреть результат.
Для разметки будем использовать div элементы. Если использовать display: inline-block для ячеек, тогда будет следующая разметка:
Но есть одна проблема — браузер (не все браузеры) интерпретирует пустые места между ячейками как текстовые ноды.
Есть отличная статья, как с этим бороться.
И если мы используем шаблонизатор (EJS, JSX, Angular, Vue), то это легко решить:
Однако уже 2017 год, flexbox давно поддерживается, я делал на нем проекты еще в 2014 для IE11.
А сегодня можно вообще не стесняться его. Это упростит нам задачу, можно будет делать столько пустых нод, сколько нужно:
Общие моменты использования
Таблица должна встраиваться в Redux архитектуру, примеры таких таблиц предалагают подключать свои reducers .
Мне этот подход не нравится. По моему мнению, разработчик должен контроллировать процесс сортировки, фильтрации. Это требует дополнительного кода.
Вместо такого «черного ящика», который потом сложно кастомизировать:
разработчик должен будет писать:
Разработчик должен сам прописывать шаги: вычислить описание колонок, отфильтровать, отсортировать.
Все функции/конструкторы getColumnDescriptions, filterBy, sortBy, TableHeader, TableBody, TableColumn будут импортироваться из моей таблицы.
В качестве данных будет использоваться массив объектов:
Мне понравился подход создания описания колонок в jsx в качестве элементов.
Будем использовать ту же идею, однако, чтобы сделать независимыми шапку и тело таблицы, будем вычислять описание один раз и передавать его и в шапку и в тело:
В функции getTableColumns мы создаем описание колонок.
Все обязательные свойства я могу описать через propTypes , но после того как их вынесли в отдельную библиотеку — это решение кажется сомнительным.
Обязательно указываем row — число, которое показывает индекс строки в шапке (если шапка будет группироваться).
Параметр dataField , определяет какой ключ из объекта использовать для получения значения.
Ширина width тоже обязательный параметр, может задаватся как числом или как массивом ключей от которых зависит ширина.
В примере верхняя строка в таблице row= зависит от ширины двух колонок [«Company», «Cost»] .
Элемент TableColumn «фейковый», он никогда не будет отображаться, а вот его содержимое this.props.children — отображается в ячейке шапки.
На основе описаний колонок сделаем функцию, которая будет разбивать описания по рядам и по ключам, а также будет сортировать описания по рядам в результирующем массиве:
Теперь обработанные описания передаём в шапку и в тело для отображения ячеек.
Шапка будет строить ячейки так:
Тело таблицы будет строить ячейки тоже на основе обработанных описаний колонок:
Тело таблицы использует описания у которых есть свойство dataField , поэтому описания фильтруются используя функцию getCellDescriptions .
Тело таблицы будет слушать события изменения размеров экрана, а также прокрутки самого тела таблицы:
Подстройка ширины таблицы происходит следующим образом.
После отображения берётся ширина контейнера, сравнивается с шириной всех ячеек, если ширина контейнера больше, увеличивается ширина всех ячеек.
Для этого разработчик должен хранить состояние коэффициента ширины (который будет меняться).
Следующие функции реализованы в таблице, однако разработчик может использовать свои. Чтобы использовать уже реализованные, необходимо их импортировать и прилинковать к текущему компоненту:
Функция подстройки ширины:
Функция синхронизация шапки:
Ключевая особенность таблицы для redux — это то, что она не имеет своего внутреннего состояния (она должна иметь состояние, но только в том месте, где укажет разработчик).
И подстройка ширины adjustBody и синхронизация скролла adjustScroll — это функции которые изменяют состояние у прилинкованного компонента.
Внутрь TableColumn можно вставлять любую jsx разметку. Зачастую используются такие варианты: текст, кнопка сортировки и кнопка фильтрации. Для массива активных сортировок/фильтраций разработчик должен создать состояние и передавать его в таблицу.
Передаем в таблицу массив активных сортировок/фильтраций:
Компонент сортировки SortButton и компонент фильтрации MultiselectDropdown при изменении «выбрасывают» новые активные фильтры/сортировки, которые разработчик должен заменить в состоянии.
Массивы activeSorts и activeFilters как раз и предполагают, что возможна множественная сортировка и множественная фильтрация по каждой колонке.
К сожалению, формат статьи не позволяет описать всех тонкостей, поэтому предлагаю сразу посмотреть результат.
Итого разработчику в таблице необходимо:
- автоподстройка ширины таблицы под ширину контейнера
- прокрутка тела таблицы и синхронизация шапки
- сортировка таблицы (возможна множественная сортировка)
- фильтрация таблицы (возможна множественная фильтрация)
Все это я реализовал в примере. Надеюсь теперь, при переходе на новый фреймворк, у вас как минимум появился выбор — брать готовую или сделать свою таблицу.
Add a horizontal scrollbar to an HTML table
Is there a way to add a horizontal scrollbar to an HTML table? I actually need it to be scrollable both vertically and horizontally depending on how the table grows but I cannot get either scrollbar to appear.
19 Answers 19
First, make a display: block of your table
then, set overflow-x: to auto .
Nice and clean. No superfluous formatting.
If an issue is taken about cells not filling the entire table, append the following additional CSS code:
Did you try CSS overflow property?
UPDATE
As other users are pointing out, this is not enough to add the scrollbars.
So please, see and upvote comments and answers below.
Wrap the table in a DIV, set with the following style:
This is an improvement of Serge Stroobandt’s answer and works perfectly. It solves the issue of the table not filling the whole page width if it has less columns.
Use the CSS attribute "overflow" for this.
Edit: @WickyNilliams has noted that setting display: block on a table body will strip the table of semantics and thus is not a good solution due to accessibility issues.
I had good success with the solution proposed by @Serge Stroobandt, but I encountered the problem @Shevy had with the cells then not filling the full width of the table. I was able to fix this by adding some styles to the tbody .
This worked for me in Firefox, Chrome, and Safari on Mac.
I couldn’t get any of the above solutions to work. However, I found a hack:
I was running into the same issue. I discovered the following solution, which has only been tested in Chrome v31:
Insert the table inside a div, so the table will take full length
I figured out this answer based on previous solution and it’s comment and added some adjustments of my own. This works for me on the responsive table.
The ‘more than 100% width’ on the table really made it work for me.
add tag table to div element with style="overflow-x:auto"
This is what worked for me
table can have any width . I usually use 100% or max-content for the table.
I tried all the above solutions but had some issues with them.
If we add display: ‘block’ to the table, the cells do not occupy the full width. If we add it to the table wrapper, your custom table header like search, filter etc will also scroll which will look bad.
I was able to achieve the expected behaviour by adding overflow-x: auto to the body wrapper of the table.
Cells take full width even with less columns and a scroll bar appears automatically as needed.
Like already stated, using display:block; on table is bad. I tried most of the answers in this thread, none worked as I wanted. If your HTML is structured like this:
And you want the parent div to be horizontally scrollable, you can try the following: