I need to properly skin a menu/tree like structure.
Each item is composed by three elements: two floats (one left and one right) and the last non-floated to fill the remaining space automatically expanding the container when possible.
In the first level all renders properly but on sub-levels the width of container is too small.
NOTE: I need each level ul container will be independently sized based on its content.
HTML example structure:
<ul>
<li>
<div class="link">
<span></span>
<span>3434</span>
<span>Item 1</span>
</div>
<ul>
<li>
<div class="link">
<span></span>
<span>123</span>
<span>Item 1.2</span>
</div>
</li>
<li>
<div class="link">
<span></span>
<span>312</span>
<span>Item 1.2342342</span>
</div>
</li>
<li>
<div class="link">
<span></span>
<span>12</span>
<span>Item 1.2234123</span>
</div>
</li>
</ul>
</li>
<li>
<div class="link">
<span></span>
<span>3453</span>
<span>Item 2123123123123123123</span>
</div>
</li>
<li>
<div class="link">
<span></span>
<span>34534</span>
<span>Item asdasdasd</span>
</div>
</li>
</ul>
CSS:
ul {
position: absolute;
background: white;
border: 1px solid black;
overflow: visible;
margin: 0;
padding: 0;
}
li {
position: relative;
margin: 0;
padding: 0.1em 0.5em;
}
ul>li>ul {
left: 100%;
}
.link {
display;
block;
position: relative;
}
.link>span:nth-child(1) {
display: block;
float: left;
width: 1em;
height: 1em;
margin-right: 0.25em;
background: cyan;
}
.link>span:nth-child(2) {
display: block;
float: right;
height: 1em;
margin-left: 0.25em;
background: red;
color: white;
}
.link>span:nth-child(3) {
display: block;
white-space: nowrap;
overflow: auto;
}
Here a jsfiddle to better show the problem
You can increase the width of the .ul>.li>.ul element:
ul>li>ul {
left: 100%;
width:100%;
}
This will make it increase to be the same width as the top level menu:
https://jsfiddle.net/dxr76e1z/1/
You could render inner <ul> as a table and it will autosize to fit its contents:
ul>li>ul {
left: 100%;
display: table;
}
Finally I have found the solution using flexbox model. This method preserve also jQuery animations.
Only CSS update is needed:
ul {
display: block;
position: absolute;
list-style: none;
background-color: orange;
border: 1px solid red;
padding: 0.2em;
}
li {
display: block;
}
ul>li>ul {
left: 100%;
}
.link {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: flex-start;
align-items: stretch;
align-content: stretch;
margin: 0.2em;
}
.link>span {
display: block;
align-self: auto;
}
.link>:nth-child(1) {
flex-shrink: 0;
width: 1em;
background-color: cyan;
margin-right: 0.25em;
}
.link>:nth-child(2) {
order: 1;
flex-shrink: 0;
background-color: red;
margin-left: 0.25em;
white-space: nowrap;
color: white;
}
.link>:nth-child(3) {
flex-basis: 100%;
flex-shrink: 1;
background-color: yellow;
white-space: nowrap;
}
Here the updated jsfiddle.
Related
I have been struggling with this CSS issue, when the overflown content would not have padding applied to it. I can summarize it in this picture:
basically I have set a padding for the internal container that overflows, but for some reason this padding is not propagated for the area that is hidden. After you have scrolled to the end of the container, you can see that no padding is present.
I have been able to pinpoint the problem to internal container not expanding fully inside the overflow zone.. It's a bit hard to explain it so I have prepared a fiddle.
function toggleCollapseMenu() {
document.getElementById("mainMenu").classList.toggle("uncollapsed");
}
:root {
--height: 150px;
}
html,
body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
}
ul {
list-style-type: none;
padding: 0;
margin: 0;
}
a {
text-decoration: none;
}
.app {
height: 100%;
display: flex;
flex-direction: column;
overflow: hidden;
}
#collapseBtn {
display: inline-block;
cursor: pointer;
background-color: black;
color: white;
padding: 0.5rem;
box-sizing: border-box;
position: fixed;
top: 0;
z-index: 999;
border: unset;
width: 200px;
height: 100px;
}
#collapseBtn:hover {
background-color: gray;
}
.menu,
.content {
width: 100%;
}
.menu {
background-color: black;
transition: height 0.8s ease-in;
height: var(--height);
overflow: hidden;
}
.content {
background-color: burlywood;
flex: 1;
overflow: auto;
margin: auto;
}
.menu-container {
overflow-y: hidden;
overflow-x: auto;
height: 100%;
width: 100%;
height: var(--height);
position: absolute;
bottom: 0;
-webkit-transition: height 0.2s ease-in;
-moz-transition: height 0.2s ease-in;
-o-transition: height 0.2s ease-in;
transition: height 0.2s ease-in;
}
.menu-container ul {
background-color: #587c34;
display: flex;
flex-direction: column;
flex-wrap: wrap;
height: 100%;
padding: 1rem;
box-sizing: border-box;
min-width: 100%;
width: 100%;
margin: auto;
}
.menu-container ul li {
min-width: var(--height);
border: 1px solid white;
box-sizing: border-box;
height: 100%;
max-height: var(--height);
}
.menu-container ul li a {
display: block;
width: 100%;
height: 100%;
padding: 0.2rem;
box-sizing: border-box;
}
.menu-container .nav-link-container {
display: flex;
flex-direction: column;
background-color: #f55858;
justify-content: center;
text-align: center;
align-items: center;
height: 100%;
justify-content: start;
}
.menu-container span.nav-link-icon {
background-color: magenta;
font-size: 60px;
}
.menu-container span.nav-link-text {
background-color: lightseagreen;
overflow: hidden;
text-overflow: ellipsis;
font-size: 20px;
margin: auto;
}
.menu.uncollapsed .menu-container {
height: 100vh;
overflow-y: auto;
overflow-x: hidden;
}
.menu.uncollapsed ul {
flex-direction: row;
align-content: start;
}
.menu.uncollapsed ul li {
width: 100%;
height: var(--height);
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/css/all.min.css" rel="stylesheet"/>
<div class="app">
<div class="content">
content
<button id="collapseBtn" onclick="toggleCollapseMenu()">
collapse
</button>
</div>
<div id="mainMenu" class="menu">
<div class="menu-container">
<ul>
<li>
<a>
<div class="nav-link-container">
<span class="nav-link-icon"><i class="fas fa-home"></i></span>
<span class="nav-link-text">One two</span>
</div>
</a>
</li>
<li>
<a>
<div class="nav-link-container">
<span class="nav-link-icon"><i class="fas fa-home"></i></span>
<span class="nav-link-text">One two three</span>
</div>
</a>
</li>
<li>
<a>
<div class="nav-link-container">
<span class="nav-link-icon"><i class="fas fa-home"></i></span>
<span class="nav-link-text">One two three four</span>
</div>
</a>
</li>
<li>
<a>
<div class="nav-link-container">
<span class="nav-link-text">no icon</span>
</div>
</a>
</li>
<li>
<a>
<div class="nav-link-container">
<span class="nav-link-text">no icon</span>
</div>
</a>
</li>
<li>
<a>
<div class="nav-link-container">
<span class="nav-link-text">no icon</span>
</div>
</a>
</li>
<li>
<a>
<div class="nav-link-container">
<span class="nav-link-text">no icon</span>
</div>
</a>
</li>
</ul>
</div>
</div>
</div>
See how the green area (internal overflown content) suddenly ends in the middle of the screen. And at the end there is no padding applied because of it.
Same is when you expand the menu to full-screen (see collapse button) - then vertically there is no padding at the end of the overflown document.
Other fiddle:
http://jsfiddle.net/vkrs38qt/9/
I have tried adding following code snippet to overflown content (menu-container):
min-width: 100%;
width: 100%;
margin: auto;
Because that is what I usually do in such cases, but it has no effect on the container whatsoever in my current scenario. The long story short I would like to know how to apply padding to overflown content from the beginning till the end (both vertically and horizontally) :)
Sorry if the explanation is vague, hopefully the code and pictures will speak for themselves.
.menu-container ul inherits the overflow value from .menu-container, and so you need to override it.
.menu-container ul {
...
overflow: auto;
...
}
Unfortunately, now your content gets covered up. Changing the z-Index works for the horizontal, but the vertical looks odd.
function toggleCollapseMenu() {
document.getElementById("mainMenu").classList.toggle("uncollapsed");
}
:root {
--height: 150px;
}
html,
body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
}
ul {
list-style-type: none;
padding: 0;
margin: 0;
}
a {
text-decoration: none;
}
.app {
height: 100%;
display: flex;
flex-direction: column;
overflow: hidden;
}
#collapseBtn {
display: inline-block;
cursor: pointer;
background-color: black;
color: white;
padding: 0.5rem;
box-sizing: border-box;
position: fixed;
top: 0;
z-index: 999;
border: unset;
width: 80px;
height: 40px;
}
#collapseBtn:hover {
background-color: gray;
}
.menu,
.content {
width: 100%;
}
.menu {
background-color: black;
transition: height 0.8s ease-in;
height: var(--height);
overflow: hidden;
}
.content {
background-color: burlywood;
flex: 1;
overflow: auto;
margin: auto;
}
.menu-container {
overflow-y: hidden;
overflow-x: auto;
height: 100%;
width: 100%;
position: absolute;
bottom: 0;
-webkit-transition: height 0.2s ease-in;
-moz-transition: height 0.2s ease-in;
-o-transition: height 0.2s ease-in;
transition: height 0.2s ease-in;
}
.menu-container ul {
background-color: #587c34;
display: flex;
flex-direction: column;
flex-wrap: wrap;
height: 100%;
padding: 1rem;
box-sizing: border-box;
overflow: auto;
min-width: 100%;
width: 100%;
margin: auto;
}
.menu-container ul li {
min-width: var(--height);
border: 1px solid white;
box-sizing: border-box;
height: 100%;
max-height: var(--height);
}
.menu-container ul li a {
display: block;
width: 100%;
height: 100%;
padding: 0.2rem;
box-sizing: border-box;
}
.menu-container .nav-link-container {
display: flex;
flex-direction: column;
background-color: #f55858;
justify-content: center;
text-align: center;
align-items: center;
height: 100%;
justify-content: start;
}
.menu-container span.nav-link-icon {
background-color: magenta;
font-size: 60px;
}
.menu-container span.nav-link-text {
background-color: lightseagreen;
overflow: hidden;
text-overflow: ellipsis;
font-size: 20px;
margin: auto;
}
.menu.uncollapsed .menu-container {
height: 100vh;
overflow-y: auto;
overflow-x: hidden;
}
.menu.uncollapsed ul {
flex-direction: row;
align-content: start;
}
.menu.uncollapsed ul li {
width: 100%;
height: var(--height);
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/css/all.min.css" rel="stylesheet"/>
<div class="app">
<div class="content">
content
<button id="collapseBtn" onclick="toggleCollapseMenu()">
collapse
</button>
</div>
<div id="mainMenu" class="menu">
<div class="menu-container">
<ul>
<li>
<a>
<div class="nav-link-container">
<span class="nav-link-icon"><i class="fas fa-home"></i></span>
<span class="nav-link-text">One two</span>
</div>
</a>
</li>
<li>
<a>
<div class="nav-link-container">
<span class="nav-link-icon"><i class="fas fa-home"></i></span>
<span class="nav-link-text">One two three</span>
</div>
</a>
</li>
<li>
<a>
<div class="nav-link-container">
<span class="nav-link-icon"><i class="fas fa-home"></i></span>
<span class="nav-link-text">One two three four</span>
</div>
</a>
</li>
<li>
<a>
<div class="nav-link-container">
<span class="nav-link-text">no icon</span>
</div>
</a>
</li>
<li>
<a>
<div class="nav-link-container">
<span class="nav-link-text">no icon</span>
</div>
</a>
</li>
<li>
<a>
<div class="nav-link-container">
<span class="nav-link-text">no icon</span>
</div>
</a>
</li>
<li>
<a>
<div class="nav-link-container">
<span class="nav-link-text">no icon</span>
</div>
</a>
</li>
</ul>
</div>
</div>
</div>
Simple question (snippet below):
<ul> with display: flex
each <li> should have the same size and together must occupy the full width of the <ul>
each <li> has a <a> which the content may have 1 or 2 lines of text.
each <li> has height set to auto to adjust to the <a> content
My problem:
I need the "one-line" links to auto expand to the height of the "two-line" links. Setting height: 100% doesn't work because their parent height it's intentionally set to auto to adjust for content.
But in some cases I'll get two-line links, and some cases all will be one-line. So I need the one-line links to auto-expand when that happens.
How is this possible?
#root {
width: 140px;
box-sizing: border-box;
}
ul {
display: flex;
justify-content: space-between;
margin: auto;
padding: 0;
}
li {
flex-grow: 1;
flex-basis: 30px;
list-style-type: none;
display: inline-block;
border: 1px dotted blue;
height: auto;
}
a {
cursor: pointer;
border: 1px dotted green;
display: inline-block;
background-color: lightblue;
padding: 8px 0px;
}
<div id="root">
<ul>
<li><a>Link 1</a></li>
<li><a>Long Link 2</a></li>
</ul>
</div>
You don't need to use inline-block with flex. Just use display: flex for li and display: block for a. Finally, add the width: 100% for a. It seems match your requirement.
#root {
width: 140px;
box-sizing: border-box;
}
ul {
display: flex;
justify-content: space-between;
margin: auto;
padding: 0;
}
li {
flex-grow: 1;
flex-basis: 30px;
list-style-type: none;
display: flex;
border: 1px dotted blue;
height: auto;
}
a {
cursor: pointer;
border: 1px dotted green;
display: block;
background-color: lightblue;
padding: 8px 0px;
width: 100%;
}
<div id="root">
<ul>
<li><a>Link 1</a></li>
<li><a>Long Link 2</a></li>
</ul>
</div>
you can omit padding from top and bottom of the anchor and use height 100% a{height: 100%;}
#root {
width: 140px;
box-sizing: border-box;
}
ul {
display: flex;
justify-content: space-between;
margin: auto;
padding: 0;
}
li {
flex-grow: 1;
flex-basis: 30px;
list-style-type: none;
display: inline-block;
border: 1px dotted blue;
height: auto;
}
a {
cursor: pointer;
border: 1px dotted green;
display: inline-block;
background-color: lightblue;
height: 100%;
}
<div id="root">
<ul>
<li><a>Link 1</a></li>
<li><a>Long Link 2</a></li>
</ul>
</div>
I have <ul> list and inside <li> i have link <a href="...">
I want the <li> not to be influenced by the content and have fixed size.
My CSS
ul.files {
display: inline-block;
padding: 0;
margin: 0 auto;
}
ul.files li {
display: inline;
}
ul.files li a {
color: black;
float: left;
padding: 8px 15px;
text-decoration: none;
border: 1px solid #ddd;
margin: 0 3px;
background-color: #ffffff;
}
My HTML
<ul class="files">
<li>
<a id="some_id" href="http">123</a>
</li>
</ul>
To be able to set fixed width and height to <li> you need to change display: inline; to inline-block
ul.files li {
display: inline-block;
width: 150px;
height: 150px;
}
To center text
To center content of li you can use display: inline-flex
ul.files li {
display: inline-flex;
justify-content: center;
align-items: center;
width: 150px;
height: 150px;
}
We have a list of boxes with horizonal scrolling, like this:
ul {
padding: 0;
list-style: none;
display: flex;
justify-content: space-between;
flex-wrap: nowrap;
}
li {
display: inline-block;
flex: 0 0 24%;
max-width: 24%;
margin-right: 1.3%;
margin-top: 3px;
height: 140px;
position: relative;
color: #000000;
white-space: normal;
text-align: left;
}
.container {
white-space: nowrap;
background: #fff;
overflow-y: hidden;
overflow-x: scroll;
width: 100%;
position: relative;
height: 160px;
}
.cover {
content: '';
position: absolute;
right: 0;
top: 0;
width: 20px;
height: 100%;
background-color: #ffffff;
z-index: 999;
}
.box {
border: 1px solid #000;
}
<div class="container">
<div class="cover"> </div>
<ul>
<li class="box empty"></li>
<li class="box gradient"></li>
<li class="box gradient"></li>
<li class="box gradient"></li>
<li class="box gradient"></li>
</ul>
</div>
How to make the "cover" div fixed on the right after the div has scrolled horizontally? At the moment it's stuck at the original position, as you can see from this screenshot:
I have a potential solution but I needed to put the overflow onto the <ul>, move the "cover" after the <ul> and make the container display: flex as well. The "cover" is then just relatively positioned back over the <ul>.
I also added a background-color to show the "cover" better for the demo.
ul {
padding: 0;
list-style: none;
display: flex;
justify-content: space-between;
flex-wrap: nowrap;
position: relative;
width: 100%;
overflow-y: hidden;
overflow-x: scroll;
}
li {
display: inline-block;
flex: 0 0 24%;
max-width: 24%;
margin-right: 1.3%;
margin-top: 3px;
height: 140px;
color: #000000;
white-space: normal;
text-align: left;
}
.container {
white-space: nowrap;
background: #fff;
height: 180px;
background-color: white;
display: flex;
}
.cover {
content: '';
position: relative;
left: -20px;
width: 20px;
height: 150px;
background-color: tomato;
}
.box {
border: 1px solid #000;
}
<div class="container">
<ul>
<li class="box empty"></li>
<li class="box gradient"></li>
<li class="box gradient"></li>
<li class="box gradient"></li>
<li class="box gradient"></li>
</ul>
<div class="cover"></div>
</div>
I am using an inline list as a nav menu, and I would like the hyperlink/list item to take up the full height of the container with the label vertically positioned in the center of the container. Here is what I have:
#top-nav-container {
font-size: 14px;
width: 100%;
height: 50px;
overflow: hidden;
top: 0;
left: 0;
position: fixed;
z-index: 500;
background: #3498db;
}
#top-nav-container .nav-contents {
height: 100%;
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-items: center;
}
#top-nav-container .nav-left {
width: 175px;
}
#top-nav-container .nav-mid {} #top-nav-container .nav-right {
margin-left: auto;
text-align: right;
width: 250px;
}
#top-nav-container .top-nav-logo {
max-height: 35px;
float: left;
}
#top-nav-container ul {
margin: 0 0 0 30px;
padding: 0;
float: left;
list-style: none;
display: flex;
/* Removes whitespace between li elements */
flex-direction: row;
align-items: center;
}
#top-nav-container ul li {} #top-nav-container li a {
text-decoration: none;
background: red;
border-right: 1px solid #fff;
color: #fff;
padding: 0 12px;
}
<header id="top-nav-container">
<div class="container nav-contents">
<div class="nav-left">
<a href="#" title="Home">
<img src="http://coneyislandpark.com/imgUploader/logos/Pepsi_logo_2008.png" alt="Home" class="top-nav-logo" />
</a>
</div>
<div class="nav-mid">
<ul>
<li>Home
</li>
<li>About
</li>
<li>Contact
</li>
</ul>
</div>
<div class="nav-right">
Stuff here...
</div>
</div>
</header>
Any other suggestions you have with any of this is greatly appreciated.
You need to add both height and line-height to the links, and also make sure they are either display: block or display: inline-block. Note that inline-block would be preferred:
#top-nav-container li a {
height: 50px;
line-height: 50px;
display: inline-block;
}
Note that on small screens, the Stuff Here... div would get cut off due to having a current width of 250px. Simply turn this down to say 50px (or however wide your container would actually be):
#top-nav-container .nav-right {
width: 50px;
}
I've created a fiddle showing this here.
Hope this helps! :)
You need to modify your CSS a little, see the following snippet:
#top-nav-container {
font-size: 14px;
width: 100%;
height: 50px;
overflow: hidden;
top: 0;
left: 0;
position: fixed;
z-index: 500;
background: #3498db;
}
#top-nav-container .nav-contents {
height: 100%;
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-items: center;
}
#top-nav-container .nav-left {
width: 175px;
}
#top-nav-container .nav-mid {
/* all below rules were added*/
position: absolute;
line-height: 50px;
height: 100%;
left: 50%;
transform: translateX(-50%);
}
#top-nav-container .nav-right {
margin-left: auto;
text-align: right;
width: 250px;
}
#top-nav-container .top-nav-logo {
max-height: 35px;
float: left;
}
#top-nav-container ul {
margin: 0 0 0 30px;
padding: 0;
float: left;
list-style: none;
display: flex;
/* Removes whitespace between li elements */
flex-direction: row;
align-items: center;
}
#top-nav-container ul li {} #top-nav-container li a {
text-decoration: none;
background: red;
border-right: 1px solid #fff;
color: #fff;
padding: 0 12px;
/* all below rules were added*/
height: 50px;
line-height: 50px;
display: inline-block;
}
<header id="top-nav-container">
<div class="container nav-contents">
<div class="nav-left">
<a href="#" title="Home">
<img src="http://coneyislandpark.com/imgUploader/logos/Pepsi_logo_2008.png" alt="Home" class="top-nav-logo" />
</a>
</div>
<div class="nav-mid">
<ul>
<li>Home
</li>
<li>About
</li>
<li>Contact
</li>
</ul>
</div>
<div class="nav-right">
Stuff here...
</div>
</div>
</header>