Статьи

Дайте поплавкам щелчок в макетах CSS

Если вы новичок в макетах CSS, вы были бы прощены за то, что думаете, что использование CSS с плавающей точкой творческим путем — это верх навыка. Если вы изучили столько учебников по макету CSS, сколько сможете найти, вы можете предположить, что освоение плавающих элементов — это обряд. Вы будете поражены изобретательностью, поражены сложностью, и вы получите чувство достижения, когда, наконец, поймете, как работают поплавки.

Не обманывайтесь. Тебе промывают мозги.

Знаки опасности

Я заметил это правило в файле сброса CSS:

address, blockquote, center, dir, div, fieldset, pre, dd, dt, frameset,li, h1, h2, h3, h4, h5, h6, dl, ol, ul, form, table { float: left; } 

Это признак того, что автор CSS является последователем единственно верного макета; верующий в магию поплавков. Последователи считают, что они нашли единственную технику верстки, которая им когда-либо понадобится. Повсеместно включенный в CSS-фреймворки, использование одного из них равносильно принятию решения о том, что вам никогда не понадобится изучать другую технику макета CSS.

Правда в том, что использование поплавков для макета было лучшим решением, которое кто-либо мог придумать шесть лет назад с ограниченной поддержкой CSS, доступной в то время. Мы находимся в 2011 году, возможности браузерного CSS еще впереди, а плавающая толпа все еще кодирует CSS, как в 2005 году. Плавающие макеты душат инновации CSS.

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

Ironic Clearfix

Ошибка в плавающих макетах — это необходимость очищать поплавки. Когда у вас есть стек плавающих элементов, они извлекаются из потока документов, и их контейнерный элемент разрушается. Если вы хотите, чтобы этот контейнер правильно окружал свои плавающие дочерние элементы (я называю их плавающими), вам нужно очистить эти плавающие элементы.

Методы для этого различны и зависят от конкретных требований макета. Если у вас есть группа плавающих элементов внутри содержащего элемента, и вам нужно, чтобы этот элемент расширялся на полную высоту, то также перемещайте контейнер. Тем не менее, наиболее популярным методом является применение прозрачного исправления: добавьте элемент, который откажется уступать поплавкам.

Первоначальный clearfix заключался в добавлении блочного элемента после всех плавающих элементов с правилом clear: both; вот так:

 <div></div> 
 .clearfix { clear: both; } 

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

Это высота технологии исправления ошибок:

 .clearfix:before, .clearfix:after { content: "020"; display: block; height: 0; overflow: hidden; } .clearfix:after { clear: both; } .clearfix { zoom: 1; } 

Вы просто добавляете класс clearfix в свой элемент контейнера и позволяете магии случиться. Он настолько прогрессивный, что даже включен в проект HTML5 Boilerplate .

Я нахожу более чем ироничным, что единственные браузеры, которые поддерживают этот метод — которые поддерживают псевдоэлементы :before и :after и генерируемый контент — поддерживают почти все спецификации CSS2.1 (плюс некоторые из спецификаций CSS3) и т. Д. в любом случае, вам не нужны кладжеты, такие как плавающие макеты. Мы говорим о браузерах IE8 и выше.

Настоящая проблема

У нас было десятилетие, когда единственными вариантами компоновки были линейное или блочное отображение, а также плавающее или абсолютное позиционирование. Создание макета — это действительно сочетание множества маленьких простых задач макета. Эти задачи часто делались излишне сложными с использованием поплавков для позиционирования элементов. Изобретательность, необходимая для решения этой введенной сложности, стала эталоном для мастерства CSS.

Почему бы не перестать использовать поплавки и вместо этого убрать сложность?

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

Дисплей: встроенный блок;

Inline-block — это значение для свойства display, которое позволяет последовательно применять такие свойства, как margin s, padding , width , height и vertical-align , оставаясь при этом встроенным элементом. Это невероятно полезно в любой ситуации, когда вы хотите выровнять блочные элементы по горизонтали в строках.

