Оформляем таблицы с помощью CSS: как работать с полями, границами и свойством z-index
Структура таблицы
Эталонный вариант таблицы
Иллюстрация выше показывает, как можно оформить таблицу с помощью CSS. Первый ряд выступает в качестве заголовка, а разделы таблицы обозначены подзаголовками.
Выше представлена структура таблицы в HTML. В
содержится главное название. В таблице есть несколько секций , каждая из которых имеет собственный подзаголовок.Что не так с margin и как оформить отступы для элементов таблицы
Как видно на иллюстрации в начале статьи, между главным заголовком и секцией
, а также между остальными секциями , есть отступы. Можно подумать, что они определяются свойствами margin-top для , но это не так.Свойство border
Самый простой способ получить отступы без использования margin — применить к
border-top: 1 em .Все секции
, у которых должны быть отступы, имеют класс .section . Чтобы свойство border-top сработало, необходимо применить к таблице border-collapse: collapse .Псевдоэлементы ::before и ::after
Псевдоэлементы ::before и ::after — ещё один способ добавить отступы для элементов таблицы.
В данном случае создаётся пустой ряд, который обеспечивает визуальный отступ между секциями
.Вы можете использовать для оформления отступов как псевдоэлементы, так и свойство border .
Как применить к элементам таблицы border-radius
Задача: добавить к секциям
границы и применить к ним border-radius . Напрямую это сделать невозможно — border и border-radius не работают с .Пример выше показывает, как с помощью box-shadow добиться практически такого же результата, как с помощью border при работе с нетабличными элементами.
Как оформлять ячейки таблицы
Внешний вид текущей таблицы (см. иллюстрацию ниже) отличается от эталонного варианта, который представлен в начале статьи.
Нужны марджины, а не паддинги
После добавления границ можно заметить, что полученные отступы работают не как «марджины», а как «паддинги». Это можно изменить, если работать с границами ячеек и использовать селекторы :first-child и :last-child .
В примере выше стили применяются к соответствующим элементам th и td ячеек таблицы. К ячейкам, которые находятся в углах таблицы, применяется border-radius . Все ячейки, которые находятся по краям таблицы, имеют границы. Селекторы :first-child и :last-child позволяют обращаться к нужным ячейкам.
Как применять z-index к элементам таблицы
Проблемы с box-shadow
На первой иллюстрации в статье видно, что свойство box-shadow применяется к подзаголовкам, поэтому тени попадают на следующие ниже ряды таблицы. Если попробовать прямо применить box-shadow к соответствующему элементу, тень в рядах не появится.
В обычной ситуации можно использовать для решения таких проблем z-index . Но с таблицами всё сложнее: z-index не работает с
. Проблема решается, если вы знаете, как работать с контекстом наложения. Если применить к элементу position: relative и z-index , появляется новый контекст наложения. Также эту задачу можно решить с помощью transform: translate (0, 0) .Заключение
Чтобы сделать таблицы визуально привлекательными, приходится использовать неочевидные трюки CSS. Но этим и хороши CSS — с их помощью можно решить практически любую задачу по оформлению веб-элементов.
При работе с таблицами возникает соблазн переопределить свойство display . Но это приведёт к дополнительным сложностям: придётся вручную определять ширину ячеек, чтобы таблица нормально отображалась. Поэтому удобнее пользоваться предложенными выше трюками, которые позволяют оформлять таблицы элегантно и без лишнего кода.
Адаптированный перевод статьи Styling HTML Tables: How to Apply Margins, Borders and z-index on Table Elements by Markus Oberlehner. Мнение автора оригинальной публикации может не совпадать с мнением администрации «Хекслета».
Источник
Таблицы! Таблицы? Таблицы…
В статье я покажу стандартную табличную разметку, какие у неё есть альтернативы. Дам пример собственной таблицы и разметки, а также опишу общие моменты её реализации.
Стандартная HTML4 таблица
Если мы не указали ширину таблицы/столбцов, то ширина таблицы подстраивается и растягивается, чтобы вместить содержимое любого из столбцов.
В данном случае вычисляется процентное соотношение каждого столбца к общей ширине и каждый столбец растягивается соответственно процентному соотношению.
В первом примере ширина всей таблицы (примерно) = 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, если посмотреть в разметку, использует тоже две таблицы:
Верхняя таблица отображает шапку, нижняя — тело. Хотя для пользователя кажется как будто бы это одна таблица.
Опять же пример использует синхронизацию прокрутки, если прокрутить тело таблицы, то произойдет синхронизация шапки.
А как же так получается, что тело таблицы (одна таблица) и шапка (другая таблица) подстраиваются под ширину контейнера и они никак не разъезжаются по ширине и совпадают друг с другом?
Тут кто как умеет так и синхронизирует, например, вот функция синхронизации ширины из вышеприведенной библиотеки:
И тут мы окажемся не первыми, некоторые вообще не используют табличную разметку. Например 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= <0>зависит от ширины двух колонок [«Company», «Cost»] .
Элемент TableColumn «фейковый», он никогда не будет отображаться, а вот его содержимое this.props.children — отображается в ячейке шапки.
Разработка
На основе описаний колонок сделаем функцию, которая будет разбивать описания по рядам и по ключам, а также будет сортировать описания по рядам в результирующем массиве:
Теперь обработанные описания передаём в шапку и в тело для отображения ячеек. Шапка будет строить ячейки так:
Тело таблицы будет строить ячейки тоже на основе обработанных описаний колонок:
Тело таблицы использует описания у которых есть свойство dataField , поэтому описания фильтруются используя функцию getCellDescriptions .
Тело таблицы будет слушать события изменения размеров экрана, а также прокрутки самого тела таблицы:
Подстройка ширины таблицы происходит следующим образом.
После отображения берётся ширина контейнера, сравнивается с шириной всех ячеек, если ширина контейнера больше, увеличивается ширина всех ячеек.
Для этого разработчик должен хранить состояние коэффициента ширины (который будет меняться).
Следующие функции реализованы в таблице, однако разработчик может использовать свои. Чтобы использовать уже реализованные, необходимо их импортировать и прилинковать к текущему компоненту:
Функция подстройки ширины:
Функция синхронизация шапки:
Ключевая особенность таблицы для redux — это то, что она не имеет своего внутреннего состояния (она должна иметь состояние, но только в том месте, где укажет разработчик).
И подстройка ширины adjustBody и синхронизация скролла adjustScroll — это функции которые изменяют состояние у прилинкованного компонента.
Внутрь TableColumn можно вставлять любую jsx разметку. Зачастую используются такие варианты: текст, кнопка сортировки и кнопка фильтрации.
Для массива активных сортировок/фильтраций разработчик должен создать состояние и передавать его в таблицу.
Передаем в таблицу массив активных сортировок/фильтраций:
Компонент сортировки SortButton и компонент фильтрации MultiselectDropdown при изменении «выбрасывают» новые активные фильтры/сортировки, которые разработчик должен заменить в состоянии. Массивы activeSorts и activeFilters как раз и предполагают, что возможна множественная сортировка и множественная фильтрация по каждой колонке.
К сожалению, формат статьи не позволяет описать всех тонкостей, поэтому предлагаю сразу посмотреть результат.
Итого разработчику в таблице необходимо:
- автоподстройка ширины таблицы под ширину контейнера
- прокрутка тела таблицы и синхронизация шапки
- сортировка таблицы (возможна множественная сортировка)
- фильтрация таблицы (возможна множественная фильтрация)
Все это я реализовал в примере. Надеюсь теперь, при переходе на новый фреймворк, у вас как минимум появился выбор — брать готовую или сделать свою таблицу.
Источник
Верстка таблицы html css
В статье я покажу стандартную табличную разметку, какие у неё есть альтернативы. Дам пример собственной таблицы и разметки, а также опишу общие моменты её реализации.
Стандартная HTML4 таблица
Если мы не указали ширину таблицы/столбцов, то ширина таблицы подстраивается и растягивается, чтобы вместить содержимое любого из столбцов.
В данном случае вычисляется процентное соотношение каждого столбца к общей ширине и каждый столбец растягивается соответственно процентному соотношению.
В первом примере ширина всей таблицы (примерно) = 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, если посмотреть в разметку, использует тоже две таблицы:
Верхняя таблица отображает шапку, нижняя — тело. Хотя для пользователя кажется как будто бы это одна таблица.
Опять же пример использует синхронизацию прокрутки, если прокрутить тело таблицы, то произойдет синхронизация шапки.
А как же так получается, что тело таблицы (одна таблица) и шапка (другая таблица) подстраиваются под ширину контейнера и они никак не разъезжаются по ширине и совпадают друг с другом?
Тут кто как умеет так и синхронизирует, например, вот функция синхронизации ширины из вышеприведенной библиотеки:
И тут мы окажемся не первыми, некоторые вообще не используют табличную разметку. Например 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= <0>зависит от ширины двух колонок [«Company», «Cost»] .
Элемент TableColumn «фейковый», он никогда не будет отображаться, а вот его содержимое this.props.children — отображается в ячейке шапки.
Разработка
На основе описаний колонок сделаем функцию, которая будет разбивать описания по рядам и по ключам, а также будет сортировать описания по рядам в результирующем массиве:
Теперь обработанные описания передаём в шапку и в тело для отображения ячеек. Шапка будет строить ячейки так:
Тело таблицы будет строить ячейки тоже на основе обработанных описаний колонок:
Тело таблицы использует описания у которых есть свойство dataField , поэтому описания фильтруются используя функцию getCellDescriptions .
Тело таблицы будет слушать события изменения размеров экрана, а также прокрутки самого тела таблицы:
Подстройка ширины таблицы происходит следующим образом.
После отображения берётся ширина контейнера, сравнивается с шириной всех ячеек, если ширина контейнера больше, увеличивается ширина всех ячеек.
Для этого разработчик должен хранить состояние коэффициента ширины (который будет меняться).
Следующие функции реализованы в таблице, однако разработчик может использовать свои. Чтобы использовать уже реализованные, необходимо их импортировать и прилинковать к текущему компоненту:
Функция подстройки ширины:
Функция синхронизация шапки:
Ключевая особенность таблицы для redux — это то, что она не имеет своего внутреннего состояния (она должна иметь состояние, но только в том месте, где укажет разработчик).
И подстройка ширины adjustBody и синхронизация скролла adjustScroll — это функции которые изменяют состояние у прилинкованного компонента.
Внутрь TableColumn можно вставлять любую jsx разметку. Зачастую используются такие варианты: текст, кнопка сортировки и кнопка фильтрации.
Для массива активных сортировок/фильтраций разработчик должен создать состояние и передавать его в таблицу.
Передаем в таблицу массив активных сортировок/фильтраций:
Компонент сортировки SortButton и компонент фильтрации MultiselectDropdown при изменении «выбрасывают» новые активные фильтры/сортировки, которые разработчик должен заменить в состоянии. Массивы activeSorts и activeFilters как раз и предполагают, что возможна множественная сортировка и множественная фильтрация по каждой колонке.
К сожалению, формат статьи не позволяет описать всех тонкостей, поэтому предлагаю сразу посмотреть результат.
Итого разработчику в таблице необходимо:
- автоподстройка ширины таблицы под ширину контейнера
- прокрутка тела таблицы и синхронизация шапки
- сортировка таблицы (возможна множественная сортировка)
- фильтрация таблицы (возможна множественная фильтрация)
Все это я реализовал в примере. Надеюсь теперь, при переходе на новый фреймворк, у вас как минимум появился выбор — брать готовую или сделать свою таблицу.
Источник
2.8. CSS-таблицы
Спецификация CSS даёт неограниченные возможности для оформления таблиц. По умолчанию таблица и ячейки таблицы не имеют видимых границ и фона, при этом ячейки внутри таблицы не прилегают вплотную друг к другу.
Ширина ячеек таблицы определяется шириной их содержимого, поэтому ширина столбцов таблицы может быть разной. Высота всех ячеек ряда одинаковая и определяется высотой самой высокой ячейки.
Форматирование таблиц
- Содержание:
- 1. Границы таблицы border
- 2. Как задать ширину и высоту таблицы
- 3. Как задать фон таблицы
- 4. Столбцы таблицы
- 5. Как добавить таблице заголовок
- 6. Как убрать промежуток между рамками ячеек
- 7. Как увеличить промежуток между рамками ячеек
- 8. Как скрыть пустые ячейки таблицы
- 9. Компоновка макета таблицы с помощью свойства table-layout
- 10. Лучшие макеты таблиц (Топ-10 таблиц)
1. Границы таблицы border
Таблица и ячейки внутри неё по-умолчанию отображаются в браузере без видимых границ. Границы таблицы задаются свойством border :
Границы ячеек заголовка каждого столбца задаются для элемента th :
Границы ячеек тела таблицы задаются для элемента td :
Толщина рамок соседних ячеек не удваивается, поэтому задать границы для всей таблицы можно следующим способом:
Внешнюю границу таблицы можно выделить, задав ей увеличенную ширину:
Границы можно задавать частично:
Подробнее о свойстве border вы можете прочитать здесь.
2. Как задать ширину и высоту таблицы
По умолчанию ширина и высота таблицы определяется содержимым её ячеек. Если ширина не задана, то она будет равна ширине самого широкого ряда (строки).
Ширина таблицы и столбцов задаётся с помощью свойства width . Если для таблицы задано table
Ширину таблицы и столбцов обычно задают в px или % , например:
Фиксировать высоту с помощью свойства height не рекомендуется.
3. Как задать фон таблицы
По умолчанию фон таблицы и ячеек прозрачный. Если страница или блок, содержащие таблицу, имеют фон, то он будет просвечиваться сквозь таблицу. Если фон задан и для таблицы и для ячеек, то в местах наложения фона таблицы и ячеек будет виден фон только ячеек. В качестве фона для таблицы в целом и её ячеек могут выступать:
4. Столбцы таблицы
- с помощью элемента можно задать фон для любого количества столбцов;
- с помощью селектора table td:first-child , table td:last-child можно задать стили для первого или последнего столбца таблицы (за исключением первой ячейки заголовка таблицы);
- с помощью селектора table td:nth-child(правило отбора столбцов) можно задать стили для любых столбцов таблицы.
Подробнее про элемент вы можете прочитать здесь.
Подробнее про CSS-селекторы вы сможете прочитать здесь.
5. Как добавить таблице заголовок
Добавить заголовок в таблицу можно с помощью элемента , а с помощью свойства caption-side его можно поместить перед таблицей или под ней. Для горизонтального выравнивания текста заголовка применяется свойство text-align .
caption-side | |
---|---|
Значения: | |
top | Заголовок таблицы располагается над таблицей. Значение по умолчанию. |
bottom | Располагает заголовок под таблицей. |
initial | Устанавливает значение свойства в значение по умолчанию. |
inherit | Наследует значение свойства от родительского элемента. |
Рис. 1. Пример отображения заголовка под таблицей
6. Как убрать промежуток между рамками ячеек
Рамки ячеек таблицы по умолчанию разделены небольшим промежутком. Если задать для таблицы border-collapse: collapse , то промежуток уберётся.
border-collapse | |
---|---|
Значения: | |
separate | Рамки ячеек располагаются раздельно. |
collapse | Рамки ячеек сливаются в одну, а промежутки между рамками убираются. |
initial | Устанавливает значение свойства в значение по умолчанию. |
inherit | Наследует значение свойства от родительского элемента. |
Рис. 2. Пример таблиц со сливающимися и раздельными рамками ячеек
7. Как увеличить промежуток между рамками ячеек
С помощью свойства border-spacing можно менять расстояние между рамками ячеек. Данное свойство применяется к таблице в целом.
border-spacing | |
---|---|
Значения: | |
Добавляет промежутки между рамками как по вертикали, так и по горизонтали. Если заданы две длины, то первая всегда определяет горизонтальный промежуток, а вторая — вертикальный. | |
initial | Устанавливает значение свойства в значение по умолчанию. |
inherit | Наследует значение свойства от родительского элемента. |
Рис. 3. Пример таблиц с увеличенными промежутками между рамками ячеек
8. Как скрыть пустые ячейки таблицы
Свойство empty-cells скрывает или показывает пустые ячейки. Действует только на ячейки, которые не содержат какой-либо контент. Если для ячейки задан фон, а для таблицы задано table
empty-cells | |
---|---|
Значения: | |
show | Рамка и фон пустой ячейки будут отрисовываться так же, как для ячейки таблицы, имеющей содержимое. |
hide | Если все ячейки строки пусты, то вся строка отображается так, если бы было задано значение display: none . |
initial | Устанавливает значение свойства в значение по умолчанию. |
inherit | Наследует значение свойства от родительского элемента. |
Рис. 4. Пример скрытия пустой ячейки таблицы
9. Компоновка макета таблицы с помощью свойства table-layout
Компоновка макета таблицы определяется одним из двух подходов: фиксированный макет или автоматический макет. Под компоновкой в данном случае подразумевается как распределяется ширина таблицы между шириной ячеек.
Свойство не наследуется.
table-layout | |
---|---|
Значения: | |
auto | Значение по умолчанию. Ширина макета таблицы определяется шириной её содержимого с учетом значений свойств padding-left , padding-right , border-left width плюс одна ширина border-right последней ячейки в ряду, или заданной шириной ячеек и толщиной рамки. Если ширина ячеек не задана явно, они могут быть разной ширины. |
fixed | Свойство сработает только в том случае, если для таблицы задана ширина. Ширина ячеек будет одинаковой, а содержимое ячеек, которое не помещается в ячейку, будет наползать под содержимое соседней ячейки. |
initial | Устанавливает значение свойства в значение по умолчанию. |
inherit | Наследует значение свойства от родительского элемента. |
10. Лучшие макеты таблиц
По материалам статьи Top 10 CSS Table Designs из журнала Smashing Magazine
1. Горизонтальный минимализм
Горизонтальные таблицы — это таблицы, текст в которых читается по горизонтали. Каждая сущность представляет собой отдельную строку. Вы можете оформить подобные таблицы в минималистском стиле, поместив двухпиксельную границу под заголовком th .
При большом количестве строк такой дизайн таблиц затрудняет их чтение. Для решения этой проблемы можно добавить однопиксельную границу под всеми элементами td .
Добавление эффекта :hover для элемента tr облегчит чтение таблиц, оформленных в минималистском стиле. При наведении курсора мыши на ячейку, остальные ячейки той же строки выделяются одновременно, что упрощает процесс отслеживания информации, если таблицы имеют несколько столбцов.
2. Вертикальный минимализм
Несмотря на то, что подобные таблицы используются редко, тем не менее, вертикально ориентированные таблицы полезны для категоризации или сравнения описания объектов, представленных колонкой. Можно оформить их в минималистском стиле, добавив пробел, разделяющий столбцы.
3. «Коробочный» стиль
Наиболее надежным стилем для оформления таблиц всех типов, является так называемый «коробочный» стиль. Достаточно подобрать хорошую цветовую гамму, а затем задать цвет фона для всех ячеек. Не забудьте подчеркнуть различие между строками, установив границы в качестве разделителя.
Самое сложное — найти ту цветовую гамму, которая будет гармонично сочетаться с вашим сайтом. Если сайт нагружен по графике и дизайну, то вам будет довольно трудно использовать этот стиль.
4. Горизонтальная зебра
Зебра-таблица выглядит довольно привлекательной и удобной. Дополнительный цвет фона может служить в качестве визуальной подсказки для людей при чтении таблицы.
5. Газетный стиль
Для достижения так называемого газетного эффекта, можно применить границы для элементов таблицы и поиграть с ячейками внутри. Легкий, минималистичный газетный стиль может выглядеть так: обыграйте цветовую гамму, добавьте границы, отступы, разные фоны, и эффект :hover при наведении на строку.
6. Фон таблицы
Если вы ищете быстрый и уникальный способ оформления таблицы, выберите привлекательное изображение или фото, относящиеся к теме таблицы и установите ее фоном таблицы.
Источник
➤ Adblockdetector