flex column wrap in position absolute - css

I can't seem to wrap my head around this. I'm working on an (existing) menu structure. The current menu never intended the amount of sub-items we have, and as such it overflows from the viewport. Since its sticky some items aren't accessible which is problematic. Since flexbox has an issue where the flexbox itself doesn't adjust its width when wrapping columns, the background of the sub-menu doesn't continue. Again problematic since floating text, over other text, is annoying. Having read up on it, it appears the writing-mode solution is mostly used. However when I try to apply it, it still gets a singular row since the header element has to have position: fixed attached to it.
example to clarify:
html:
<header>
<div class="wrapper">
<ul class="parent">
<li class="child">Menu item 1</li>
<li class="child">Menu item 2</li>
<li class="child">Menu item 3
<ul class="sub-parent">
<li class="sub-child">Sub item 1</li>
<li class="sub-child">Sub item 2</li>
<li class="sub-child">Sub item 3</li>
<li class="sub-child">Sub item 4</li>
<li class="sub-child">Sub item 5</li>
<li class="sub-child">Sub item 6</li>
<li class="sub-child">Sub item 7</li>
<li class="sub-child">Sub item 8</li>
<li class="sub-child">Sub item 9</li>
<li class="sub-child">Sub item 10</li>
<li class="sub-child">Sub item 12</li>
<li class="sub-child">Sub item 13</li>
<li class="sub-child">Sub item 14</li>
<li class="sub-child">Sub item 15</li>
<li class="sub-child">Sub item 16</li>
<li class="sub-child">Sub item 17</li>
<li class="sub-child">Sub item 18</li>
<li class="sub-child">Sub item 19</li>
</ul>
</li>
<li class="child">Menu item 4</li>
<li class="child">Menu item 5</li>
<li class="child">Menu item 6</li>
</ul>
</div>
</header>
<div class="content">
Sub-items should wrap till end of viewport
</div>
css:
header{
position: fixed;
top: 0;
}
.wrapper{
background: #8AB9B5;
}
.parent{
display: flex;
background: #C8C2AE;
list-style: none;
width: 100vw;
}
.child{
margin: 0.5em;
}
.sub-parent{
display: flex;
flex-direction: row;
flex-wrap: wrap;
max-height: 80vh;
background: #D0CDD7;
position: absolute;
margin: 0;
list-style: none;
padding: 0;
writing-mode: vertical-lr;
}
.sub-child{
background: #ACB0BD;
display: block;
margin: 0.5em;
writing-mode: horizontal-tb;
}
.content{
margin-top:100px;
}
https://jsfiddle.net/Tristanschaaf/7pd504hj/99/
Current result:
Expected/wanted result:
It's possible that the sub-items also have a sub-item structure.
I can't seem to find a way to make the flexbox to see it can expand vertically. Additionally there is an issue in Firefox on which the height seems to be initially set to 0 until a viewport resize is triggered.
I am very aware that this structure can cause it's own UX issues but I'm not here to discuss those, as per usual, the impact of that impacts other sides of the business as well and I cannot change it for now.

You have to just remove writing-mode: vertical-lr; property from .sub-parent element and just need to give fix-width to this element width:200px;.

Not sure this what exactly you needed or so,
But what i did is gave some width(200px here) to .sub-parent ul and also some width(fit-content here) to it's children li and then removed/commented one or two from your code to make it look like this. If any doubt do ask
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<style>
header{
position: fixed;
top: 0;
}
.wrapper{
background: #8AB9B5;
}
.parent{
display: flex;
background: #C8C2AE;
list-style: none;
width: 100vw;
}
.child{
margin: 0.5em;
}
.sub-parent{
display: flex;
/* flex-direction: row; */
flex-wrap: wrap;
/* max-height: 80vh; */
width: 200px;
background: #D0CDD7;
position: absolute;
margin: 0;
list-style: none;
padding: 0;
justify-content: center;
/* writing-mode: vertical-lr; */
}
.sub-child{
width: fit-content;
background: #ACB0BD;
display: block;
margin: 0.5em;
writing-mode: horizontal-tb;
}
.content{
margin-top:100px;
}
</style>
<body>
<header>
<div class="wrapper">
<ul class="parent">
<li class="child">Menu item 1</li>
<li class="child">Menu item 2</li>
<li class="child">Menu item 3
<ul class="sub-parent">
<li class="sub-child">Sub item 1</li>
<li class="sub-child">Sub item 2</li>
<li class="sub-child">Sub item 3</li>
<li class="sub-child">Sub item 4</li>
<li class="sub-child">Sub item 5</li>
<li class="sub-child">Sub item 6</li>
<li class="sub-child">Sub item 7</li>
<li class="sub-child">Sub item 8</li>
<li class="sub-child">Sub item 9</li>
<li class="sub-child">Sub item 10</li>
<li class="sub-child">Sub item 12</li>
<li class="sub-child">Sub item 13</li>
<li class="sub-child">Sub item 14</li>
<li class="sub-child">Sub item 15</li>
<li class="sub-child">Sub item 16</li>
<li class="sub-child">Sub item 17</li>
<li class="sub-child">Sub item 18</li>
<li class="sub-child">Sub item 19</li>
</ul>
</li>
<li class="child">Menu item 4</li>
<li class="child">Menu item 5</li>
<li class="child">Menu item 6</li>
</ul>
</div>
</header>
<div class="content">
Sub-items should wrap till end of viewport
</div>
</body>
</html>

