В этом уроке мы будем создавать анимированное вращающееся меню, которое включает в себя набор различных методов CSS3.
В этом меню используется очень много CSS3 но, на удивление, это меню очень хорошо работает во многих браузерах. Основная проблема связана с Оперой, которая сталкивается с несколькими проблемами при попытке запустить код (в связи с отсутствием поддержки преобразования).
Только чистый CSS
Для достижения желаемого эффекта, мы должны использовать несколько CSS трюков. Во-первых, нам нужно создать HTML. Мы поставим туда несколько флажков и радио кнопок, которые (позже) будем использовать в тандеме с CSS, чтобы проверить, если пользователь нажал на них. Затем у нас могут быть label`ы где угодно в коде, которые будет связываться с соответствующими радио кнопками, и использовать эти лейблы как блочные элементы для нормального дизайна. Потом, для того чтобы изменить CSS других элементов щелчком мыши, можно просто использовать .checkbox:checked.
Для этого конкретного меню и простоты, мы будем использовать простые символы ASCII, но вы можете использовать набор иконок или любые другие CSS-иконки. Если вы не можете их получить, тогда просто используйте изображения/картики вместо иконок.
HTML для меню:
<div id="menu">
<input type="checkbox" id="on-check" name="on-check" />
<label id="on-button" for="on-check">
<span>
<span class="ss-plus"><!-- Вставьте сюда символ "ON" если не пользуетесь иконками --></span></span>
<span>
<span class="ss-hyphen"><!-- Вставьте сюда символ "OFF" если не пользуетесь иконками --></span></span>
</label>
<input type="radio" id="info-home" name="radio-check" />
<input type="radio" id="info-compass" name="radio-check" checked />
<input type="radio" id="info-heart" name="radio-check" />
<input type="radio" id="info-rss" name="radio-check" />
<input type="radio" id="info-refresh" name="radio-check" />
<input type="radio" id="info-star" name="radio-check" />
<div id="menu-items">
<div class="middle">
<div class="top">
<span class="bg-piece"> </span>
<label class="ss-home" for="info-home"><!-- Put home icon here if not using symbol set --</label>
<span class="bg-piece"></span>
<label class="ss-compass" for="info-compass"><!-- Put compass icon here if not using symbol set --></label>
<span class="bg-piece"></span>
<label class="ss-heart" for="info-heart"><!-- Put heart icon here if not using symbol set --></label>
</div>
<div class="bottom">
<span class="bg-piece"> </span>
<label class="ss-rss" for="info-rss"><!-- Put rss icon here if not using symbol set --></label>
<span class="bg-piece"></span>
<label class="ss-refresh" for="info-refresh"><!-- Put refresh icon here if not using symbol set --></label>
<span class="bg-piece"></span>
<label class="ss-star" for="info-star"><!-- Put icon here if not using symbol set --></label>
</div>
</div>
</div>
<div class="info home-info">Домой</div>
<div class="info compass-info">Нужен маршрут?</div>
<div class="info heart-info">Любовь</div>
<div class="info rss-info">RSS</div>
<div class="info star-info">Галактика</div>
<div class="info refresh-info">Обновить</div>
<div class="faux-shadow"></div>
</div>
Теперь создайте CSS файл и слинкуйтесь с ним в хэдере (head) вашего HTML документа.
CSS
Чтобы сделать меню интерактивным, мы объединим две основные функции CSS: селекторы-родственники и :checked псевдо-класс. Мы также включим 3D преобразование, чтобы ON/OFF кнопка перевернулась, когда будет включена. Начальное стилирование только меняет внешний вид меню:
/* Для правильного позиционирования меню */
#menu {
position:relative;
width:230px;
margin: 0px auto;
top:100px;
left:37px;
}
/* Мы используем overflow: hidden; поэтому нам нужно создать фальшивую тень*/
.faux-shadow {
position:absolute;
content: "";
width:150px;
height:150px;
top:0px;
left:0px;
box-shadow:0 0 50px rgba(0,0,0,0.3);
border-radius:300px;
-webkit-transition:all 0.4s linear;
-moz-transition:all 0.4s linear;
-ms-transition:all 0.4s linear;
-o-transition:all 0.4s linear;
transition:all 0.4s linear;
z-index:-9999;
}
/* Кнопка по центру, которую будет нажимать пользователь для активации меню*/
#on-button {
border-radius:100px;
width:150px;
height:150px;
color:#fff;
float:left;
box-sizing:border-box;
-moz-box-sizing:border-box;
cursor:pointer;
background-color:#313b3d;
pointer-events:none;
font-size:5em;
text-shadow:0 1px 1px rgba(0,0,0,0.3);
box-shadow:inset 0 -125px 100px -100px rgba(0,0,0,0.5),0 0 20px rgba(0,0,0,0.2);
}
/* On hover */
#on-button:hover {
box-shadow:inset 0 125px 100px -100px rgba(0,0,0,0.5),0 0 20px rgba(0,0,0,0.2);
}
/* On click */
#on-button:active {
box-shadow:inset 0 125px 100px -100px rgba(0,0,0,0.5),0 0 20px rgba(0,0,0,0.2), inset 0 0 30px rgba(0,0,0,0.3);
}
/* Спаны внутри on кнопки будут вращаться */
#on-button > span {
-webkit-backface-visibility:hidden;
-moz-backface-visibility:hidden;
-ms-backface-visibility:hidden;
-o-backface-visibility:hidden;
-webkit-transition:-webkit-transform 0.2s linear;
-moz-transition:-moz-transform 0.2s linear;
-ms-transition:-ms-transform 0.2s linear;
-o-transition:-o-transform 0.2s linear;
transition: transform 0.2s linear;
display: block;
width:122px;
height:122px;
background:#313b3d;
border-radius:120px;
pointer-events:auto;
position:absolute;
z-index:3;
top:0;
left:0;
box-sizing:border-box;
-moz-box-sizing:border-box;
padding:34px;
margin:14px;
box-shadow:inset 0 -112px 100px -100px rgba(0,0,0,0.5);
}
/* Изменение тени на hover, для соответствия с тенью контейнера*/
#on-button:hover > span {
box-shadow:inset 0 112px 100px -100px rgba(0,0,0,0.5);
}
/* Переворачиваем последний span-элемент */
#on-button > span:last-of-type {
-webkit-transform:rotateY(180deg);
-moz-transform:rotateY(180deg);
-o-transform:rotateY(180deg);
-ms-transform:rotateY(180deg);
transform:rotateY(180deg);
}
/* Добавление псевдо элемена с белым фоном, который будет создавать иллюзию, что у ON кнопки есть отверстие*/
#on-button:after {
position:absolute;
content:" ";
top:0;
left:0;
width:120px;
height:120px;
margin:15px;
border-radius:120px;
background:#fff;
z-index:2;
}
Далее нам нужно проверить, если флажок ON отмечен. Затем мы используем родственный селектор, чтобы показать DIV, который мы хотим стилировать и изменить соответствующим образом.
/* При нажатии на кнопку ON поворот всех спанов на 180% */
#on-check:checked + #on-button > span:first-of-type {
-webkit-transform:rotateY(180deg);
-moz-transform:rotateY(180deg);
-o-transform:rotateY(180deg);
-ms-transform:rotateY(180deg);
transform:rotateY(180deg);
}
#on-check:checked + #on-button > span:last-of-type {
-webkit-transform:rotateY(0deg);
-moz-transform:rotateY(0deg);
-ms-transform:rotateY(0deg);
-o-transform:rotateY(0deg);
transform:rotateY(0deg);
}
/* Изменим ширину и высоту тени faux shadow */
#on-check:checked ~ .faux-shadow {
width:300px;
height:300px;
top:-75px;
left:-75px;
}
/* Не показываем элементы если чекбокс NOT CHECKED */
#menu #on-check:not(:checked) ~ .info {
opacity:0;
}
/* Показываем секции с задержкой в 0.4s */
#menu #on-check:checked ~ .info {
-webkit-transition:all 0.2s linear 0.4s;
-moz-transition:all 0.2s linear 0.4s;
-ms-transition:all 0.2s linear 0.4s;
-o-transition: all 0.2s linear 0.4s;
transition:all 0.2s linear 0.4s;
}
/* Показываем внутреннее меню */
#on-check:checked ~ #menu-items {
width:300px;
height:300px;
left:-75px;
top:-75px;
}
Следующий шаг, это изменить сам контейнер меню.
/* Оформление пунктов меню контейнера DIV */
#menu-items {
width:150px;
height:150px;
border-radius:250px;
background:#aaa;
position:absolute;
top:0;
left:0;
z-index:-99;
overflow:hidden;
-webkit-mask-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAA5JREFUeNpiYGBgAAgwAAAEAAGbA+oJAAAAAElFTkSuQmCC);
box-shadow:0 0 15px rgba(0,0,0,0.3);
-webkit-transition:all 0.4s linear;
-moz-transition:all 0.4s linear;
-ms-transition:all 0.4s linear;
-o-transition:all 0.4s linear;
transition:all 0.4s linear;
}
/* Мы разделили кусочки меню на два div: top и bottom. */
#menu-items .top, #menu-items .bottom {
width:100%;
float:left;
z-index:1;
height:50%;
}
#menu-items .bottom {
top:50%;
}
/* The middle div is largely to fix a bug where the content would exceed the border radius when overflow: hidden; was set */
#menu-items .middle {
height:100%;
white-space:
nowrap;
}
/* Стилирование фоновых кусков. Эти контейнеры ничего не делают, они только для дизайна */
#menu-items .middle .bg-piece {
width:33.3%;
height:100%;
text-align:center;
display:inline-block !important;
background:#eee;
font-size:2.5em;
position:absolute;
display:block;
}
/* Важно убедиться, что все части фона в правильной позиции, а это требует немного экспериментирования. Приведенный ниже код проверяет, чтобы все было расположено в правильном порядке */
#menu-items .middle > div .bg-piece:nth-of-type(2) {
position:absolute;
width:0;
height:0;
}
#menu-items .middle .bottom .bg-piece:nth-of-type(2):after, #menu-items .middle .top .bg-piece:nth-of-type(2):after {
content:" ";
position:absolute;
border-color:transparent transparent #eee transparent;
border-width:148px;
border-style:solid;
top:-142px;
left:0px;
z-index:999;
}
#menu-items .middle .top .bg-piece:nth-of-type(2):after {
border-color:#eee transparent transparent transparent;
top:-5px;
left:0;
}
#menu-items .middle .top .bg-piece:nth-of-type(1) {
box-shadow:inset -125px 0 36px -35px rgba(0,0,0,0.1),inset -7px -161px 72px rgba(0,0,0,0.1);
}
#menu-items .middle .top .bg-piece:nth-of-type(3) {
box-shadow:inset 125px 0 36px -35px rgba(0,0,0,0.1),inset -7px -161px 72px rgba(0,0,0,0.1);
}
#menu-items .middle > div .bg-piece:nth-of-type(1) {
width:50%;
box-shadow:inset -125px 0 36px -35px rgba(0,0,0,0.1);
}
#menu-items .middle > div .bg-piece:nth-of-type(3) {
width:50%;
right:0;
box-shadow:inset 125px 0 36px -35px rgba(0,0,0,0.1);
}
/* ------------------------------------------------------------ */
Теперь мы переходим к стилированию информационных боксов и labels, чтобы убедиться, что всё находится в правильном положении.
/* Labels - это те элементы, которые содержат иконки */
#menu-items label {
position:absolute;
z-index:9999999;
font-size:2em;
border-radius:5px;
cursor:pointer;
text-shadow:1px 1px 0 rgba(255,255,255,0.1);
/* Голубое свечение при наведении мышки */
#menu-items label:hover {
text-shadow:0 0 15px #a6d8f4;
}
/* Информационные боксы, они появляются, когда выбран пункт меню */
#menu .info {
opacity:0;
position:absolute;
left:55px;
top:-136px;
display:inline-block;
background-color:#d2d2d2;
padding:10px;
color:#343434;
z-index:9999999;
font:normal normal 1.5em Arial, sans-serif;
background:#eee;
border:1px solid #ddd;
font-weight:bold;
border-radius:8px;
box-shadow:inset 0px 40px 200px -30px rgba(255,255,255,1),0px 0px 20px rgba(0,0,0,0.1);
}
/* Маленькие стрелочки для коробок меню */
#menu .info:after {
position:absolute;
content:" ";
top:37px;
left:8px;
border-color:#f3f3f3 transparent transparent transparent;
border-width:10px;
border-style:solid;
}
/* Границы для стрелки */
#menu .info:before {
position:absolute;
content:" ";
top:38px;
left:8px;
border-color:#ddd transparent transparent transparent;
border-width:10px;
border-style:solid;
}
/* Скрыть радио и флажки */
#menu input[type='checkbox'],input[type='radio'] { display: none; }
/* Правильное расположение иконок */
#menu-items .top .ss-home { top: 90px; left:34px; }
#menu-items .top .ss-heart { top: 90px; left:241px; }
#menu-items .top .ss-compass { top: 21px; left:137px; }
#menu-items .bottom .ss-rss { top: 181px; left:35px; }
#menu-items .bottom .ss-star { top: 181px;left: 243px; }
#menu-items .bottom .ss-refresh { top: 249px;left: 139px; }
И, наконец, нам нужно вращать иконки в нужном направлении, и убедиться в том, что они повернуты в том заданом положении, при нажатие. Опять же, мы используем родственные селекторы и :checked псевдо-класс.
/* Код ниже вращает пункты меню в правильное положение, когда каждый из них нажат. */
#info-home:checked ~ #menu-items, #menu-items .top .ss-heart {
-webkit-transform:rotateZ(66deg);
-moz-transform:rotateZ(66deg);
-ms-transform:rotateZ(66deg);
-o-transform:rotateZ(66deg);
transform:rotateZ(66deg);
}
#info-heart:checked ~ #menu-items, #menu-items .top .ss-home {
-webkit-transform:rotateZ(-66deg);
-moz-transform:rotateZ(-66deg);
-ms-transform:rotateZ(-66deg);
-o-transform:rotateZ(-66deg);
transform:rotateZ(-66deg);
}
#info-rss:checked ~ #menu-items, #menu-items .bottom .ss-star {
-webkit-transform:rotateZ(114deg);
-moz-transform:rotateZ(114deg);
-ms-transform:rotateZ(114deg);
-o-transform:rotateZ(114deg);
transform:rotateZ(114deg);
}
#info-star:checked ~ #menu-items, #menu-items .bottom .ss-rss {
-webkit-transform:rotateZ(-114deg);
-moz-transform:rotateZ(-114deg);
-ms-transform:rotateZ(-114deg);
-o-transform:rotateZ(-114deg);
transform:rotateZ(-114deg);
}
#info-refresh:checked ~ #menu-items, #menu-items .bottom .ss-refresh {
-webkit-transform:rotateZ(180deg);
-moz-transform:rotateZ(180deg);
-ms-transform:rotateZ(180deg);
-o-transform:rotateZ(180deg);
transform:rotateZ(180deg);
}
/* --------------------------------------------------------------- */
/* Выделить выбранный пункт */
#info-home:checked ~ #menu-items .ss-home, #info-heart:checked ~ #menu-items .ss-heart, #info-rss:checked ~ #menu-items .ss-rss, #info-star:checked ~ #menu-items .ss-star, #info-refresh:checked ~ #menu-items .ss-refresh, #info-compass:checked ~ #menu-items .ss-compass {
text-shadow:0 0 15px #3facf2;
color:#24434f;
}
/* Сделайте непрозрачность инфо коробок 1, когда они нажаты */
#info-home:checked ~ .home-info, #info-heart:checked ~ .heart-info, #info-rss:checked ~ .rss-info, #info-star:checked ~ .star-info, #info-refresh:checked ~ .refresh-info, #info-compass:checked ~ .compass-info {
opacity:1;
}
Вот и всё.