Реагуючі блоки однакової висоти на основі Flexbox з JavaScript Fallback
Чому саме Flexbox? Тому що цей модуль був розроблений для того, щоб вирішити проблеми даного типу. Це гнучкий і ефективний спосіб управління для всіх видів макетів. Цей спосіб не створює майже ніякого часового розриву між правильним та неправильним виглядом макета. В випадку JavaScript рішення потрібен час, щоб скачати документ, а потім завантажити відповідний JS файл і, якщо такий є, завантажити зображення в блок. Flexbox миттєвий і JavaScript займає всього кілька секунд. Цей спосіб з JavaScript ідеально підходить для людей, які використовують старі браузери, які не підтримують Flexbox.
Проблема
Код і проблема (макет з ламаною лінією) для вирішення:
<ul class="list">
<li class="list__item"><!-- content --></li>
<li class="list__item"><!-- content --></li>
<!-- other items -->
</ul>
.list
{
overflow: hidden; /* just clearing floats */
}
.list__item
{
width: 25%; /* 4 items per row */
float: left;
}

Вирішення:
Якщо ви ще не працювали з Flexbox, ви будете приємно здивовані. display: flex ініціює Flexbox для елемента контейнера, flex-wrap: wrap обгортання каже обернути дочірні елементи, а не розміщати їх на одній лінії. Повторюючи display: flex для дочірніх елементів, гарантується, що елементи мають однакову висоту у своїх рядках.
.list
{
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-wrap: wrap;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
}
.list__item
{
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
}
\
Це прекрасно працює в останніх версіях Chrome, Android, Safari, Opera, Firefox, і Internet Explorer 10 +. Для решти є “таблетка” JavaScript.
Я не включив це в попередньому коді CSS, але деякі з старих WebKit браузерів підтримують старий синтаксис Flexbox (display: -webkit-box). Тим не менш, обгортка -webkit-box-lines: multiple не працює на IOS Safari 6.1- та Android 4.3-.
JavaScript Fallback
Ця частина охоплює запасне рішення для таких браузерів, як Internet Explorer 9-, Android 4.3-, IOS Safari 6.1-, і Opera Mini. Я написав невеликий шматочок JQuery-залежного коду, який:
-
Виявляє, якщо браузер не підтримує Flexbox;
-
Розраховує кількість елементів в рядку, розділивши ширину.list і ..list__item;
-
Віртуально ділить список в рядках відповідно до цього числа;
-
Виявляє, який елемент має найбільшу висоту в кожному рядку;
-
Встановлює цю висоту для інших елементів в кожному рядку відповідно.
;( function( $, window, document, undefined )
{
'use strict';
var s = document.body || document.documentElement, s = s.style;
if( s.webkitFlexWrap == '' || s.msFlexWrap == '' || s.flexWrap == '' ) return true;
var $list = $( '.list' ),
$items = $list.find( '.list__item' ),
setHeights = function()
{
$items.css( 'height', 'auto' );
var perRow = Math.floor( $list.width() / $items.width() );
if( perRow == null || perRow < 2 ) return true;
for( var i = 0, j = $items.length; i < j; i += perRow )
{
var maxHeight = 0,
$row = $items.slice( i, i + perRow );
$row.each( function()
{
var itemHeight = parseInt( $( this ).outerHeight() );
if ( itemHeight > maxHeight ) maxHeight = itemHeight;
});
$row.css( 'height', maxHeight );
}
};
setHeights();
$( window ).on( 'resize', setHeights );
$list.find( 'img' ).on( 'load', setHeights );
})( jQuery, window, document );
Що робити, если JavaScript відключеній в браузері? Проблема в тому, що нативна функція виявлення CSS є менш підтримуваною, ніж сама Flexbox. Тому, використовуючи @support неможливо охопити кожен браузер, який підтримує Flexbox. Але це краще, ніж нічого.
Як можна вирішити цю проблему: “вимкнений JavaScript = немає підтримки Flexbox( скоріше всього - самий вірний спосіб)” і і виправити винятки з допомогою @support. Можна додати ім'я класу .no-JS до <HTML> тега і видалити його за допомогою JavaScript. Так ми будемо знати відключений він чи ні. Тоді, стилюйте елементи списку і, нарешті, "компенсуйте" це стилювання за допомогою @support.
Блоки відображаються, як рядки в повну ширину в цьому випадку. Якщо є будь-які зображення, вони будуть вирівняні по правому краю рядка на великих екранах.
<html class="no-js">
<head>
<!-- your stuff -->
<script>(function(e,t,n){var r=e.querySelectorAll("html")[0];r.className=r.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")})(document,window,0);</script><!-- remove this if you are using Modernizr -->
</head>
<!-- your stuff -->
</html>
html.no-js .list__item
{
width: 100%;
float: none;
}
html.no-js .list__item img
{
max-width: 9.375rem; /* 150 */
float: right;
margin-left: 1.25rem; /* 20 */
}
@supports ( display: -webkit-flex ) or ( display: -ms-flex ) or ( display: flex )
{
html.no-js .list__item
{
width: 25%;
float: left;
}
html.no-js .list__item img
{
max-width: none;
float: none;
margin-left: 0;
}
}

590 5


Коментарі:
0
Taras987
$list.find( 'img' ).on( 'load', setHeights );
спрацює стільки разів, скільки є картинок, чи я помиляюсь?