Основой блогов во всем мире является использование неупорядоченного списка для меню навигации. Для поворота этого списка по горизонтали обычно требуется, чтобы вы плавали по всем пунктам меню влево или вправо, а затем имели дело с высотой содержащего элемента и любыми проблемами очистки. Все эти проблемы сводятся к нулю путем применения display: inline-block; ко всем элементам li. Если вы хотите, чтобы якорные элементы заполняли пространство, примените display: block; им.

Вот пример HTML для простого меню:

 <div class="nav"> <ul> <li><a href="home">Home</a></li> <li><a href="about">About</a></li> <li><a href="news">Latest News</a></li> <li><a href="meals">Kitten Meals</a></li> <li><a href="pelts">kitten Pelts</a></li> <li><a href="dioramas">kitten Dioramas</a></li> <li><a href="search">Search</a></li> </ul> </div> 

Далее мы применяем одинаково простой CSS:

 .nav > ul > li { display: inline-block; } .nav > ul > li a:link, .nav > ul > li a:visited { display: block; } 

После добавления некоторых косметических стилей у нас появляется горизонтальное меню:

встроенный блок-нав

Возможно, вы заметили тот факт, что маркер списка больше не виден. Это потому, что элементы списка имеют display значение элемента list-item по умолчанию; изменение display значения также убрало маркер списка.

Элементы inline-block также будут реагировать на свойство vertical-align . Поэтому, если у вас есть элементы разных размеров, вы можете создавать различные эффекты, например:

встроенный блок-NAV2

Верхнее меню использует vertical-align: middle; и нижнее меню использует vertical-align: bottom; ,

Вот еще один пример, который использует inline-block для создания 2D-сетки элементов. Что мне нравится в использовании inline-block таким образом, так это то, что элементы так хорошо переносятся при разной ширине браузера. Еще раз HTML и CSS просты:

 <ul> <li class="product"><img src="..."><p>$5.99kg</p></li> <li class="product"><img src="..."><p>$2.99kg</p></li> <li class="product"><img src="..."><p>$15.99kg</p></li> <li class="product"><img src="..."><p>$3.99kg</p></li> <li class="product"><img src="..."><p>Fresh baked</p></li> <li class="product"><img src="..."><p>Ready to eat</p></li> <li class="product"><img src="..."><p>Taste in store</p></li> <li class="product"><img src="..."><p>Delicious with cranberries</p></li> </ul> 
 li.product { display: inline-block; ... } 

С добавлением некоторых косметических стилей и соответствующей ширины эффект завершается:

встроенный блок-сетка

Если вы используете медиа-запросы, вы можете убедиться, что ширина содержащего элемента установлена ​​на оптимальное значение, чтобы избежать появления сирот в последней строке. Это как укладка плитки. Посмотрите пример в архиве кода, если вы хотите увидеть это в действии.

Inline-block также полезен при представлении формы. Это отличный способ применить одинаковую ширину к вашим labels без использования структурной разметки:

 <fieldset> <legend>Your Details</legend> <label for="name">Full Name:</label><input type="text" value="" /> <label for="address">Address:</label><input type="text" name="address" value="" /> <label for="email">Email:</label><input type="text" name="email" value="" /> </fieldset> 

Применить display: inline-block; к элементу label и input примените соответствующую ширину к элементу fieldset :

 label { display: inline-block; width: 10em; } input[type="text"] { display: inline-block; width: 20em; } fieldset { width: 30em; } 

Результатом является красиво отформатированная форма:

встроенный блок-форма

Если вы применяете display: inline-block; по нескольким элементам fieldset вы можете выровнять их по горизонтали, например так:

встроенный блок-form2

Размер коробки: бордюр

Box-sizing блока на самом деле является свойством CSS3, но поддерживается всеми браузерами, кроме IE6 и 7. box-sizing значение border-box к элементу блока, браузер будет включать ширину отступов и границ в общую ширину элемент; сокращение пространства содержимого в процессе. Именно так работал IE5. Проблема с теперь стандартным способом вычисления ширины элемента — суммы ширины элемента, отступов, ширины границы и поля — состоит в том, что вы не можете указать ширину 100%, а затем применить отступы или границы, потому что это увеличит ширина элемента превышает 100%. Box-sizing: border-box; это ответ.

