«Великий зрівнювач» або спосіб вирішити проблему вирівнювання по висоті

Ми багато займаємося електронною комерцією і часто зустрічаємо завдання щодо вирівнювання елементів. На перший погляд все просто, в коді пишеться кілька рядків і все ок. Але насправді елементи бувають дуже різні, правил застосування теж багато, а ще є адаптив.

Ця стаття стане у пригоді тим, хто часто стикається з проблемою вирівнювання елементів по висоті в різних ситуаціях.

Рис. 1. Порядок відображення групи товарів.



Стандартними елементами картки товару є фото товару, назва, ціна, кнопка «купити». Але часто з'являються додаткові поля, наприклад: «рейтинг», «відгуки», «немає у продажу», «акції / знижки», «стара / нова ціна», опис товару та інші, які можуть впливати на стандартну висоту картки товару, а оскільки розміри і наповнення контентом цих елементів варіюється для кожного товару індивідуально (наприклад на якомусь товарі є стара ціна, на іншому немає або назва в кілька рядків) не тільки весь ряд у нас набуває некоректний вигляд, а і впливає на відображення наступних елементів.

Рис. 2. Некоректне відображення при додаванні елементів, або зміні їх висот.



Варіант з фіксованим розміром картки не дуже підходить, оскільки:

  1. 90% моїх робіт — адаптивні сайти (мінімум фіксованих розмірів, в даному випадку — висота картки товару не повинна бути фіксованою).
  2. Не вийде розрахувати оптимальну висоту, щоб підходила для всіх варіантів.


Можна взяти розбиття по системі Grid – один ряд по чотири товару (приклад із спрощеної семантикою):

<row>
<col>
<col>
<col>
<col>
</row>


Але тоді виникають труднощі з обробкою і висновком товарів на стороні сервера (необхідно ускладнювати вибірку циклами і умовами), особливо, якщо товари вибираються з різних категорій — тоді у нас нова категорія буде починатися з нового ряду, а нам потрібно вивести всі товари поспіль.

В ідеалі нам необхідна наступна структура:

<div class="wrapper">
<div class="product-card">...</div>
<div class="product-card">...</div>
<div class="product-card">...</div>
<div class="product-card">...</div>
.........
<div class="product-card">...</div>
</div>


І щоб все виглядало рівно і красиво.

Ось тут мене і виникла ідея написати невелику функцію, яка буде цим займатися. Я зустрічав деякі готові рішення, але у них були проблеми, або вже дуже обмежена область застосування. Довелося писати свій «велосипед».

Отже! Перейдемо ближче до технічної частини статті:

  1. Функція написана з використанням бібліотеки jQuery, за бажанням легко переписується на native js.
  2. В ній просто розібратися, і додати (за необхідності) щось своє.
  3. найважливіше! — вона робить свою справу!


Структура DOM дерева використовується як у прикладі вище:

<div class="wrapper">
<div class="product-card">...</div>
<div class="product-card">...</div>
<div class="product-card">...</div>
<div class="product-card">...</div>
.........
<div class="product-card">...</div>
</div>


Принцип роботи наступний:

  1. Дізнаємося ширину картки товару «product-card»;
  2. Дізнаємося ширину батьківського обгортки «wrapper»;
  3. Виробляємо розрахунок — скільки карток влізе по ширині в обгортку (округлення у бік зменшення) так ми отримуємо имитируемый ряд;
  4. Далі в роботу вступають цикли:
    а) Скільки і яких елементів необхідно зрівняти по висоті в одній картці;
    б) Порівнює ці висоти в кожній картці імітованого ряду, і знаходить найбільше значення висоти порівнюваних елементів;
    в) Призначає відповідні висоти всім елементам які потрапили в область порівняння.


Нижче вказано власне сам скрипт (цифрами відзначені пункти зі списку принципу роботи):

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");


Зверніть увагу! Першим аргументом ви повинні вказати картку товару. Далі у будь-якому порядку перелік тих елементів, які необхідно вирівняти, функція може прийняти і обробити будь-яке число елементів!

Ось як приклад скріншот, на якому чітко видно що, з-за різниці висот елементів (title товару має різну кількість рядків, і в першому товар з'явилася стара ціна), перший ряд виглядає некоректно, а другий ряд змістився.

Рис. 3. Приклад відображення групи товарів без вирівнювання.



А на наступному зображенні чітко видно, як змінилося співвідношення висот елементів:

Рис. 4. Приклад результату роботи скрипта.



Буду радий, якщо ця стаття припала комусь на користь! Всім успіхів, цікавих проектів та нестандартних рішень!
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.