Панель закладок средствами CSS3.

Перевод статьи:  CSS3 Tabs
Автор:  Chris Coyier.

В ходе создания панели закладок, разработчики, прежде всего, думают о написании соответствующего JavaScript кода, который работает по обычному сценарию:

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

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

Панель закладок.

Панель закладок.

Селектор псевдокласса :target.

В нашем случае основная концепция реализации такого подхода опирается на функционал CSS псевдоселектора :target, который используется в связке с селекторами идентификаторов элементов — #id. Полученный в результате сложный селектор будет работать в том случае, если в указанном URL адресе присутствует идентичное значение ID c предшествующим символом решетки # (*анкор). То есть, если применяемый URL выглядит примерно вот так:

http://css-tricks.com/#element-id

и на странице присутствует элемент с соответствующим идентификатором id="element-id"

<h1 id="element-id">header text</h1>

то этому элементу будет соответствовать следующий селектор:

#element-id:target {color: red;}

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

<a href="#element-id">Link text</a>

Поддержка CSS3 браузерами.

Обычно руководство, подобное этому заканчивается кратким перечислением браузеров поддерживающих и не поддерживающих рассмотренный в нем прием. Но в данном конкретном случае, необходимо более детально рассмотреть этот вопрос. Дело в том, что псевдокласс :target представлен последним, третьим уровнем спецификации — CSS3 и все настоящие версии популярных браузеров обеспечивают его полную поддержку. Я, конечно же как и большинство других разработчиков, придерживаюсь точки зрения, требующей прекращения поддержки браузера IE6, и поэтому особо не переживаю о том, будет ли работать описанный выше метод в этом браузере (а он работать не будет). Но основная проблема заключается в том, что псевдокласс :target не поддерживается и в двух последующих, седьмой и восьмой версиях IE. То есть применительно к этим браузерам данное пособие можно отнести, скорее всего, к категории познавательных случаев веб-разработки, используемых исключительно в методических целях, чем к руководству по практическому использованию CSS приемов в рамках проектов масштабного использования.

Поэтому если вы действительно хотите использовать данный прием в ходе создания сайта, предназначенного для широкой аудитории, то вам необходимо воспользоваться условными комментариями, позволяющими подключать необходимый JavaScript код, который реализует панель закладок в случае, если посетитель вашего сайта пользуется ранними версиями IE. Но в данной статье этот вопрос не рассматривается.

HTML код.

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

<div class="tabbed-area">

<ul class="tabs group">
<li><a href="#box-one">Tab 1</a></li>
<li><a href="#box-two">Tab 2</a></li>
<li><a href="#box-three">Tab 3</a></li>
</ul>

<div class="box-wrap">

<div id="box-one">
<!–– box one content ––>
</div>

<div id="box-two">
<!–– box two content ––>
</div>

<div id="box-three">
<!–– box three content ––>
</div>

</div>

</div>

Даже в таком «сыром» виде без подключения CSS кода, вы увидите список ссылок, при щелчке по каждой из которых, область видимости документа будет смещаться вниз к соответствующему блоку с содержимым закладки.

CSS

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