Вы можете успешно применить ширину 100% к элементу (или ширину двух или более смежных элементов, которые составляют 100%), а также добавить отступы и границы, не беспокоясь о том, что элементы будут расти выше 100%. Очень удобно для жидких макетов.

Важное примечание: в зависимости от версии браузера вам может понадобиться использовать префиксы, специфичные для поставщика, -moz-box-sizing для браузеров на основе Gecko и -webkit-box-sizing для браузеров на основе webkit. Firefox 3.6 и Chrome 10, кажется, поддерживают свойство без префикса поставщика, но Safari 5 все еще нуждается в нем.

Минимальная высота

Вот типичная ситуация расположения: два столбца; один для основного контента и один для дополнительного контента. HTML может выглядеть так:

 <div class="wrapper"> <div class="content"> ... main content here </div> <div class="nav"> ... navigation menu and complementary content here </div> </div> 

Затем мы применяем следующий CSS для упорядочивания столбцов.

 .wrapper { padding: 2em; max-width:  980px; margin: 0 auto; position: relative; min-height: 40em; } .nav { position: absolute; width: 150px; top: 2em; background-color: #FF6A00; } .content { margin-left: 200px; } 

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

Поскольку дополнительный столбец расположен абсолютно, он находится вне потока документов, и элемент контейнера будет свернут до высоты более короткого столбца содержимого. В наше время широко распространенной совместимости для свойства min-height мы можем легко избежать этой проблемы и применить значение min-height к содержащему элементу; достаточно, чтобы убедиться, что он окружает дополнительную колонку.

Вот результат:

позиционно-демо

Если вы хотите, чтобы столбец находился на другой стороне, нет необходимости корректировать разметку, просто настройте значения CSS.

 .nav { position: absolute; width: 150px; top: 2em; right: 2em; background-color: #FF6A00; } .content { margin-right: 200px; } 

Другие CSS-свойства, которые полезны для макета, но которых традиционно избегают, включают position: fixed; max-width , min-width и max-height . Вам следует еще раз взглянуть на эти свойства, поскольку поддержка браузеров в наши дни обширна.

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

Дисплей: стол

С появлением IE8 все браузеры поддерживают связанные с таблицей значения для свойства display . Это позволяет нам применять поведение макета таблиц, строк и ячеек к любым элементам HTML. Для выравнивания по столбцам или строкам эти display значения являются быстрым и простым решением.

Часто происходит быстрое сопротивление всему, что связано с таблицами, упоминаемым на одном дыхании с макетами CSS. На самом деле некоторые веб-профессионалы так возмущены предложением использовать display: table; вы бы подумали, что мы убиваем котят.

Значения display основе таблиц не связаны с использованием HTML-таблиц для разметки. Дебаты приходили и уходили. Теперь они скучные. Давайте двигаться дальше.

Все предыдущие примеры с использованием display: inline-block; также может быть достигнуто с помощью display: table; и связанные ценности. Вот снова наше меню навигации, но на этот раз каждый элемент меню отображается как ячейка таблицы, а не как встроенный блок.

Стол-нав

HTML-код такой же, а CSS-код требует лишь нескольких простых изменений:

 .nav > ul { display: table; border-spacing: 0.25em; } .nav > ul > li { display: table-cell; } 

Вы можете заметить, что нет элемента, играющего роль строки таблицы. В этом нет необходимости: браузеры восстанавливают недостающие части структуры таблицы, используя анонимные элементы. Вы также можете заметить, что, поскольку мы применяем поведение отображения таблицы к элементу ul , мы также можем применять свойства стиля, связанные с таблицей, например, border-spacing .

Наша новая строка меню имеет одно большое отличие в поведении от своего двоюродного брата на основе inline-block . Поскольку он действует как таблица с одной строкой, эти пункты меню больше не переносятся. Вместо этого, если окно браузера становится уже, они объединяются — ширина каждой ячейки будет уменьшаться, как в HTML-таблице. Это стоит иметь в виду при выборе метода макета; иногда вы можете захотеть обернуть элементы, иногда нет. Выбор ваш.

Если мы хотим создать фиксированную, равноудаленную сетку элементов, CSS-таблицы придут на помощь. Это модификация предыдущего примера сетки, за исключением того, что на этот раз нам нужно настроить HTML. Мы будем использовать несколько элементов ul и каждый из них станет строкой таблицы:

 <div class="content"> <ul> <li class="product"><img src="..."><p>$5.99kg</p></li> <li class="product"><img src="..."><p>$2.99kg</p></li> <li class="product"><img src="..."><p>$15.99kg</p></li> <li class="product"><img src="..."><p>$3.99kg</p></li> </ul> <ul> <li class="product"><img src="..."><p>Fresh baked</p></li> <li class="product"><img src="..."><p>Ready to eat</p></li> <li class="product"><img src="..."><p>Taste in store</p></li> <li class="product"><img src="..."><p>Delicious with cranberries</p></li> </ul> </div> 

Вот CSS:

 .content { display: table; border-spacing: 1em; } .content > ul { display: table-row; } li.product { display: table-cell; width:  170px; } 

Вот ваша идеальная сетка:

Таблица сетки

Конечно, легко добиться нашего двухколоночного макета с помощью display: table ;:

 .nav { display: table-cell; width: 150px; padding-right: 50px; } .content { display: table-cell; } 

Столбцы одинаковой высоты, без необходимости указывать значение min-height , с минимумом суеты. Конечно, чтобы отрегулировать положение дополнительного столбца, нам нужно изменить порядок в источнике HTML. Это небольшой недостаток, который вы должны учитывать при выборе display: table; ,

Столбцы одинаковой высоты особенно полезны, если вы хотите включить вертикальные границы между столбцами. Использование display: table; В этой ситуации есть дополнительный бонус: свойство border-collapse . Возьмем, к примеру, обычный нижний колонтитул из трех столбцов, который вы можете найти на сайте на платформе WordPress:

 <ul> <li class="widget-container"> ...footer column content </li> <li class="widget-container"> ...footer column content </li> <li class="widget-container"> ...footer column content </li> </ul> 

Вот конечный результат; столбцы одинаковой высоты с вертикальной границей в один пиксель на столбцах.

Стол-сноска

Еще раз CSS прост:

 .footer { display: table; border-collapse: collapse; width: 100%; } .footer > li { display: table-cell; width: 33.3%; padding: 1em; border-left: 1px solid #FF6A00; border-right: 1px solid #FF6A00; } 

Небольшое предостережение: свойство border-collapse должно быть установлено для элемента, к которому вы добавили display: table; свойство.

Наконец, вот трюк, который CSS таблицы могут выполнять без особых усилий, с которыми борются другие методы: вертикальное выравнивание. Вот чего мы хотим достичь; идеальное центрирование блочного элемента:

Стол-VALIGN

Нам понадобится элемент, который будет таблицей, и элемент, который будет отдельной ячейкой. В этом примере мы html элементы html и body для div элемента div . Остальное легко:

 html { width: 100%; height:  100%; display: table; } body { display: table-cell; vertical-align: middle; } body > div { width: 300px; margin: 0 auto; } 

Разве поплавки не годятся для чего-то?

Защитники плавающего макета быстро указывают на сильные стороны своей техники. Вот часто цитируемые преимущества:

Источник Заказ Независимости

Как я уже упоминал выше, зависимость от порядка исходного HTML-кода для столбцов при использовании display: table; это общая критика. Но я сомневаюсь в том, что плавающие макеты действительно не зависят от порядка источника, верят, что они являются единственным способом достижения независимости порядка источника, и что даже важно, что независимость порядка источника.

Для начала давайте кое-что проясним: чистые CSS-макеты — это просто выдумка. Все текущие методы макета CSS в некоторой степени зависят от потока документов. В CSS отсутствует способ описания макета, полностью независимого от порядка разметки, хотя он может появиться в ближайшем будущем.

Утверждения о независимости порядка источника обычно означают только то, что вы можете изменить порядок столбцов. С простым изменением CSS левый становится правым, а правый становится левым. Верхние и нижние колонтитулы и содержимое внутри столбцов обычно по-прежнему в порядке отображения. Но как часто эта возможность переключения столбцов используется в реальных условиях? Эта возможность возможна только в определенных обстоятельствах, и разметка и CSS должны создаваться с учетом этой способности. Если эта способность действительно требуется по определенной причине, она может стоить всех хлопот. Если вы используете его только для того, чтобы доказать, что это возможно, то стоит ли вся сложность и хрупкость небольшого уменьшения зависимости от порядка источника?

Единственный реальный способ позиционирования элементов без учета исходного порядка — использовать значения position fixed или absolute . Пример макета min-height выше является примером. Также, если вы используете display: inline-block; для горизонтального выравнивания элементов блока можно использовать комбинацию положительных и отрицательных значений margin чтобы визуально изменить порядок элементов без изменения исходного порядка.

Если вы по-прежнему не уверены в том, что проблема с исходным порядком — это красная сельдь, учтите, что, как указывается в этой статье 465 Berea St , в Руководстве по доступности веб-контента четко рекомендуется, чтобы порядок исходного кода HTML соответствовал порядку отображения . Учтите также, что рост HTML5 делает вопрос с исходным кодом спорным вопросом. HTML5 предоставляет явно семантические элементы. Порядок, в котором вы размещаете их в источнике, не влияет на индексацию вашего контента. Элемент article будет содержать содержимое статьи, элемент header будет содержать содержимое заголовка, а элемент aside будет содержать дополнительный контент.

Совместимость браузера

Совместимость с IE 6 и 7 часто используется в качестве ярма для безудержного энтузиазма по поводу новых методов компоновки. Если вы все еще цепляетесь за идею, что одна таблица стилей должна работать везде, во всех браузерах, концепция адаптивного дизайна должна навсегда разрушить это понятие. В любом случае, с таким количеством подключенных к Интернету устройств вам необходимо настроить взаимодействие с этими устройствами.

С выпуском IE9 пришло время выпустить эти старые клокеры на пастбище. Относитесь к IE6 и 7 как к наименее способным мобильным устройствам и используйте условные комментарии для обеспечения минимального опыта. Если вы используете расширенное правило прозрачного исправления, о котором я упоминал в начале этой статьи, но у вас нет альтернативной таблицы стилей для IE6 и 7, вы уже игнорируете проблему совместимости браузера.

Там всегда будут поплавки

Конечно, поплавки полезны в некоторых ситуациях. Всегда будет необходимость плавать элемент так, чтобы вокруг него текло другое содержимое страницы. Просто нет необходимости постоянно вдавливать их в услугу сложного макета.

Это оно?

Вы можете подумать: «Это так? Это кажется очень простым и очевидным ». Я согласен! В этом весь смысл. Плавающая толпа заставит вас поверить, что единственный способ создать продвинутые макеты CSS — это сложные стеки плавающих элементов. Это больше не правда. Теперь у нас есть набор простых в использовании свойств. Объедините некоторые или все вышеперечисленные методы в один макет, и вы сможете делать все, что захотите, без поплавков.

Я смотрю, как мои дети играют в Little Big Planet 2, и вижу, как они создают свои собственные миры с нуля. Я хочу, чтобы они видели сеть таким же образом: как игровая площадка. Когда макеты просты в создании, создание инструментов, генерирующих макеты CSS, также будет простым. Людям больше не нужно кодировать вручную.

Браузеры стали стремительно развиваться со времен старых неудач. Вдохновленные принятием Ajax и теперь HTML5 и CSS3, производители браузеров работают усерднее, чем когда-либо. Мы должны поддерживать этот импульс, максимально использовать новые технологии. Этот опыт дает людям повод обновить свои браузеры, создателям браузеров — продолжать разработку, а создателям инструментов — создавать более совершенные и простые в использовании инструменты. Мы должны исследовать границы, разрабатывать новые методы и загружать эти старые, заветные рецепты макетов за дверь. Они сдерживают нас.

Будущее

CSS3 макет настроен на предоставление гораздо более захватывающих элементов управления макетом. Но нам придется подождать еще несколько лет, прежде чем эти стандарты получат широкую поддержку. Мне кажется, что большой сегмент веб-индустрии стоит на месте, ожидая, пока полностью не поддерживаются стандарты верстки CSS3. Зачем ждать? Гораздо проще методы верстки доступны прямо сейчас.

Весь исходный код для примеров в этой статье доступен на GitHub .

Ни один котенок на самом деле не пострадал при создании этой статьи.