纯css多层菜单,带有功能性痕迹导航

时间:2016-07-15 09:52:17

标签: html css menu breadcrumbs

我正在尝试创建一个带有痕迹导航的多层菜单,而不使用javascript。我遇到过大量的纯CSS菜单和面包屑,但从未组合在一起工作。这是我想要实现的设计(点击'更多'汉堡包菜单):

https://invis.io/857RUKE6M

这就是我目前在html / css中所拥有的内容(请参阅下面的codepen链接)。请原谅原始/ hacky代码。在这一点上,我只是测试想法,一旦找到解决方案,我将简化和美化我的代码。

http://codepen.io/jessbenz/pen/LZWjjz

这是一个代码段,但请查看上面的codepen链接以获得更好的感受:

<div class="smart-nav">
    <input type="radio" id="bread-home" class="breadcrumb" name="bread" />
    <input type="radio" id="bread-women" class="breadcrumb" name="bread" />
    <input type="radio" id="bread-womens-clothing" class="breadcrumb" name="bread" />
    <div class="smart-nav-panels">
      <ul id="home">

        <li>
          <input type="radio" name="first">
          <label>1 Women</label>
          <ul id="women">
            <li>
              <input type="radio" name="second">
              <label>1.1 Women's Clothing</label>
              <ul id="womens-clothing">
                <li>
                  <label>1.1.1 Women's Shirts</label>
                </li>
              </ul>
            </li>
          </ul>
        </li>

        <li>
          <input type="radio" name="first">
          <label>2 Men</label>  
          <ul id="men">
            <li>2.1 Men's Shirts</li>
          </ul>         
        </li>

      </ul>
    </div>
</div>

和我的sass:

.breadcrumb:checked ~ .smart-nav-panels ul {
  display: none;
}
#bread-home:checked ~ .smart-nav-panels > ul {
  display: block;
}
#bread-women:checked ~ .smart-nav-panels {
  #home, #women {
    display: block;
  }
}
#bread-womens-clothing:checked ~ .smart-nav-panels {
  #home, #women, #womens-clothing {
    display: block;
  }
}
#bread-home:checked ~ .smart-nav-panels li input:checked > ul:first-child {
  display: block;
}
.smart-nav-panels {
  margin: 0;
  padding: 0;
  ul {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    width: 100%;
    height: 100%;
    background: lightgrey;
  }
  ul, li {
    list-style: none;
    margin: 0;
    padding: 0;
  }
  > ul:first-child {
    ul {
      left: 100%;
    }
  }
  li {
    input + label + ul {
      display: none;
    }
    input:checked + label + ul {
      display: block;
      // left:0;
    }
  }
}
input:checked ul {
  display: block;
}

如果你点击我的codepen样本中的女性服装,你会发现我已经在那里实现了我所需要的一半。顶部水平单选按钮表示面包屑,灰色块内的垂直单选按钮表示层菜单。当我选择面包屑收音机时会出现问题。显示正确的幻灯片,但如果我再次在菜单中选择一个收音机,它就不会显示,因为我的面包屑css正在优先选择并隐藏相关内容。我想这里存在的问题是不使用javascript。如何使用纯CSS使我的导航相互识别?可能这种组合两个无线电导航的方法是不正确的。我真的希望有人可以分享他们的智慧。 :)

提前致谢

1 个答案:

答案 0 :(得分:1)

你不要回避挑战,对吗? :)

在我发布任何更多细节之前,我会说简短的回答是“构建静态网站”。换句话说,假设您的一个设计约束是“没有javascript”,请将问题移到使用决策逻辑/代码以使其更容易解决的地方(即:服务器)。

即使您设法解决了这个问题(并且我不确定在HTML / CSS的约束下是否可能),您将要遇到的下一个问题是将所有行为附加到它上面。您将要根据菜单选择加载特定内容,而您要做的唯一方法是:

  • javascript事件,或
  • 一个静态链接(锚元素,因此我的简短答案后面的'为什么')

可以加载所有内容,也许可以找到一种方法来有条件地显示它,但问题是“兔子洞有多深?”。此外,如果您正在构建功能手机和/或慢速连接,则加载所有内容将对用户体验产生负面影响。

说完所有这些之后,我设法略微简化了CSS并修复了子类别显示的错误(请参阅注释内联)。请注意,只有“女性”类别的行为符合预期,因为“男性”和“男性”中缺少样式。 “儿童。

.container {
  position: relative;
  width: 360px;
  height: 480px;
  border: 1px solid black;
  margin: 20px auto 0 auto;
}

.breadcrumb {
  margin-top: -20px;
  display: inline-block;
  vertical-align: top;
}

/*
.breadcrumb:checked ~ .smart-nav-panels ul {
  display: none;
}

#bread-home:checked ~ .smart-nav-panels > ul {
  display: block;
}
*/

/* hide all uls except the 'home' ul by default, replaces both of the above */
.smart-nav-panels ul ul {      
  display: none;
}

/*
#bread-women:checked ~ .smart-nav-panels {
  #home, #women {
    display: block;
  }
}

#bread-womens-clothing:checked ~ .smart-nav-panels {
  #home, #women, #womens-clothing {
    display: block;
  }
}
*/

/* these next 3 style definitions are very similar to what you had before (commented 
above), except that there is no longer a need to unhide the 'home' ul, and we're
being more explicit about which uls to hide in correspondence with the state of the
breadcrumb nav */
#bread-home:checked ~ .smart-nav-panels {
  #women {
    display: none;
  }
}    

#bread-women:checked ~ .smart-nav-panels {
  #women {
    display: block;
  }
  #womens-clothing, #womens-shoes {
    display: none;
  }
}

#bread-womens-clothing:checked ~ .smart-nav-panels {
  #women, #womens-clothing {
    display: block;
  }
}

/*
#bread-home:checked ~ .smart-nav-panels li input:checked > ul:first-child {
  display: block;
}
*/

/* (i) the above didn't work because the ul isn't a direct descendant of the input,
rather it is a sibling, and in addition it doesn't matter which breadcrumb item is
checked now */
.smart-nav-panels li input:checked ~ ul {
  display: block;
}

.smart-nav-panels {
  margin: 0;
  padding: 0;
  ul {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    width: 100%;
    height: 100%;
    background: lightgrey;
  }
  ul, li {
    list-style: none;
    margin: 0;
    padding: 0;
  }

  > ul:first-child {
    ul {
      left: 100%;
    }
  }
  /* removed unnecessary styles here */
}
/* removed unnecessary style here */

这解决了一些问题,但还有更多问题。我怀疑,解决其中一些将创造新的。我能想到的一个直接的问题就是你要将分层菜单的状态与面包屑联系起来,以便你只能看到你想要的面包屑(现在你总能看到所有的面包屑)它)。

在某些时候,您将需要事件(针对行为),并且组件需要了解彼此的状态。虽然CSS具有一些状态功能,但它在事件方面没有提供任何内容。这些限制,级联性质(在其他问题中深入讨论,例如:缺少祖先选择器)和与HTML结构的耦合都有助于使这个问题成为一个非常难以解决的问题。仅CSS。

我理解在没有JS的情况下进行这种导航的愿望,当然这是一个尝试和解决的有趣问题,但最终我认为这是错误的方法。 有一个原因可以解释为什么javascript如此无处不在 - 如果没有它,我们今天的网络体验就不一样了。

(感谢Jess和其他同事的讨论通知了这个答案的部分内容。我自由地解释了。希望这对其他人有好处。)