1
votes

I'm creating a vertical navigation where list-items are circles. Sub-menu items should fly out from its parent.

I have working code, but the code works only with a single sub-menu because it requires heavy use of the 'left' and 'top' properties to position submenu list-items. I bet this could look pretty with several more sub-menus, but it would require too much CSS customization per menu for my taste.

Working demo with 1 submenu.

<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;
}

Demo that breaks because there are 2 submenus.

<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;
}

Is it possible to create the effect I want for multiple submenus with only CSS but without needing to position each submenu item individually? Or will I need to employ JavaScript to 'automatically' position elements for me?

2
I think this rather breaks because you are using a combination of fixed/relative positioning here … I would leave the main menu items in normal flow, and give them position:relative, so that their then absolutely positioned child elements take them as orientation points …CBroe

2 Answers

1
votes

You are setting the position of the submenu items in a global way, so every different submenu needs to calculate different left and top values.

If you set the submenus to be absolute positioned, the coordinates become relative to the parent that is positioned, in that case you would want your menu items to be that parent.

I have changed your HTML to set a submenu class to the second level 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>

I have done a lot of simplification in your CSS, but the key issue is that now the submenu li are posotioned taking the upper level li as basis.

/* 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;
}

fiddle

In the process, I have damaged the inner alignment of the a (sorry!), but you can easily restore that to what you need.

0
votes

I would try to use :nth-child() to easily position each subNav to your licking with out killing yourself on coding.

Here is the :nth-child() css:

.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%;
}

Finally, a fiddle: Demo