Новости

Кордони не на всю висоту в списку товарів - CSS-LIVE

  1. завдання
  2. світла мрія
  3. сувора дійсність
  4. Старі добрі float'и
  5. Таблиця замість списку
  6. Повторюваний фон кордонів замість псевдоелементів
  7. Універсальне рішення для гумових розмірів
  8. висновок

Останнє оновлення: 27.11.2012.

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

Раз така справа, пропоную познайомитися з цим завданням ближче і разом розібрати всілякі варіанти її вирішення.

завдання

Мова йде про список товарів, пункти якого з деяких боків оточені кордонами. На зображенні нижче це прекрасно видно.

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

світла мрія

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

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

HTML-код буде виглядати просто:

<Ul class = "list"> <li> <div class = "img-block"> <img src = "img1.jpg" /> </ div> <p> HP ProBook Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, </ p> <span class = "price"> $ 1270.99 </ span> </ li> <li> <div class = "img-block"> <img src = "img2.jpg" /> </ div> <p> Toshiba </ p> <span class = "price"> $ 870.99 </ span> </ li> <li> <div class = "img-block" > <img src = "img3.jpg" /> </ div> <p> Asus </ p> <span class = "price"> $ 60.99 </ span> </ li> ....... </ ul>

Нічого зайвого. Простий список з пунктами. Найцікавіше нас чекає в CSS:

