<
  • Главная
Статьи

Красиве вирівнювання блоків по гумовій сітці - CSS-LIVE

  1. проблема
  2. Як це працює?
  3. text-align: center
  4. text-align: justify
  5. Рішення
  6. резюме

Сьогодні, в мій день народження (26 квітня), я хочу зробити подарунок всім верстальщикам і представити вам абсолютно унікальне, нове і найголовніше - корисне рішення вирівнювання блоків по гумовій сітці, якого так всі довго чекали і якого ще немає в мережі.

При верстці гумових сторінок часто виникає задача вибудувати однотипні блоки (наприклад, товари в каталозі або фотографії в галереї) по сітці, на зразок таблиці, але гнучкою, із заздалегідь невідомою кількістю стовпців. Колись єдиним способом для цього був float, і блоки доводилося притискати до лівого краю. За допомогою inline-block це завдання можна вирішити простіше і гнучкіше, блоки можуть мати різну висоту, і різний вертикальне вирівнювання. Але чомусь такі макети в масі все одно притиснуті до лівого краю. Здавалося б, що заважає відцентрувати цю сітку, а то і зовсім розтягнути її по ширині вільного місця c допомогою text-align: center або justify відповідно?

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

проблема

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

Проблема дуже схожа в обох випадках, так що виберемо будь-яку властивість з двох, наприклад, text-align: center. А так же скористаємося маркованих списком.