You can try the below approach. you just need to set the width of .sub-parent class as per your requirement. (as of now I have set width:40%) and I have set flex-direction: column. and overflow: auto.
header {
position: fixed;
top: 0;
}
.wrapper {
background: #8AB9B5;
}
.parent {
display: flex;
background: #C8C2AE;
list-style: none;
width: 100vw;
}
.child {
margin: 0.5em;
}
.sub-parent {
display: flex;
flex-wrap: wrap;
background: #D0CDD7;
position: absolute;
margin: 0;
list-style: none;
padding: 0;
margin-right: 60px;
}
.sub-child {
flex: 0 10%;
background: #ACB0BD;
display: block;
margin: 0.5em;
writing-mode: horizontal-tb;
}
.content {
margin-top: 100px;
}
<header>
<div class="wrapper">
<ul class="parent">
<li class="child">Menu item 1</li>
<li class="child">Menu item 2</li>
<li class="child">Menu item 3
<ul class="sub-parent">
<li class="sub-child">Sub item 1</li>
<li class="sub-child">Sub item 2</li>
<li class="sub-child">Sub item 3</li>
<li class="sub-child">Sub item 4</li>
<li class="sub-child">Sub item 5</li>
<li class="sub-child">Sub item 6</li>
<li class="sub-child">Sub item 7</li>
<li class="sub-child">Sub item 8</li>
<li class="sub-child">Sub item 9</li>
<li class="sub-child">Sub item 10</li>
<li class="sub-child">Sub item 12</li>
<li class="sub-child">Sub item 13</li>
<li class="sub-child">Sub item 14</li>
<li class="sub-child">Sub item 15</li>
<li class="sub-child">Sub item 16</li>
<li class="sub-child">Sub item 17</li>
<li class="sub-child">Sub item 18</li>
<li class="sub-child">Sub item 19</li>
<li class="sub-child">Sub item 20</li>
<li class="sub-child">Sub item 21</li>
<li class="sub-child">Sub item 22</li>
<li class="sub-child">Sub item 23</li>
<li class="sub-child">Sub item 24</li>
<li class="sub-child">Sub item 25</li>
<li class="sub-child">Sub item 26</li>
<li class="sub-child">Sub item 27</li>
<li class="sub-child">Sub item 28</li>
<li class="sub-child">Sub item 29</li>
<li class="sub-child">Sub item 30</li>
<li class="sub-child">Sub item 31</li>
<li class="sub-child">Sub item 32</li>
<li class="sub-child">Sub item 33</li>
<li class="sub-child">Sub item 34</li>
<li class="sub-child">Sub item 35</li>
<li class="sub-child">Sub item 36</li>
<li class="sub-child">Sub item 37</li>
<li class="sub-child">Sub item 38</li>
<li class="sub-child">Sub item 39</li>
<li class="sub-child">Sub item 40</li>
<li class="sub-child">Sub item 41</li>
<li class="sub-child">Sub item 42</li>
<li class="sub-child">Sub item 43</li>
</ul>
</li>
<li class="child">Menu item 4</li>
<li class="child">Menu item 5</li>
<li class="child">Menu item 6</li>
</ul>
</div>
</header>
<div class="content">
Sub-items should wrap till end of viewport
</div>

Related

Target first level ul li elements only

