«Великий уравнитель» или способ решить проблему выравнивания по высоте
Эта статья пригодится тем, кто часто встречается с проблемой выравнивания элементов по высоте в разных ситуациях.
Рис. 1. Порядок отображения группы товаров.
Стандартными элементами карточки товара являются фото товара, название, цена, кнопка «купить». Но часто появляются и дополнительные поля, например: «рейтинг», «отзывы», «нет в продаже», «акции / скидки», «старая / новая цена», описание товара и другие, которые могут влиять на стандартную высоту карточки товара, а поскольку размеры и наполнение контентом этих элементов варьируется для каждого товара индивидуально (например на каком-то товаре есть старая цена, на другом нет или название в несколько строк) то не только весь ряд у нас приобретает некорректный вид, а и влияет на отображение последующих элементов.
Рис. 2. Некорректное отображение при добавлении элементов, или изменении их высот.
Вариант с фиксированным размером карточки не очень подходит, так как:
- 90% моих работ — адаптивные сайты (минимум фиксированных размеров, в данном случае — высота карточки товара не должна быть фиксированной).
- Не получится рассчитать оптимальную высоту, чтобы подходила для всех вариантов.
Можно взять разбитие по системе Grid — один ряд по четыре товара (пример с упрощенной семантикой):
Но тогда возникают трудности с обработкой и выводом товаров на стороне сервера (необходимо усложнять выборку циклами и условиями), особенно, если товары выбираются из разных категорий — тогда у нас новая категория будет начинаться с нового ряда, а нам нужно вывести все товары подряд.
В идеале нам необходима следующая структура:
...
...
...
...
………
...
И чтобы все выглядело ровно и красиво.
Вот здесь меня и посетила идея написать небольшую функцию, которая будет этим заниматься. Я встречал некоторые готовые решения, но у них либо были проблемы, либо уж очень ограниченная область применения. Пришлось писать свой «велосипед».
Итак! Перейдем ближе к технической части статьи:
- Функция написана с использованием библиотеки jQuery, по желанию легко переписывается на native js.
- В ней просто разобраться, и добавить (по необходимости) что-то свое.
- Самое важное! — она делает свое дело!
Структура DOM дерева используется как в примере выше:
...
...
...
...
………
...
Принцип работы следующий:
- Узнаем ширину карточки товара «product-card»;
- Узнаем ширину родительской обертки «wrapper»;
- Производим расчет — сколько карточек влезет по ширине в обертку (округление в меньшую сторону) так мы получаем имитируемый ряд;
- Далее в работу вступают циклы:
а) Сколько и каких элементов необходимо уравнять по высоте в одной карточке;
б) Сравнивает эти высоты в каждой карточке имитируемого ряда, и находит наибольшее значение высоты сравниваемых элементов;
в) Назначает соответствующие высоты всем элементам которые попали в область сравнения.
Ниже указан собственно сам скрипт (цифрами отмечены пункты из списка принципа работы):
function GreatBalancer(block){
var wrapWidth = $(block).parent().width(), // 1
blockWidth = $(block).width(), // 2
wrapDivide = Math.floor(wrapWidth / blockWidth), // 3
cellArr = $(block);
for(var arg = 1;arg<=arguments.length;arg++) { // 4.1
for (var i = 0; i <= cellArr.length; i = i + wrapDivide) {
var maxHeight = 0,
heightArr = [];
for (j = 0; j < wrapDivide; j++) { // 4.2
heightArr.push($(cellArr[i + j]).find(arguments[arg]));
if (heightArr[j].outerHeight() > maxHeight) {
maxHeight = heightArr[j].outerHeight();
}
}
for (var counter = 0; counter < heightArr.length; counter++) { // 4.3
$(cellArr[i + counter]).find(arguments[arg]).outerHeight(maxHeight);
}
}
}
}
и его вызов
GreatBalancer(".product-card",".product-title",".price-min",".product-image");
Обратите внимание! Первым аргументом вы должны указать карточку товара. Далее в любом порядке перечень тех элементов, которые необходимо уровнять, функция может принять и обработать любое число элементов!
Вот в качестве примера screenshot, на котором четко видно что, из-за различия высот элементов (title товара имеет разное количество строк, и в первом товаре появилась старая цена), первый ряд выглядит некорректно, а второй ряд сместился.
Рис. 3. Пример отображения группы товаров без выравнивания.
А на следующем изображении отчетливо видно, как изменилось соотношение высот элементов:
Рис. 4. Пример результата работы скрипта.
Буду рад, если эта статья пришлась кому то на пользу! Всем успехов, интересных проектов и нестандартных решений!
Комментарии (14)
29 ноября 2016 в 13:17
+1↑
↓
Зачем js? Чем flexbox не угодил?
29 ноября 2016 в 13:44
0↑
↓
Данная статья предлагает один из методов решения проблемы, так как в некоторых случаях flex не подходит. Например если мы верстаем под поддержку более ранних версий IE и других браузеров, или используем в работе сетку grid встречаемую в Bootstrap или другом подобном наборе инструментов29 ноября 2016 в 13:55
0↑
↓
http://caniuse.com/#feat=flexbox — 97%. Оставшимся 3-м можно намекнуть про современный мир. А чтобы они не сильно расстраивались из-за кривой вёрстки в их, можно подключить modernizr и подключать js-решения.
Фреймворки с гридами надо выбирать нормальные. 4-й бутстрап может сетку через flex делать, почему бы не использовать его? Плюс, флекс — это не только сетка, это ещё куча крутых возможностей. А проблема отсутствия поддержки флекса всё больше становится гипотетической, нежели реальной.
29 ноября 2016 в 13:46
0↑
↓
Тем, что приходится поддерживать IE8.29 ноября 2016 в 13:57
+1↑
↓
Зачем? Это реальная надобность или так сказали? Ну и опять же, что мешает подключить modernizr и добавить фолбэк на случай старых ослов?
29 ноября 2016 в 13:30
+1↑
↓
Не получится рассчитать оптимальную высоту, чтобы подходила для всех вариантов.
Не выдумывайте и используйте flexbox29 ноября 2016 в 13:44
0↑
↓
Ответил выше
29 ноября 2016 в 13:38
0↑
↓
И зачем на JS решать задачи вёрстки, когда есть а) флексбоксы (почти все браузеры), б) старая статья «Список блоков с разным вертикальным выравниванием» (с ограничениями, но тут можно приспособить)?29 ноября 2016 в 13:44
0↑
↓
Изобрел eqheught29 ноября 2016 в 14:04
0↑
↓
bootstrap equal height тоже использует флекс. Он не удовлетворяет требованиям для разработки коммерческих проектов. По статистике IE до сих находится в верху списка по популярности. Особенно им пользуются организации с лицензионным ПО, и об этом стоит помнить.29 ноября 2016 в 14:06
0↑
↓
А я говорил про древний eqheight.js
Про флексы выше отписались — это всё пуки в пузырьки про «почти все браузеры». Лет через 5
В Foundation тоже на JS, но, если мне не изменяет память, если собрать с флексовыми гридами, будет тоже на них
29 ноября 2016 в 13:45
0↑
↓
Давно есть скрипт matchHeight именно для этой задачи29 ноября 2016 в 14:04
0↑
↓
Если саппортить старые ie то вполне сойдет, в ином случае согласен со всеми ко советовал flexbox29 ноября 2016 в 14:13
0↑
↓
Я бы функцию назвал GreatEqualizer.