<Ul> <li> Пункт 1 </ li> <li> Пункт 2 </ li> <li> Пункт 3 </ li> <li> Пункт 4 </ li> <li> Пункт 5 </ li> <li > Пункт 6 </ li> <li> Пункт 7 </ li> <li> Пункт 8 </ li> </ ul> ul {font: 14px Verdana, Geneva, sans-serif; text-align: center; } Ul li {display: inline-block; width: 80px; height: 80px; margin-bottom: 10px; background: # E76D13; vertical-align: top; text-align: center; line-height: normal; / * Емуляція inline-block для IE6-7 * / // display: inline; // zoom: 1; }

Нічого незвичайного в коді немає. Звичайний список, все ті ж старі добрі елементи рядково-блочного (display: inline-block) рівня. Саме мабуть цікаве, що варто виділити, це text-align: center, завдяки якому і відбувається наше горизонтальне вирівнювання.
Поки пункти займають єдиний рядок, все виглядає так.

Поки пункти займають єдиний рядок, все виглядає так

Але, як тільки на полі з'являється останній рядок, кількість блоків в якій менше, ніж в попередніх рядках, то виходить наступне.

Але, як тільки на полі з'являється останній рядок, кількість блоків в якій менше, ніж в попередніх рядках, то виходить наступне

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

А тепер, давайте поглянемо, щоб ми хотіли отримати.

Як видно з малюнка, два елементи в останньому рядку притиснулися до лівого краю, не дивлячись на те, що рядок по ширині явно більше, ніж загальна ширина її блоків. Це видно по правому, вільного простору, яке становить дві третини наших елементів. Саме така поведінка блоків нам і потрібно отримати в результаті. Тобто по суті зробити так, щоб вирівнювання елементів було красивим, що будуються рівно по сітці (навіть по гумовою), не дивлячись на свою кількість і надлишок білого простору в останньому рядку. Говорячи іншими словами, нам потрібно якимось чином вплинути на поведінку останнього рядка, змусивши її підкорятися нашим правилам.

Як це працює?

Перед тим, як перейти безпосередньо до вирішення завдання, давайте для початку розберемо алготітм роботи таких властивостей, як text-align: center і justify. Це допоможе нам краще зрозуміти, що відбувається в нашій сітці, її поведінку, і те, як виконується робота цих властивостей в останньому рядку.

text-align: center

Почнемо мабуть з text-align: center. У ньому можна виділити три основні етапи.

Перший етап
На початку береться рядок. Вираховується загальна ширина слів або нерозривні блоків (inline-block, img, і т.д) в рядку. Причому якщо між цими блоками є фактичні прогалини або ж відступи, які зроблені за допомогою таких засобів, як word-spacing і інших, то ці відстані так само додаються до загальної суми ширини блоків.

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

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

Щоб краще зрозуміти, як все відбувається, я зробив спеціальний малюнок

Перед нами малюнок, на якому зображений контейнер, з двома рядками, ширина яких становить 500px.
Так само ми можемо бачити, що сума всіх блоків в першому рядку з їх інтервалами дорівнює 370px. Значить на третьому етапі наш алгоритм вирахував з першого друге (500-370), що дало результат 130. Далі, як я вже говорив, поділив цю суму рівно на два рази (130/2) і відсунув найперший блок вправо, на отриманий результат (65px). Таким чином наші блоки виявилися точно по середині, з відступи з боків стали абсолютно однаковими. Якби в першому рядку не вистачило місця, то самий крайній праворуч блок перейшов би на другою рядок і алгоритм знову включився б у справу.

Теж саме стосується і другого рядка. У ній алгоритм працює точно так само, мало того, можна побачити, що бічні відступи в ній складають дробове число (132.5px), так як text-align: center ділить загальну ширину блоків з їх інтервалами рівно на 2, як я і говорив.

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

text-align: justify

Механізм text-align: justify, я вже описував в одній зі своїх статей . Повторюватися не має сенсу, тому я вам, настійно рекомендую пройти по посиланню і уважно перечитати там все, що стосується алгоритму та етапів роботи text-align: justify.
Єдине, що я хочу згадати тут, це те, що ...

Остання ж рядок не потрапляє в поле зору justify, так як він працює тільки для цілком заповнених рядків, а в останньому рядку прогалини завжди залишаються свого звичайного розміру.

Так, саме так. text-align: justify на відміну від text-align: center взагалі відмовляється працювати з останнім рядком, і тому вирівнювання по ширині в ній не відбувається.
Так що це теж входить в наші обов'язки, а саме змусити непрацюючий алгоритм діяти, і в завершальній рядку.

Рішення

Відразу забігу вперед і скажу, що рішення для обох випадків абсолютно ідентично, тому немає сенсу розбирати кожне з них окремо. Так що давайте поміркуємо, що у нас є на даний момент.
Значить, по суті, у нас є дві властивості text-align: justify і center, кожен з яких вирівнює рядки за власним алгоритмом. А так же ми вже розуміємо, що text-align: center працює з останнім рядком, а ось text-align: justify - немає. Але зате ми точно знаємо, що якщо рядок, за якою йде наступна (припустимо остання) буде повністю заповнена, то ці властивості будуть вирівнювати нашу сітку за нашими правилами. І навіть при гумової ширині контейнера такі заповнені рядки будуть вести себе так, як нам хотілося б.

Який же висновок можна з цього зробити? І як можна пов'язати ці речі з останнім рядком, в якій може бути всього один блок? Відповідь проста. Нам потрібно придумати, як можна заповнити останній рядок так, щоб, що залишилося від загальної ширини блоків простір, було чимось заповнено, і мало того, щоб це "щось" могло переходити на наступний рядок, для того, щоб наші властивості працювали бездоганно.

Отже, для заповнення останнього рядка, ми будемо використовувати псевдоелемент, згенерований за допомогою: after. Це хороший варіант, так як він допоможе вирішити нам нашу задачу і позбавить від зайвого сміття в розмітці. За замовчуванням псевдоелементи генерують рядковий блок, а значить саме те, що нам і потрібно. Так як inline-block буде представляти із себе одну велику, нерозривний букву і не зможе розбитися на кілька "цеглин", що не приведе ні до чого путнього. Ну, а block відразу ж займе окремий рядок, і так само, як і inline-block - не принесе результатів. При цих значеннях наша ситуація буде виглядати приблизно так.

ul: after {content: 'display: block, мало контенту'; display: block; background: # E76D13; }

ul: after {content: 'display: block, мало контенту';  display: block;  background: # E76D13;  }

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

З усього вищесказаного можна зрозуміти одне, що в нашій ситуації нам може допомогти елемент, саме сатиричного (inline) рівня, тобто звичайний display: inline + рядок тексту, з пробілами між слів.

ul: after {content: 'Звичайний строковий елемент, звичайний строковий елемент, звичайний строковий елемент; background: # E76D13; }

ul: after {content: 'Звичайний строковий елемент, звичайний строковий елемент, звичайний строковий елемент;  background: # E76D13;  }

Так, дуже схоже. З скриншота ясно, рядковий блок, мало того, що зміг вплинути на останній рядок, так ще й перенісся на наступну повному обсязі, залишивши на попередній сходинці нерозривне слово. З цього слова видно, що по своїй ширині воно трохи не дотягує до ширини блоків (100px), а якби дотягував, то, можливо, у нас і вийшло б щось путнє.

Загалом поекспериментувавши якийсь час з вишесказаннним, на світ народилося наступне рішення.

ul {font: 14px Verdana, Geneva, sans-serif; text-align: center; margin: 0px 0 10px; } Ul: after {content: 'iiiiiiii'; word-spacing: 97px; padding-left: 97px; / * Visibility: hidden; Приховав це властивість, заради демонстрації процесу * /} ul li {display: inline-block; width: 100px; height: 100px; margin: 0px 0 20px; background: # E76D13; vertical-align: top; text-align: center; / * Емуляція inline-block для IE6-7 * / // display: inline; // zoom: 1; }

ul {font: 14px Verdana, Geneva, sans-serif;  text-align: center;  margin: 0px 0 10px;  } Ul: after {content: 'iiiiiiii';  word-spacing: 97px;  padding-left: 97px;  / * Visibility: hidden;  Приховав це властивість, заради демонстрації процесу * /} ul li {display: inline-block;  width: 100px;  height: 100px;  margin: 0px 0 20px;  background: # E76D13;  vertical-align: top;  text-align: center;  / * Емуляція inline-block для IE6-7 * / // display: inline;  // zoom: 1;  }

Здорово! Наша сітка вирівняна так, як нам треба. Відразу ж скажу, що таке вирівнювання виходить при будь-якій ширині екрану, що не може не радувати. А тепер сама суть.

Значить у нас є рядок "iiiiiiii", що складається з букв і пробілів, але це не прості літери і пропуски, як може здатися на перший погляд. По-перше сама буква i вибрана не випадково. Справа в тому, що буква i сама по собі вузька, за рахунок чого їй легко управляти і підганяти потрібну ширину. По-друге самі прогалини складаються не тільки з символу пробілу, але і з word-spacing, тобто його значення додається до пробілу, що в сумі дає потрібну нам ширину. Так, і звичайно ж, потрібно враховувати, що зв'язка "пробіл + word-spacing" працює тільки тоді, коли в кінці неї йде інший символ, відмінний від пробілу. Так як прогалини мають властивість "схлопування", то букви i, що йдуть після word-spacing не дають їм цього зробити.

Так що, по суті, ми маємо нерозривні псевдоблокі, у вигляді "букви + padding-left" спочатку псевдоелемента, а далі у вигляді зв'язки "пробіл + word-spacing + буква", і так до кінця рядка. Ну, а на наступній сходинці все повторюється заново, тільки перший псевдоблок складається тепер з однієї літери. Але цей рядок нас вже не хвилює, нас цікавлять тільки ті "додаткові блоки", які доповнюють останній рядок з нормальними блоками в сітці.
До речі, букв повинно вистачити, щоб гарантовано заповнити останній рядок до кінця в гіршому випадку. Тобто їх число має дорівнювати максимальному кількістю блоків в рядку.
Так, і, звичайно ж, з text-align: justify цей метод працює точно так само.

Але це були плюси, а як же мінуси? Мінуси у цього варіанту є такими:
По-перше, в нестабільній роботі в Opera, блоки в якій, часом мають нечітке вирівнювання по сітці. Причому це стосується тільки останньої і передостанньої рядків. Не зрозуміло, з-за чого це відбувається, на жаль мені так і не вдалося це з'ясувати. Можливо проблема криється в тому, що крайня буква прилипає до блоку, не чуючи між ними пробілу. У будь-якому випадку, дуже сподіваюся на те, що в коментах хто небудь зможе дати пояснення цієї заковики. Але, в цілому, це не виглядає потворно, тобто працює, але просто трохи нестабільно.

По-друге, через створення додаткових елементів знизу утворюється неприємний відступ, який відбувається за рахунок його розміру шрифту і міжрядкового інтервалу. Ліки у вигляді обнулення шрифту + міжрядкового інтервалу у батька і відновленням їх в нормальний стан у нащадків - не приносить результату, так як потрібна нам рядок в псевдоелементи стає невидима, і наша сітка перестає її відчувати і піддаватися дресируванню.
Але є все ж "майже" вихід із ситуації, це нижній негативний margin, який може підтягнути частину свого "хвоста", дозволяючи таким за ним елементам налазити на нього. Детальніше про це можна почитати тут . Я сказав "майже", бо цей спосіб виручає частково, я б сказав, на половину, може трохи більше. Так як в момент створення, уже двох-сатиричного хвоста, з букв, підтягнути обидві рядки, вже не представляється можливості.

По-третє, щоб змусити цей метод працювати в IE6-7, нам буде потрібно замінити наш псевдоелемент додатковим блоком-помічником, який буде вставлений в кінці списку. Плюс до цього доведеться скористатися такими засобами, як text-justify, text-align-last (їх поведінку я вже описував в цій статті), відновленням властивості zoom в початковий стан, у додаткового блоку і іншими "радостями", завдяки яким, в цих браузерах наш спосіб буде працювати так само. В кінці статті я обов'язково приведу різні варіанти цього завдання, щоб ви могли вибрати потрібний.

резюме

У цій статті ми довели, що блокова сітка не така вже й непідвладна. Як виявилося, це цілком керована конструкція. Мало того, красиве вирівнювання блоків в сітці можна досягти абсолютно звичайним і не важким способом, а результат дозволяє нам легко використовувати його плоди в будь-яких проектах. Що я і роблю, коли надається така можливість.

Так, і звичайно ж, хочеться висловити величезну подяку Іллі Стрельцину ( @ SelenIT2 ) За його ідеї і неймовірну допомогу в матеріалах. Без нього б цієї статті не було.

Всі рішення воєдино

Оновлено 30.03.2017: Сучасне рішення цього завдання на Grid Layout (без хаков і зайвого коду)

PS Це теж може бути цікаво:

Як це працює?
Який же висновок можна з цього зробити?
І як можна пов'язати ці речі з останнім рядком, в якій може бути всього один блок?
Але це були плюси, а як же мінуси?


Новости
  • Виртуальный хостинг

    Виртуальный хостинг. Возможности сервера распределяются в равной мере между всеми... 
    Читать полностью

  • Редизайн сайта

    Редизайн сайта – это полное либо частичное обновление дизайна существующего сайта.... 
    Читать полностью

  • Консалтинг, услуги контент-менеджера

    Сопровождение любых интернет ресурсов;- Знание HTML и CSS- Поиск и обновление контента;-... 
    Читать полностью

  • Трафик из соцсетей

    Сравнительно дешевый способ по сравнению с поисковым и контекстным видами раскрутки... 
    Читать полностью

  • Поисковая оптимизация

    Поисковая оптимизация (англ. search engine optimization, SEO) — поднятие позиций сайта в результатах... 
    Читать полностью