This solution isn't going to work since I have no control over adding a class/id to the ul element: Get first level li from ul
Given that the parent ul has no id/class, can css be written to target only the first level li? If not, how could it be done?
This is the html:
<ul>
<li id="acomment-62" class=" comment-item" data-bp-activity-comment-id="62">
<div class="bb-activity-more-options-wrap action"></div>
<ul>
<li id="acomment-65" class=" comment-item" data-bp-activity-comment-id="65">
<div class="bb-activity-more-options-wrap action"></div>
<div class="acomment-meta"></div>
<div class="acomment-content"></div>
</li>
</ul>
</li>
<li id="acomment-63" class=" comment-item" data-bp-activity-comment-id="63">
<div class="bb-activity-more-options-wrap action"></div>
<ul>
<li id="acomment-66" class=" comment-item" data-bp-activity-comment-id="66">
<div class="bb-activity-more-options-wrap action"></div>
<div class="acomment-meta"></div>
<div class="acomment-content"></div>
</li>
</ul>
</li>
<li id="acomment-64" class=" comment-item" data-bp-activity-comment-id="64">
<div class="bb-activity-more-options-wrap action"></div>
<ul>
<li id="acomment-67" class=" comment-item" data-bp-activity-comment-id="67">
<div class="bb-activity-more-options-wrap action"></div>
<div class="acomment-meta"></div>
<div class="acomment-content"></div>
</li>
</ul>
</li>
You can do that with CSS alone. There's a few ways you can do it. Here is one of them and a working codepen so you can mess around with it yourself.
HTML
<ul>
<li>Item 1</li>
<li>Item with list 1
<ul>
<li>Sub 1</li>
<li>Sub 2</li>
<li>Sub 3</li>
</ul>
</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>Item with list 2
<ul>
<li>Sub 1</li>
<li>Sub 2</li>
<li>Sub 3</li>
<li>Sub List
<ul>
<li>Sub list item 1</li>
<li>Sub list item 2</li>
<li>Sub list item 3</li>
</ul>
</li>
</ul>
</li>
<li>Item 5</li>
CSS
li {
color: red;
}
li li {
color: initial;
}
I'm not sure how supported this is but you could apply the style to all li and then override that style to target any descendant li
EG.
li li {
color: initial;
}
li {
color: red;
}
<ul>
<li>A</li>
<li>B</li>
<li>
C
<ul>
<li>C1</li>
<li>C2</li>
<li>C3</li>
</ul>
</li>
<li>D</li>
<li>E</li>
</ul>

How to force all submenu levels of ONE parent menu item to be active on hover (mega menu)

