Как стать автором
Обновить

Вкладки с внешними скруглениями

Разработка веб-сайтов *
Перевод
Автор оригинала: Chris Coyier
Скругленные уголки на сегодняшний день делаются тривиально с помощью border-radius. Благодаря border-radius мы можем «обрезать» блоки сообразно необходимости, но что делать, если нам нужно скруглить «внешний» угол? Проблему проще пояснить графически:

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


Чистый HTML


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

<ul class="tabs group">
  <li class="active"><a href="#one">One</a></li>
  <li><a href="#two">Two</a></li>
  <li><a href="#three">Three</a></li>
  <li><a href="#three">Four</a></li>
</ul>

Имя класса «active» обозначает активную вкладку.

Как это работает


Причина того, почему это сложно заключается в том, что нам нужно получить форму выходящую за пределы начального блока. Что бы этого достичь без дополнительной разметки мы импользуем псевдоэлементы. Если вам нужно освежить память по поводу того, что это за элементы такие, вы можете это сделав прочитав эту и эту статейки. Непосредственно через css мы можем добавлять дополнительные стилизируемые элементы на страницу. Каждый элемент может генерировать два дополнительных с помощью псевдоселекторов :before и :after. Для каждой вкладки мы будем использовать четыре. Это возможно засчет того, что каждая вкладка состоит из двух элементов: элемента списка и якоря.

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

1) Начальное состояние
imageЭлементы списка обычно является блочным элементом, а якорь — строчным. Так что мы получаем вот такой лаяут.

2) Выстраиваем в один ряд
imageПрисвоив элементам списка float:left мы выстроим их в один ряд и укоротим до ширины якоря внутри. Фактически — до ширины контента.

3) Приводим к одинаковому размеру
imageСами по себе элементы списка не обладает отступами или полями (margin или padding), так что элементы списка и якоря вложенные в них обладают одинаковыми размерами.

4) Рассмотрим одну вкладку
imageДавайте внимательно рассмотрим одну вкладку

5) Окружности
imageМы используем два из четырех псевдоэлементов, что бы расположить окружности слева и справа у нижней грани вкладки.

6) Прямоугольники
imageC помощью оставшихся двух псевдоэлементов мы создадим меньшие прямоугольники.

7) Раскрасим вкладку и содержимое
imageУ активной вкладки и содержимого общий цвет фона.

8) Раскрашиваем псевдоэлементы
imageПрямоугольники соответствуют цвету активной вкладки, окружности соответствуют цвету фона за ними.

9) Перекрытие элементов
imageC помощью z-index мы обеспечиваем перекрытие прямоугольников окружностями.

10) Без рамки
imageРамка была просто на иллюстрации, на самом деле оно будет выглядеть где то так.

11) Заканчиваем
imageПрименяем тот же принцип для внешних вкладок и скругляем верхние уголки с помощью border-radius. Готово.

CSS


А это — огромный CSS блок, но я его подробно комментировал, что бы он был понятен.
.tabs li {
  /* Выстраиваем табы в полоску */
  float: left; 

  /* Что бы псевдоэлементы можно было абсолютно позиционировать в табах */
  position: relative;
}
.tabs a {
  /* Делаем якорь блочным элементом и укорачиваем до размера контента*/
  float: left;
  padding: 10px 40px;
  text-decoration: none;

  /* Цвета по умолчанию */
  color: black;
  background: #ddc385; 

  /* Скругляем верхние уголки */
  -webkit-border-top-left-radius: 15px;
  -webkit-border-top-right-radius: 15px;
  -moz-border-radius-topleft: 15px;
  -moz-border-radius-topright: 15px;
  border-top-left-radius: 15px;
  border-top-right-radius: 15px;
}
.tabs .active {
  /* Активную вкладку помещаем поверх остальных */
  z-index: 3;
}
.tabs .active a {
  /* Цвета активной вкладке */
  background: white;
  color: black;
}
.tabs li:before, .tabs li:after,
.tabs li a:before, .tabs li a:after {
  /* Все псевдоэлементы абсолютно позиционированы относительно нижней грани*/
  position: absolute;
  bottom: 0;
}
/* Только первая, последная и активная вкладка создают псевдоэлементы, остальным они не нужны*/
.tabs li:last-child:after,   .tabs li:last-child a:after,
.tabs li:first-child:before, .tabs li:first-child a:before,
.tabs .active:after,   .tabs .active:before,
.tabs .active a:after, .tabs .active a:before {
  content: "";
}
.tabs .active:before, .tabs .active:after {
  background: white; 

  /* Прямоугольники под окружностями */
  z-index: 1;
}
/* Прямоугольники */
.tabs li:before, .tabs li:after {
  background: #ddc385;
  width: 10px;
  height: 10px;
}
.tabs li:before {
  left: -10px;
}
.tabs li:after {
  right: -10px;
}
/* Окружности */
.tabs li a:after, .tabs li a:before {
  width: 20px;
  height: 20px;
  /* Окружности … э … крууугггглыыыыыеееее */
  -webkit-border-radius: 10px;
  -moz-border-radius:    10px;
  border-radius:         10px;
  background: #222;

  /* Окружности над прямоугольниками */
  z-index: 2;
}
.tabs .active a:after, .tabs .active a:before {
  background: #ddc385;
}
/* Первая и последняя вкладки обладают разными фоновыми цветами у внешних элементов*/
.tabs li:first-child.active a:before,
.tabs li:last-child.active a:after {
  background: #222;
}
.tabs li a:before {
  left: -20px;
}
.tabs li a:after {
  right: -20px;
}


Вот и все!



Будет работать во всех современных браузерах включая IE9 и выше. В более старых браузерах деградирует (не будет скругленных уголочков).

Улучшаем мягкую деградацию


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



Дополнительный CSS:

<style>
 /*Скругленные уголки вверху вкладок*/

/*ie 7*/
*+html .tabs li{
background: url("img/tabs.png") 0 -37px no-repeat;
}

*+html .tabs li a{
background: url("img/tabs.png") 100% -37px no-repeat;
padding: 10px 40px 10px 20px;
margin:0 0 0 20px;
}

*+html .tabs li.active{
background:url("img/tabs.png") 0 0 no-repeat;
}

*+html .tabs li.active a{
background:url("img/tabs.png") 100% 0 no-repeat;
}

*+html .tabs li{
zoom:expression(function(t) {
t.runtimeStyle.zoom = 1;
var before = document.createElement('span');
var after = document.createElement('span');

before.className = 'before-fix-for-ie';
after.className = 'after-fix-for-ie';

t.appendChild(before);
t.appendChild(after);
}(this));
}

/*ie 6*/		
* html .tabs li{
background:url("img/tabs.png") 0 -37px no-repeat;
}

* html .tabs li a{
background:url("img/tabs.png") 100% -37px no-repeat;
padding: 10px 40px 10px 20px;
margin:0 0 0 20px;
}

* html .tabs li.active{
background-position:0 0;
}

* html .tabs li.active a{
background:url("img/tabs.png") 100% 0 no-repeat;
}

* html .tabs li{
zoom:expression(function(t) {
t.runtimeStyle.zoom = 1;
var before = document.createElement('span');
var after = document.createElement('span');

before.className = 'before-fix-for-ie';
after.className = 'after-fix-for-ie';

t.appendChild(before);
t.appendChild(after);
}(this));
}

/*Внешние скругления*/
.tabs li .before-fix-for-ie{
position:absolute;
overflow:hidden;
font-size:0;
line-height:0;
top:27px;
left:-10px;
width:10px;
height:10px;
background:url("img/left.png") 0 0 no-repeat;
}
* html .tabs li .before-fix-for-ie{
background:none;
filter: progid:DXImageTransform.Microsoft.AlphaImageLoader( src='img/left.png', sizingMethod='image');
}

.tabs li.active .before-fix-for-ie{
background:url("img/active-left.png") 0 0 no-repeat;
}
* html .tabs li.active .before-fix-for-ie{
background:none;
filter: progid:DXImageTransform.Microsoft.AlphaImageLoader( src='img/active-left.png', sizingMethod='image');
}

.after-fix-for-ie{
position:absolute;
overflow:hidden;
font-size:0;
line-height:0;
top:27px;
right:-10px;
width:10px;
height:10px;
background:url("img/right.png") 0 0 no-repeat;
}
* html .tabs li .after-fix-for-ie{
background:none;
filter: progid:DXImageTransform.Microsoft.AlphaImageLoader( src='img/right.png', sizingMethod='image');
}

.tabs li.active .after-fix-for-ie{
background:url("img/active-right.png") 0 0 no-repeat;
}
* html .tabs li.active .after-fix-for-ie{
background:none;
filter: progid:DXImageTransform.Microsoft.AlphaImageLoader( src='img/active-right.png', sizingMethod='image');
}

</style>


<!--[if IE 8]>
<style>
/*ie 8*/
.tabs li{
background:transparent url("img/tabs.png") 0 -37px no-repeat;
}

.tabs li a{
background:transparent url("img/tabs.png") 100% -37px no-repeat;
padding: 10px 40px 10px 20px;
margin:0 0 0 20px;
}

.tabs li.active{
background:transparent url("img/tabs.png") 0 0 no-repeat;
}

.tabs li.active a{
background:transparent url("img/tabs.png") 100% 0 no-repeat;
}

body .tabs li:before{
content:".";
text-indent:-9000px;
overflow:hidden;
height:10px;
width:10px;
font-size:0;
line-height:0;
display:block;
position:absolute;
top:27px;
left:-10px;
z-index:10;
zoom:1;
background:transparent url("img/left.png") 0 0 no-repeat;
}

body .tabs li:after{
content:".";
text-indent:-9000px;
overflow:hidden;
height:10px;
width:10px;
font-size:0;
line-height:0;
display:block;
position:absolute;
top:27px;
right:-10px;
z-index:10;
zoom:1;
background:transparent url("img/right.png") 0 0 no-repeat;
}

body .tabs li.active:before{
content:".";
text-indent:-9000px;
overflow:hidden;
height:10px;
width:10px;
font-size:0;
line-height:0;
display:block;
position:absolute;
top:27px;
left:-10px;
z-index:10;
zoom:1;
background:transparent url("img/active-left.png") 0 0 no-repeat;
}

body .tabs li.active:after{
content:".";
text-indent:-9000px;
overflow:hidden;
height:10px;
width:10px;
font-size:0;
line-height:0;
display:block;
position:absolute;
top:27px;
right:-10px;
z-index:10;
zoom:1;
background:transparent url("img/active-right.png") 0 0 no-repeat;
}
</style>
<![endif]-->


Для ie8 пришлось вынести CSS в отдельный блок, выделенный условными комментариями, так как мне не удалось найти хака, который бы работал для ie8 и не работали бы для ie9. Если кто то знает такой — пожалуйста, поделитесь.

Я не видел необходимости вдаваться в подробности, но если есть необходимость, то я охотно поясню любой момент, который может вызвать вопросы.

Надеюсь дополнение будет полезно.
Теги:
Хабы:
Всего голосов 195: ↑177 и ↓18 +159
Просмотры 10K
Комментарии Комментарии 104