...

четверг, 6 марта 2014 г.

Магический круг: CSS головоломка

Доброго времени суток, уважаемые хабравчане. Недавно Hugo Giraudel, он же CSS гоблин, SASS хакер и Margin псих опубликовал в своем блоге очень интересную CSS задачку на смышленость.

image


Сможете заверстать подобное учитывая следующие правила?



  • Окружность в центре должна быть прозрачной, чтобы был виден background

  • Расстояние между левыми и правыми блоками, как между верхними и нижними должно быть одинаковое

  • При наличии потомков в блоке, содержимое должно отобраться

  • DOM должен выглядеть следующим образом: ul > li > section > header + footer

  • Нельзя использовать JavaScript и изображения

  • Дополню еще от себя: нельзя использовать CSS Shape и Clip Path




Чтобы не было очень лень — каркас уже есть.

Сделали?




Базовый HTML:



<ul class="boxes">

<li class="box box-alpha">
<section class="box-content">
<header class="box-header"></header>
<footer class="box-footer"></footer>
</section>
</li>

<li class="box box-beta">
<section class="box-content">
<header class="box-header"></header>
<footer class="box-footer"></footer>
</section>
</li>

<li class="box box-gamma">
<section class="box-content">
<header class="box-header"></header>
<footer class="box-footer"></footer>
</section>
</li>

<li class="box box-delta">
<section class="box-content">
<header class="box-header"></header>
<footer class="box-footer"></footer>
</section>
</li>
</ul>


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



.boxes:after {
background: none repeat scroll 0 0 #34495E;
border: 0.5em solid #2C3D50;
border-radius: 50%;
content: " ";
height: 5.5em;
left: 50%;
margin-left: -2.75em;
position: absolute;
top: 10.75em;
width: 5.5em;
}




Первый способ: радиальный градиент




Необходимо задать правильные радиальные градиенты с цветом и прозрачностью всем footer элементам для верхних блоков и всех header элементам для нижних блоков. На первый взгляд это самый тривиальный способ решения, но в нем есть изюменка, которая заключается в использовании CSS calc() для придания отзывчивости:

.box-alpha .box-footer {
background: radial-gradient(circle at calc(100% + 2em) 7em , rgba(0, 0, 0, 0) 6em, #148F77 6em) repeat scroll 0 0 rgba(0, 0, 0, 0);
}
.box-beta .box-footer {
background: radial-gradient(circle at -2em 7em , rgba(0, 0, 0, 0) 6em, #25A25A 6em) repeat scroll 0 0 rgba(0, 0, 0, 0);
}
.box-gamma .box-header {
background: radial-gradient(circle at calc(100% + 2em) -2em , rgba(0, 0, 0, 0) 6em, #217DBB 6em) repeat scroll 0 0 rgba(0, 0, 0, 0);
}
.box-delta .box-header {
background: radial-gradient(circle at -2em -2em , rgba(0, 0, 0, 0) 6em, #804399 6em) repeat scroll 0 0 rgba(0, 0, 0, 0);
}


Второй способ: рамка для псевдо-элементов




Я думаю, это — самый изобретательный способ решения. Для элементов header и footer в соответствии для каждого из блоков задаем margin в нужную сторону. После чего для каждый секции и header с footer создаем псевдо-элементы:

.box-alpha .box-content:before {
border-color: #148F77 rgba(0, 0, 0, 0) rgba(0, 0, 0, 0) #148F77;
bottom: -7.5em;
right: -7.5em;
}
.box-content:before {
border: 10em solid #FF0000;
content: "";
display: block;
height: 0;
position: absolute;
width: 0;
}
.box-alpha .box-content:after {
border-color: #148F77;
bottom: -10em;
right: -10em;
}
.box-content:after {
border: 2em solid #FF0000;
border-radius: 30em;
content: "";
display: block;
height: 12em;
position: absolute;
width: 12em;
z-index: 0;
}

...




Общаем внимание на :before для .box-alpha, у которого нет ширины или высоты. Вспоминаем как мы все привыкли делать «стрелочки» или треугольники на CSS с помощью border. Тот же принцип и здесь.

image

Третий способ: тени и отрицательные отступы




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

.block__element--cut:before {
border-radius: 50%;
content: "";
height: 8em;
margin: -5em;
position: absolute;
width: 8em;
z-index: -1;
}
.block:nth-child(1) .block__element--cut:before {
bottom: 0;
box-shadow: 0 0 0 40em #0F414C;
right: 0;
}
.block:nth-child(2) .block__element--cut:before {
bottom: 0;
box-shadow: 0 0 0 40em #673A01;
left: 0;
}
.block:nth-child(3) .block__element--cut:before {
box-shadow: 0 0 0 40em rgba(187, 169, 255, 0.65);
right: 0;
top: 0;
}
.block:nth-child(4) .block__element--cut:before {
box-shadow: 0 0 0 40em rgba(176, 214, 95, 0.65);
left: 0;
top: 0;
}




Но самое элегантное тут вовсе не тень. А использование отрицательного значения margin: -5em. При абсолютном позиционировании right, bottom для элемента будет действовать значения margin-right: -5em и margin-bottom: -5em соответственно.

Оригинальное решение Hugo на SASS можно посмотреть тут. Он использует box-shadow как в третьем примере. Вспомнив под конец мой вчерашний перевод «Только разработчики 90-х помнят этор», хочется сказать, что лет через 15 мы также будет улыбаться на эти дикие методы, которые приведены в этом посту.


Спасибо всем за внимание.


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.


Комментариев нет:

Отправить комментарий