I have a mega menu that I'm attempting to build within HubSpot. I have searched through other posts, but can't find a solution.
Details:
- horizontal menu with vertical dropdowns on some items.
- need a mega menu on the first menu item only
- menu has 3 levels
- dropdown mega menu has 3 columns, each with a "heading" which is the 2nd level menu item. Then 3rd level submenu items for each column.
I have it styled exactly as I need it. When I hover over the parent menu item, the mega menu background appears with the 2nd level menu headings (horizontally). Good to this point.
NOW THE ISSUE... the 3rd level menu items (contents of the 3 columns) only shows when I hover over the 2nd level headings. I need these 3rd level items to be active automatically when the parent level menu item is hovered.
SO... need something to trigger all of the 3rd level menu items to be active when the 1st level parent menu item is hovered on.
<ul>
<li class="hs-menu-item hs-menu-depth-1 hs-item-has-children" role="menu">MEGA PARENT
<ul class="hs-menu-children-wrapper">
<li class="hs-menu-item hs-menu-depth-2 hs-item-has-children" role="menuitem">HEADING ITEM 1
<ul class="hs-menu-children-wrapper">
<li class="hs-menu-item hs-menu-depth-3">COLUMN 1 - ITEM 1</li>
<li class="hs-menu-item hs-menu-depth-3">COLUMN 1 - ITEM 2</li>
<li class="hs-menu-item hs-menu-depth-3">COLUMN 1 - ITEM 3</li>
</ul></li>
<li class="hs-menu-item hs-menu-depth-2 hs-item-has-children" role="menuitem">HEADING ITEM 2
<ul class="hs-menu-children-wrapper">
<li class="hs-menu-item hs-menu-depth-3">COLUMN 2 - ITEM 1</li>
<li class="hs-menu-item hs-menu-depth-3">COLUMN 2 - ITEM 2</li>
<li class="hs-menu-item hs-menu-depth-3">COLUMN 2 - ITEM 3</li>
<li class="hs-menu-item hs-menu-depth-3">COLUMN 2 - ITEM 4</li>
</ul></li>
<li class="hs-menu-item hs-menu-depth-2" role="menuitem">HEADING ITEM 3</li>
</ul></li>
</ul>
If I understand correctly, you should be able to do this pretty simply. But maybe I'm confused...
.hs-menu-depth-1:hover .hs-menu-depth-2 > .hs-menu-children-wrapper {
display: block;
}
I.e. when you hover over .hs-menu-depth-1, apply the following styling to the ul submenu that is a direct child of .hs-menu-depth-2, which is the ul that contains all the 3rd-level menu items.
I guess your .hs-menu-depth-2 and .hs-menu-depth-3 allready have display: none;.
Then you add
.hs-menu-depth-1:hover .hs-menu-depth-2, .hs-menu-depth-1:hover .hs-menu-depth-3 {
display: block;
}
or if you don't have any other elements that are display: none; in your menu you can do:
.hs-menu-depth-1:hover *{
display: block;
}
See:
.hs-menu-depth-2{
display: none;
}
.hs-menu-depth-3{
display: none;
}
.hs-menu-depth-1:hover .hs-menu-depth-2, .hs-menu-depth-1:hover .hs-menu-depth-3{
display: block;
}
<ul>
<li class="hs-menu-depth-1">mega parent
<ul>
<li class="hs-menu-depth-2" role="menuitem">heading ITEM 1
<ul>
<li class="hs-menu-depth-3">column 1 - item 1</li>
<li class="hs-menu-depth-3">column 1 - item 2</li>
<li class="hs-menu-depth-3">column 1 - item 3</li>
</ul>
</li>
<li class="hs-menu-depth-2">heading ITEM 2
<ul>
<li class="hs-menu-depth-3">column 2 - item 1</li>
<li class="hs-menu-depth-3">column 2 - item 2</li>
<li class="hs-menu-depth-3">column 2 - item 3</li>
<li class="hs-menu-depth-3">column 2 - ITEM 4</li>
</ul>
</li>
<li class="hs-menu-depth-2">heading item 3</li>
</ul>
</li>
</ul>
or see: https://codepen.io/Minegolfer/pen/pozwKwQ
You can use the > to select elements only one layer inwards:
/* subject of answer */
.hs-menu-children-wrapper {
display:none;
}
.hs-item-has-children:hover > .hs-menu-children-wrapper {
display:inherit;
}
/* mockup menu style */
.hs-menu-item {
list-style: none;
width: 160px;
position: relative;
line-height: 30px;
background: #404040;
padding: 0 5px;
box-sizing: border-box;
}
.hs-menu-item:hover {
background: #707070;
}
.hs-menu-item a {
color: white;
text-decoration: none;
}
.hs-menu-children-wrapper {
list-style: none;
position: absolute;
padding: 0;
margin: 0;
top: 0;
left: 160px
}
<ul>
<li class="hs-menu-item hs-menu-depth-1 hs-item-has-children" role="menu">MEGA PARENT
<ul class="hs-menu-children-wrapper">
<li class="hs-menu-item hs-menu-depth-2 hs-item-has-children" role="menuitem">HEADING ITEM 1
<ul class="hs-menu-children-wrapper">
<li class="hs-menu-item hs-menu-depth-3">COLUMN 1 - ITEM 1</li>
<li class="hs-menu-item hs-menu-depth-3">COLUMN 1 - ITEM 2</li>
<li class="hs-menu-item hs-menu-depth-3">COLUMN 1 - ITEM 3</li>
</ul></li>
<li class="hs-menu-item hs-menu-depth-2 hs-item-has-children" role="menuitem">HEADING ITEM 2
<ul class="hs-menu-children-wrapper">
<li class="hs-menu-item hs-menu-depth-3">COLUMN 2 - ITEM 1</li>
<li class="hs-menu-item hs-menu-depth-3">COLUMN 2 - ITEM 2</li>
<li class="hs-menu-item hs-menu-depth-3">COLUMN 2 - ITEM 3</li>
<li class="hs-menu-item hs-menu-depth-3">COLUMN 2 - ITEM 4</li>
</ul></li>
<li class="hs-menu-item hs-menu-depth-2" role="menuitem">HEADING ITEM 3</li>
</ul></li>
</ul>
(not a very visual demo for lack of CSS in original question)

CSS hover over <li> and reveal hidden <ul>

Here is my code as simple as possible for convenience.
#hidden {
display: none;
}
#visible:hover + #hidden {
display: block;
}
<html>
<head>
</head>
<body>
<ul>
<li id="visible">
Names
<ul id="hidden">
<li>name 1</li>
<li>name 2</li>
<li>name 3</li>
<li>name 4</li>
</ul>
</li>
</ul>
</body>
</html>
So I have tried to follow this code example from this webiste and do the same with my code, but it didn't worked.
Could you explain to me why? And show me the correct way ?
Because element with id #hidden is child and not sibling of the element with id #visible. You can use Descendant selector:
#hidden {
display: none;
}
#visible:hover #hidden {
display: block;
}
<ul>
<li id="visible">
Names
<ul id="hidden">
<li>name 1</li>
<li>name 2</li>
<li>name 3</li>
<li>name 4</li>
</ul>
</li>
</ul>
References
Adjacent sibling selectors
It doesn't work because you are using the adjacent sibling selector (+). #hidden is a descendent of #visible so no intermediary selector is required:
#hidden {
display: none;
}
#visible:hover #hidden {
display: block;
}
<ul>
<li id="visible">
Names
<ul id="hidden">
<li>name 1</li>
<li>name 2</li>
<li>name 3</li>
<li>name 4</li>
</ul>
</li>
</ul>
Your current selector would work for a similar structure to the following, which is obviously invalid:
<ul>
<li id="visible">
Names
</li>
<ul id="hidden"> /* #hidden is now a sibling of #visible */
<li>name 1</li>
<li>name 2</li>
<li>name 3</li>
<li>name 4</li>
</ul>
</ul>

Position nested list next to parent list with CSS

i have got a nested list, which is positioned under the parent list:
<ul>
<li> Item 1 </li>
<ul>
<li> Subitem 1 </li>
<li> Subitem 2 </li>
<li> Subitem 3 </li>
</ul>
</ul>
Is there any way to style them with css so that the nested list is right and centered to the parent list? The result should look like this:
- Subitem 1
Item 1 - Subitem 2
- Subitem 3
Best regards
You can try a tabular approach:
.list {
display: table;
}
.list > li, .list > ul {
display: table-cell;
vertical-align: middle;
}
<ul class="list">
<li>Item 1</li>
<ul>
<li>Subitem 1</li>
<li>Subitem 2</li>
<li>Subitem 3</li>
</ul>
</ul>
However, note that the HTML above is invalid, because the inner ul should be a child of li.
With a correct layout, I would use an inline-block approach:
.list > li > ul {
display: inline-block;
vertical-align: middle;
}
<ul class="list">
<li>Item 1
<ul>
<li>Subitem 1</li>
<li>Subitem 2</li>
<li>Subitem 3</li>
</ul>
</li>
</ul>

Menu cannot be showed within DIV with specific width defined

I added a horizational menu in a header of WordPress within a <nav id="hoz-menu"> I have no idea which CSS statement make the menu exceed the block. It is supposed the CSS of the menu is responsive.
Demo can be found from http://jsfiddle.net/yckelvin/nqx2a1ao/
Here is the screen capture of the Chrome debug http://screencloud.net/v/Ernf
Below is HTML code of the menu
<nav id="hoz-menu">
<ul id="hoz-menu" class="topmenu">
<li class="topfirst"><span>Item 1</span>
<ul>
<li>Item 1.1</li>
<li>Item 1.2</li>
</ul></li>
<li class="topmenu"><span>Item 2</span>
<ul>
<li>Item 2.1</li>
<li>Item 2.2</li>
<li>Item 2.3</li>
<li>Item 2.4</li>
<li>Item 2.5</li>
</ul></li>
<li class="topmenu">Item 3</li>
<li class="topmenu">Item 4</li>
<li class="topmenu">Item 5</li>
<li class="topmenu">Item 6</li>
<li class="toplast">Item 7</li>
</ul>
</nav>
the width of <nav id="hoz-menu"> is 420px and CSS is
{
display: block;
}
CSS of <ul id="hoz-menu" class="topmenu">
#hoz-menu ul#hoz-menu, ul#hoz-menu ul {
margin: 0;
list-style: none;
padding: 0;
background-color: #dedede;
border-width: 1px;
border-style: solid;
border-color: #5f5f5f;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
}

Resources