.tabs { list-style: none; }
.tabs li { display: inline; }
.tabs li a { color: black; float: left; display: block; padding: 4px 10px;
margin-left: -1px; position: relative; left: 1px;
background: white; text-decoration: none; }
.tabs li a:hover { background: #ccc; }

Устанавливая путем определения свойства float: left смещение ссылок влево, мы нарушаем визуальную структуру, предусмотренную их родительским элементом <li>, для которого нет необходимости определять известный нам класс clearfix. Его мы применим для родительского блока <ul>, что позволит установить стандартное значение высоты ярлыков закладок.

.group:after { visibility: hidden; display: block; font-size: 0; content: "  ";
clear: both; height: 0; }

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

Ну а теперь займемся элементарным оформлением панелей. В нашем случае используется один общий контейнер div для всех имеющихся панелей. Это сделано для того, чтобы задав для блока-контейнера относительное позиционирование, мы смогли в его контексте абсолютно позиционировать внутренние панели, которые будут одной высоты и ширины, а их верхние границы располагаются на одном уровне. Кроме того, соседние границы панелей и ярлыков совпадают и имеют ширину 1px.

.box-wrap { position: relative; min-height: 250px; }
.tabbed-area div div { background: white; padding: 20px; min-height: 250px;
position: absolute; top: -1px; left: 0; width: 100%; }
.tabbed-area div div, .tabs li a { border: 1px solid #ccc; }

И последний штрих, «оживляющий» созданную нами структуру из трех панелей. Он очень прост и основан на манипуляции значениями свойства z-index панелей в момент их выбора пользователем (то есть когда они будут соответствовать псевдоклассу :target).

#box-one:target, #box-two:target, #box-three:target { z-index: 1; }

А как же визуальное выделение активного ярлыка.

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

Решение именно этого вопроса и является в нашем случае самым проблемным. Хотя я и нашел выход из ситуации, но он, к сожалению, является не самым лучшим, так как имеет ряд недостатков. Проблема заключается в том, что пользуясь исключительно средствами CSS, мы не можем, перемещаясь по каскадной структуре CSS кода выбирать элементы, стоящие выше по иерархии. Поэтому, если мы хотим иметь доступ к форматированию ярлыков соответствующих панелей, то единственным выходом в нашем случае будет вложение указателя на требуемый ярлык <a> внутрь общего селектора CSS правила. Вот пример:

#box-four:target a[href="#box-four"] { color: red; }

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

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

<div class="box-wrap">

<div id="box-four">
<!–– content for panel ––>

<ul class="tabs group">
<li class="cur"><a href="#box-four">Tab 4</a></li>
<li><a href="#box-five">Tab 5</a></li>
<li><a href="#box-six">Tab 6</a></li>
</ul>
</div>

<div id="box-five">
<!–– content for panel ––>

<ul class="tabs group">
<li><a href="#box-four">Tab 4</a></li>
<li class="cur"><a href="#box-five">Tab 5</a></li>
<li><a href="#box-six">Tab 6</a></li>
</ul>
</div>

<div id="box-six">
<!–– content for panel ––>

<ul class="tabs group">
<li><a href="#box-four">Tab 4</a></li>
<li><a href="#box-five">Tab 5</a></li>
<li class="cur"><a href="#box-six">Tab 6</a></li>
</ul>
</div>

</div>

Это, конечно же, не идеальный вариант, но в такой структуре кода элементы, используемые для представления ярлыков <li>, находятся внутри блоков панелей <div>, что позволяет нам определить класс "current" для той ссылки, которая соответствует нужной панели и применить к ней требуемое форматирование. Используя приведенный ниже CSS код, мы добиваемся правильного позиционирования панелей и ярлыков – ярлык, так же как и соответствующая ему панель с контентом, отображаются в верхнем слое документа, и являются видимыми для пользователя.

.cur-nav-fix .tabs { position: absolute; bottom: 100%; left: -1px; }
.cur-nav-fix .tabs li a {
background: -webkit-linear-gradient(top, white, #eee);
background: -moz-linear-gradient(top, white, #eee);
background: -ms-linear-gradient(top, white, #eee);
background: -o-linear-gradient(top, white, #eee);
}
#box-four { z-index: 1; }
#box-four:target .tabs, #box-five:target .tabs,
#box-six:target .tabs { z-index: 3; }
.cur-nav-fix .tabs li.cur a { border-bottom: 1px solid white;
background: white; }
Панель закладок с соответствующим оформлением.

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

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

Демо-страница.

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

Неприятные моменты.

Побывав на демо-странице, вы, вероятно, заметили, что если щелкнуть сначала по какому-нибудь из ярлыков одной панели, а затем задействовать ярлык другой панели закладок (левее или ниже), то после второго щелчка, первая панель будет сброшена в состояние, устанавливаемое по умолчанию, вместо того, чтобы сохранять установленное пользователем текущее состояние. Причина такого поведения кроется в псевдоселекторе :target и его взаимосвязи с используемым в качестве якоря идентификатором элемента #id в URL ссылки. По правде говоря, полноценное решение этой проблемы все-таки требует вмешательства кода JavaScript. Поэтому, если вас не устраивает предлагаемый вариант, то вам необходимо воспользоваться соответствующим скриптом.

Еще один недостаток использования якорных элементов в реализации панелей закладок – это постоянные смещения окна браузера при щелчке по определенному ярлыку. Это связано с тем, что браузер автоматически выводит на самую верхнюю позицию окна ту закладку, которой соответствует используемый в задействованном ярлыке якорь (*Идентификатор с решеткой в URL — #id.). Это, конечно, происходит лишь в том случае, если документ содержит достаточно контента для прокрутки окна браузера вниз. Опять же, для решения этой проблемы без использования JavaScript кода не обойтись.

*Соглашусь с одним из разработчиков, оставивших совой комментарий к оригиналу статьи, который называет данный способ реализации панели закладок несовершенным. Причин несколько, но основная из них заключается в том, что пользуясь таким образом разработанной страницей и переключаясь на содержание нескольких закладок, пользователь, при желании вернуться на предыдущую страницу, после нажатия соответствующей кнопки истории просмотра браузера («На предыдущую страницу»), будет последовательно наблюдать содержание активированных ранее закладок, а не предшествующую страницу. И учитывая все упомянутые выше недостатки, этот способ можно, всё-таки, отнести к категории «познавательных случаев» использования CSS, а не рекомендовать его к использованию в рамках реального веб-проекта.

* Примечание переводчика.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *