Вертикальная круговая навигация с анимированными подменю: только CSS3?

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

У меня есть рабочий код, но код работает только с одним подменю, потому что он требует интенсивного использования свойств "left" и "top" для позиционирования элементов списка подменю. Бьюсь об заклад, это могло бы выглядеть красиво с несколькими дополнительными подменю, но на мой вкус потребовалось бы слишком много настроек CSS для каждого меню.

Рабочая демонстрация с 1 подменю.

<nav>
    <ul class="menu">
        <li><a href="/">Home Page</a></li>
        <li><a href="/">About</a>
            <ul>
                <li><a href="/">Our History</a></li>
                <li><a href="/">Our Philosophy</a></li>
                <li><a href="/">Our Mission</a></li>
            </ul>
        </li>
        <li><a href="/">Services</a></li>
        <li><a href="/">Our Team</a></li>
        <li><a href="/">Contact Us</a></li>
    </ul>
</nav>

CSS

/* Circle Menu */
nav {
    width: 10em;
}
.menu a{
    display: block;
    padding:10px;
    width: 100%;
    height: 7.5em;
    border-radius: 750px 750px 750px 750px;
    -moz-border-radius: 750px 750px 750px 750px;
    -webkit-border-radius: 750px 750px 750px 750px;
    background-color: hsl(0, 100%, 72%);
    text-align: center;
    margin-bottom: 1em;
}
.menu li{
    margin-bottom: 1em;
    list-style: none;
}
.menu li ul{
    -webkit-transition:all .35s ease-in;
    -moz-transition:all .35s ease-in;
    -o-transition:all .35s ease-in;
    transition:all .35s ease-in;

    opacity: 0;
    padding: 0;

    display: inline;
    top: -8em;
    position: fixed;
}
.menu li:hover ul{
    -webkit-transition:all .35s ease-in;
    -moz-transition:all .35s ease-in;
    -o-transition:all .35s ease-in;
    transition:all .35s ease-in;

    padding: 0;
    opacity: 1;
}
.menu ul li a{
    width: 100%;
    background-color: hsl(0, 60%, 72%);
}
.menu li ul li {
    -webkit-transition:all .35s ease-in;
    -moz-transition:all .35s ease-in;
    -o-transition:all .35s ease-in;
    transition:all .35s ease-in;

    position:relative;
    left:0;
}
.menu li:hover ul li {
    -webkit-transition:all .35s ease-in;
    -moz-transition:all .35s ease-in;
    -o-transition:all .35s ease-in;
    transition:all .35s ease-in;

    position: relative;
    left: 190px;
}
.menu li ul li:nth-child(1) {
    top: 307px;
    left: 0px;
    -webkit-transition:all .35s ease-in;
    -moz-transition:all .35s ease-in;
    -o-transition:all .35s ease-in;
    transition:all .35s ease-in;
}
.menu li:hover ul li:nth-child(1) {
    top: 150px;
    left: 160px;
    -webkit-transition:all .35s ease-in;
    -moz-transition:all .35s ease-in;
    -o-transition:all .35s ease-in;
    transition:all .35s ease-in;
}
.menu li ul li:nth-child(2) {
    top: 153px;
    left: 0;
    -webkit-transition:all .35s ease-in;
    -moz-transition:all .35s ease-in;
    -o-transition:all .35s ease-in;
    transition:all .35s ease-in;
}
.menu li:hover ul li:nth-child(2) {
    left: 240px;
    -webkit-transition:all .35s ease-in;
    -moz-transition:all .35s ease-in;
    -o-transition:all .35s ease-in;
    transition:all .35s ease-in;
    top: 150px;
}
.menu li ul li:nth-child(3) {
    top: -5px;
    left: 0;
    -webkit-transition:all .35s ease-in;
    -moz-transition:all .35s ease-in;
    -o-transition:all .35s ease-in;
    transition:all .35s ease-in;
}
.menu li:hover ul li:nth-child(3) {
    top: 153px;
    left: 160px;
    -webkit-transition:all .35s ease-in;
    -moz-transition:all .35s ease-in;
    -o-transition:all .35s ease-in;
    transition:all .35s ease-in;
}

Демонстрация не работает из-за 2 подменю.

<nav>
    <ul class="menu">
        <li><a href="/">Home Page</a></li>
        <li><a href="/">About</a>
            <ul>
                <li><a href="/">Our History</a></li>
                <li><a href="/">Our Philosophy</a></li>
                <li><a href="/">Our Mission</a></li>
            </ul>
        </li>
        <li><a href="/">Services</a></li>
        <li><a href="/">Our Team</a>
            <ul>
                <li><a href="/">Jim</a></li>
                <li><a href="/">Karla</a></li>
                <li><a href="/">Manzanita</a></li>
            </ul>
        </li>
        <li><a href="/">Contact Us</a></li>
    </ul>
</nav>

CSS

/* Circle Menu */
nav {
    width: 10em;
}
.menu a{
    display: block;
    padding:10px;
    width: 100%;
    height: 7.5em;
    border-radius: 750px 750px 750px 750px;
    -moz-border-radius: 750px 750px 750px 750px;
    -webkit-border-radius: 750px 750px 750px 750px;
    background-color: hsl(0, 100%, 72%);
    text-align: center;
    margin-bottom: 1em;
}
.menu li{
    margin-bottom: 1em;
    list-style: none;
}
.menu li ul{
    -webkit-transition:all .35s ease-in;
    -moz-transition:all .35s ease-in;
    -o-transition:all .35s ease-in;
    transition:all .35s ease-in;

    opacity: 0;
    padding: 0;

    display: inline;
    top: -8em;
    position: fixed;
}
.menu li:hover ul{
    -webkit-transition:all .35s ease-in;
    -moz-transition:all .35s ease-in;
    -o-transition:all .35s ease-in;
    transition:all .35s ease-in;

    padding: 0;
    opacity: 1;
}
.menu ul li a{
    width: 100%;
    background-color: hsl(0, 60%, 72%);
}
.menu li ul li {
    -webkit-transition:all .35s ease-in;
    -moz-transition:all .35s ease-in;
    -o-transition:all .35s ease-in;
    transition:all .35s ease-in;

    position:relative;
    left:0;
}
.menu li:hover ul li {
    -webkit-transition:all .35s ease-in;
    -moz-transition:all .35s ease-in;
    -o-transition:all .35s ease-in;
    transition:all .35s ease-in;

    position: relative;
    left: 190px;
}
.menu li ul li:nth-child(1) {
    top: 307px;
    left: 0px;
    -webkit-transition:all .35s ease-in;
    -moz-transition:all .35s ease-in;
    -o-transition:all .35s ease-in;
    transition:all .35s ease-in;
}
.menu li:hover ul li:nth-child(1) {
    top: 150px;
    left: 160px;
    -webkit-transition:all .35s ease-in;
    -moz-transition:all .35s ease-in;
    -o-transition:all .35s ease-in;
    transition:all .35s ease-in;
}
.menu li ul li:nth-child(2) {
    top: 153px;
    left: 0;
    -webkit-transition:all .35s ease-in;
    -moz-transition:all .35s ease-in;
    -o-transition:all .35s ease-in;
    transition:all .35s ease-in;
}
.menu li:hover ul li:nth-child(2) {
    left: 240px;
    -webkit-transition:all .35s ease-in;
    -moz-transition:all .35s ease-in;
    -o-transition:all .35s ease-in;
    transition:all .35s ease-in;
    top: 150px;
}
.menu li ul li:nth-child(3) {
    top: -5px;
    left: 0;
    -webkit-transition:all .35s ease-in;
    -moz-transition:all .35s ease-in;
    -o-transition:all .35s ease-in;
    transition:all .35s ease-in;
}
.menu li:hover ul li:nth-child(3) {
    top: 153px;
    left: 160px;
    -webkit-transition:all .35s ease-in;
    -moz-transition:all .35s ease-in;
    -o-transition:all .35s ease-in;
    transition:all .35s ease-in;
}

Можно ли создать эффект, который я хочу для нескольких подменю, только с помощью CSS, но без необходимости позиционировать каждый элемент подменю по отдельности? Или мне нужно будет использовать JavaScript для «автоматического» позиционирования элементов?


person Miguel Valencia    schedule 14.02.2014    source источник
comment
Я думаю, что это скорее ломается, потому что вы используете здесь комбинацию фиксированного/относительного позиционирования… Я бы оставил пункты главного меню в обычном потоке и дал бы им position:relative, чтобы их тогда абсолютно позиционированные дочерние элементы воспринимали их как точки ориентации…   -  person CBroe    schedule 15.02.2014


Ответы (2)


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

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

Я изменил ваш HTML, чтобы установить класс подменю на второй уровень ul.

HTML

<nav>
    <ul class="menu">
        <li><a href="/">Home Page</a></li>
        <li><a href="/">About</a>
            <ul class="submenu">
                <li><a href="/">Our History</a></li>
                <li><a href="/">Our Philosophy</a></li>
                <li><a href="/">Our Mission</a></li>
            </ul>
        </li>
        <li><a href="/">Services</a></li>
        <li><a href="/">Our Team</a>
            <ul class="submenu">
                <li><a href="/">Jim</a></li>
                <li><a href="/">Karla</a></li>
                <li><a href="/">Manzanita</a></li>
            </ul>
        </li>
        <li><a href="/">Contact Us</a></li>
    </ul>
</nav>

Я сильно упростил ваш CSS, но главная проблема в том, что теперь подменю li позиционируется на основе верхнего уровня li.

/* Circle Menu */
nav {
    width: 10em;
}
.menu a{
    display: block;
    width: 7.5em;
    height: 7.5em;
    border-radius: 50%;
    background-color: hsl(0, 100%, 72%);
    text-align: center;
}
.menu li{
    list-style: none;
    position: relative;
    margin: 0em 1em 1em 0em;
    width: 100%;
}
.submenu{
    opacity: 0;
    position: absolute;
    width: 100%;
    height: 100%;
    top: 0px;
    left: 0px;
    padding: 0px;
}

.submenu:hover {
    opacity: 1;

}
.submenu li {
    -webkit-transition:all .35s ease-in;
    -moz-transition:all .35s ease-in;
    -o-transition:all .35s ease-in;
    transition:all .35s ease-in;
    position: absolute;
    width: 100%;
    left: 0px;
    top: 0px;
    height: 100%;
}
.submenu:hover li:nth-child(1) {
    top: -106px;
    left: 160px;
}
.submenu:hover li:nth-child(2) {
    top: -8px;
    left: 270px;
}
.submenu:hover li:nth-child(3) {
    top: 90px;
    left: 160px;
}

скрипка

В процессе я повредил внутреннее выравнивание a (извините!), но вы можете легко восстановить его до того состояния, которое вам нужно.

person vals    schedule 15.02.2014
comment
Спасибо vals (и всем остальным!). Я думаю, это будет решением. Позвольте мне поиграть с этим, чтобы понять, что происходит, прежде чем пометить это как решенное. - person Miguel Valencia; 16.02.2014

Я бы попытался использовать :nth-child(), чтобы легко позиционировать каждый subNav по вашему вкусу, не убивая себя при кодировании.

Вот код :nth-child():

.subNav li:nth-child(1) {
    left: 120%;
    top: 0;
}

.subNav li:nth-child(2) {
    left: 170%;
    top: 100%;
}

.subNav li:nth-child(3) {
    left: 120%;
    top: 200%;
}

Наконец, скрипка: Демонстрация

person Josh Powell    schedule 14.02.2014