* {-Moz-box-sizing: border-box; box-sizing: border-box; padding: 0; margin: 0; } .List {overflow: hidden; margin-left: 3px; margin-top: 2px; display: flex; flex-flow: row wrap; } .List> li {position: relative; padding: 40px 30px; margin-top: -2px; margin-left: -3px; text-align: center; flex: 1 0 33.333%; } .List> li :: after, .list> li :: before {position: absolute; content: ''; } .List> li :: after {top: 20px; bottom: 20px; left: 0px; border-left: 2px dashed # 999; width: 2px; } .List> li :: before {top: 0px; height: 2px; left: 17px; right: 17px; border-top: 2px dashed # 999; } .Img-block {height: 150px;} p {font-size: 17px; margin-bottom: 10px;} .price {color: # F00; font-size: 20px; font-weight: bold; }

А ось і сам результат .

Відразу попереджу вас, що дивитися приклад слід в браузері Opera 12.10+. Для того, щоб не роздувати код зайвими правилами, я використовував останній стандартизований синтаксис Flexbox'ов, який на даний день (25.11.2012) підтримується тільки в Opera.

А тепер давайте розбиратися.

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

* {-Moz-box-sizing: border-box; box-sizing: border-box; padding: 0; margin: 0; }

Так як ширина наших пунктів виставлена ​​в процентах, я вирішив додати їм в стилі box-sizing: border-box, щоб ми могли прописувати їм будь-які кордони або відступи, і при цьому не боячись, що наша верстка поїде. Взагалі, треба зауважити, що саме по собі box-sizing дуже корисна властивість, яке, на мій погляд, варто застосовувати в більшості завдань. обов'язково почитайте про нього.

Ну, а тепер включаємо flexbox'и:

.list {overflow: hidden; margin-left: 3px; margin-top: 2px; display: flex; flex-flow: row wrap; }

Три верхніх оголошення ми розберемо трохи пізніше, а ось двох останніх торкнемося саме зараз.

Рядком display: flex ми говоримо елементу <ul>, щоб він став flexbox'ом. А оголошення flex-flow: row wrap передає дочірнім елементам (в нашому випадку всім <li>), щоб вони йшли в ряд і могли переноситися на наступний рядок, якщо їх сумарна ширина перевищить батьківську.

Далі йдуть самі пункти:

.list> li {position: relative; padding: 40px 30px; margin-top: -2px; margin-left: -3px; text-align: center; flex: 1 0 33.333%; }

Як і в попередньому випадку, залишимо кілька оголошень на потім і обговоримо останнім.

Якщо контент пунктів не зможе вміститися в зазначену ширину (одну третину), то вони перенесуться на наступний рядок, автоматично вирулювавши спочатку по два в ряд, а потім і зовсім по одному. При цьому, завдяки першому параметру у flex (рівносильному окремому властивості flex-grow: 1), вони збільшать свою ширину на рівну частку залишився в рядку вільного місця. Другий параметр (еквівалентний flex-shrink: 0) гарантує, що ширина боксів не стане менше бажаної.

До речі, якщо захочете, ви можете обмежити ширину пунктів. У цьому прикладі я спеціально не став цього робити, щоб продемонструвати більш універсальне рішення і міць Flexbox'ов.

На додаток до всього, завдяки корисним властивостям Flexbox'a висота пунктів повинна підлаштовуватися під висоту контейнера, що буде для нас безсумнівним плюсом.

Пора переходити до кордонів:

.list> li: after, .list> li: before {position: absolute; content: ''; } .List> li: after {top: 20px; bottom: 20px; left: 0px; border-left: 2px dashed # 999; width: 2px; } .List> li: before {top: 0px; height: 2px; left: 17px; right: 17px; border-top: 2px dashed # 999; }

Я вирішив, що раз в нашому випадку пункти безпроблемно розтягуються по ширині і висоті, то ми цілком можемо скористатися цим, застосувавши до них пару псевдоелементів. Як ви вже здогадалися, псевдоелементи будуть абсолютно позиціонувати межами. : After відповідатиме за праву межу, а: before за верхню. За допомогою потрібних координат ці псевдо кордону будуть починатися і закінчуватися там, де нам потрібно. : After, наприклад, в 20px від низу і верху.

А тепер згадаємо ті оголошення, які ми розгубили по дорозі.

Так як лівих меж не повинно бути видно, мені довелося трохи відсунути пункти вліво і вгору за допомогою негативних margin'ов, щоб та їх частина, в якій знаходяться псевдограніци - пішла за межі контейнера. А щоб кордони взагалі зникли з поля зору, я і повісив на <ul> overflow: hidden, обрізавши їх повністю.

Ось таке ось власне просте рішення можна створити завдяки Flexbox'ам.

сувора дійсність

Помріяли? Досить. А тепер повернемося до суворої дійсності і згадаємо, що не всі браузери, під які нам доводиться робити верстку, підтримують світлі технології. Мова йде про IE9 і нижче. Тому далі ми розберемо рішення, які більш наближені до реальності.

Почнемо з фіксованих рішень, де пункти будуть володіти точною шириною і висотою.

Старі добрі float'и

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

Код, який буде повторюватися, я писати не буду, щоб не плодити зайвого.

Це рішення засноване на все тих же псевдоелементи і списку. Тому змін особливих немає, тільки лише трохи в CSS:

.list {width: 625px; overflow: hidden; margin: auto; } .List> li {position: relative; padding: 40px 30px; margin-top: -2px; margin-left: -3px; text-align: center; width: 210px; height: 280px; float: left; }

Як можна помітити, я прибрав всі записи относяіщеся до flexbox'ам і привласнив списку ширину, а пунктам задав загальні розміри і float: left, щоб вони притискалися один до одного. Ось що у нас вийшло таким чином. Цілком собі нічого, правда? І працює всюди, починаючи з IE8 :)

Таблиця замість списку

При необхідності, ми можемо замінити список таблицею , Але тоді нам доведеться робити в осередках зайвий контейнер через бородатої проблеми з позиціонуванням в осередках таблиці в Firefox .

Повторюваний фон кордонів замість псевдоелементів

Ще один варіант з фіксованими розмірами полягає у відмові від псевдоелементів на користь звичайного повторюваного фону, який представлений на малюнку нижче.

Що ми поміняли в коді на цей раз? Та власне зовсім небагато:

.list {width: 630px; overflow: hidden; margin: auto; background: -40px -50px url (bg.gif); } .List> li {width: 210px; height: 310px; padding: 40px 30px 0; text-align: center; float: left; margin-bottom: -6px; }

З коду пропали псевдоелементи, але зате з'явився фон і негативний margin. Фон я встановив на елемент <ul>, а margin на елементи <li>. Я не став заморочуватися з розмірами пунктів, а просто налаштував їх так, щоб їх межі збігалися з повторюваним фоном. Чесно кажучи, можна було б зробити красивіше, пограти з зображенням в фотошопі і з кодом, але я залишу це вам, тим більше, що проект проекту ворожнечу, а значить і зображення кожен буде підбирати під свої завдання.

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

Універсальне рішення для гумових розмірів

Як ви вважаєте, чи настав час повторити подвиг Flexbox'ов? Думаю що так. Але відразу хочу попередити, що, на жаль, на даний день в арсеналі CSS2.1 не існує рішення зробити висоту наших пунктів автоматичної і при цьому підбудовується під висоту найвищого пункту в рядку. Тому моє рішення буде, по-перше, скидатися в сторону хардкору, а по-друге, має обмеження, трохи пізніше ви зрозумієте, яке.

У HTML-коді відбулися кардинальні зміни. Я прибрав список, замінивши його на <div> 'и, і тепер код HTML виглядає так:

<Div class = "line"> <div class = "line__inner"> <div class = "item"> <div class = "img-block"> <img src = "img1.jpg" /> </ div> < p> Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, </ p> <span class = "price"> $ 1270.99 </ span> </ div> <div class = "item"> <div class = "img- block "> <img src =" img2.jpg "/> </ div> <p> Toshiba </ p> <span class =" price "> $ 870.99 </ span> </ div> <div class =" item " > <div class = "img-block"> <img src = "img3.jpg" /> </ div> <p> Asus </ p> <span class = "price"> $ 60.99 </ span> </ div > </ div> </ div> .....

Це приклад одного ряду. Тепер, для пунктів я використовую пару контейнерів (.line і .line__inner). Ми повернемося до цього моменту пізніше, т.к для початку варто поглянути на CSS, в якому теж відбулися зміни.

* {-Moz-box-sizing: border-box; box-sizing: border-box; padding: 0; margin: 0; } .Line {width: 90%; overflow: hidden; margin: 20px auto; min-width: 650px; } .Line__inner {position: relative; padding: 20px 0; white-space: nowrap; } .Item {width: 33.3333%; display: inline-block; position: relative; vertical-align: top; white-space: normal; text-align: center; padding: 0 30px; margin-left: -3px; } .Line: first-child {margin-top: 0;} .line: first-child .item: after {display: none; margin-top: 0;} .item: after, .item: before {position: absolute; content: ''; } .Item: after {top: -20px; height: 2px; left: 20px; border-top: 2px dashed # 999; right: 20px} .item: before {top: 0px; height: 5000px; left: 0px; border-left: 2px dashed # 999; width: 2px; }

А тепер давайте розбиратися. Загалом, я вирішив скористатися одним зі старих трюків з емуляцією колонок однакової висоти. Якщо прибрати все зайве, то можна побачити , В чому полягає це рішення. Все дуже просто. Кожен псевдоелемент (в нашому випадку: before) знаходиться в своєму пункті і розтягується по висоті на те значення, якого точно вистачило б для колонки будь-якої висоти. Так як псевдоелемент абсолютно позиціонується, то його розміри ніколи не розтягнутий контейнер, тому що елемент відсутній в потоці. Але при цьому, завдяки величезній висоті, псевдоелемент легко розтягується на всю висоту контейнера (а за фактом перевищує її), який в свою чергу вміщує все знаходяться в ньому колонки, розтягуючись по висоті найдовшою. Таким чином за допомогою overflow: hidden у батьківського блоку ми легко можемо обрізати все зайве і привести все псевдоколонкі до однаковій висоті.

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

Так, у цього способу є і обмеження, про який я писав вище. Пункти не повинні переноситися на наступний ряд, тому що в цьому випадку ми не зможемо обрізати псевдоелементи і завдання не виконається. Тому я замінив плаваючий механізм на рядково-блоковий (inline-block). Це було необхідно для перестраховки, щоб зовні я міг виставити батьківського контейнеру white-space: nowrap, знаючи, що при будь-якій ширині всі мої пункти не зможуть випадково перескочити на наступний рядок. Відповідно, у самих пунктів я повернув white-space в значення normal, щоб елементи всередині них вели себе добре :)

В іншому, я думаю, з коду все досить очевидно. Єдине, на що варто звернути увагу, це на додатковий контейнер у батьківського блоку (.line__inner). Без нього мені не вдалося обійтися. Справа в тому, що, тому що висота псевдоелемента обрізається самим контейнером, то з'їсти рибку і не обляпати домогтися потрібних відступів знизу і зверху не вийде (upd: получіловь все ж. Дякуємо gordi ). Але за допомогою додаткового контейнера ця задача вирішується простими padding'амі.

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

Це рішення прекрасно поводиться в будь-якому браузері, починаючи з IE8 +, але якщо вам раптом необхідно налагодити його роботу в IE7, то доведеться замінити псевдоелементи на ... допустимо <span> 'и, а inline-block'і на відомі хакі.

висновок

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

(27.11.2012) У коментарях, один добрий чоловік ( gordi ) Поліпшив останнє рішення, позбувшись від зайвої контейнера (.Line__inner).

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

Бачите сірі пунктирні лінії?
Думаю, всі вже зрозуміли, що від нас вимагається?
Подумайте, як би ви тоді вирішували це завдання?
Цілком собі нічого, правда?
Що ми поміняли в коді на цей раз?
Але чому б не замінити їх на межі, використавши той же прийом?

Уважаемые партнеры, если Вас заинтересовала наша продукция, мы готовы с Вами сотрудничать. Вам необходимо заполнить эту форму и отправить нам. Наши менеджеры в оперативном режиме обработают Вашу заявку, свяжутся с Вами и ответят на все интересующее Вас вопросы.

Или позвоните нам по телефонам: (048) 823-25-64

Организация (обязательно) *

Адрес доставки

Объем

Как с вами связаться:

Имя

Телефон (обязательно) *

Мобильный телефон

Ваш E-Mail

Дополнительная информация: