В этом уроке мы будем создавать анимированное вращающееся меню, которое включает в себя набор различных методов CSS3.
В этом меню используется очень много CSS3 но, на удивление, это меню очень хорошо работает во многих браузерах. Основная проблема связана с Оперой, которая сталкивается с несколькими проблемами при попытке запустить код (в связи с отсутствием поддержки преобразования).
Только чистый CSS
Для достижения желаемого эффекта, мы должны использовать несколько CSS трюков. Во-первых, нам нужно создать HTML. Мы поставим туда несколько флажков и радио кнопок, которые (позже) будем использовать в тандеме с CSS, чтобы проверить, если пользователь нажал на них. Затем у нас могут быть label`ы где угодно в коде, которые будет связываться с соответствующими радио кнопками, и использовать эти лейблы как блочные элементы для нормального дизайна. Потом, для того чтобы изменить CSS других элементов щелчком мыши, можно просто использовать .checkbox:checked.
Для этого конкретного меню и простоты, мы будем использовать простые символы ASCII, но вы можете использовать набор иконок или любые другие CSS-иконки. Если вы не можете их получить, тогда просто используйте изображения/картинки вместо иконок.
<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,iVBORw0KGgoAAAANSUhEUgAAAAEAAA ABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQB BZG9iZSBJbWFnZVJlYWR5ccllPAAAAA5JREFUeNp iYGBgAAgwAAAEAAGbA+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; }
Высоких конверсий!