100% children height in horizontal navigation with dynamic logo/element height - css

I've browsed around for a while but I believe I have a slightly more unique situation here.
I have a simple navigation which is a <ul> list, with each <li> containing an anchor <a>. The first <li> contains an image which is the logo.
I'd like for each of the subsequent <li> AND <a> elements to expand to the height of the logo, whatever it may be (I would like for the only static height in this solution to be defined on the logo's image, if possible).
The elements should also be vertically centered.
When you hover on the <a> tags, the background and cursor selection should cover the entire height.
I've tried using display: flex; and display: table-cell, with vertical-align: middle and a bunch of other things. I've almost got it but there is some empty space above and below the <a> tags. The only way I can see to fix it is to use a static height on the <a> tags, but I'm posting here to see if anyone knows of any alternatives.
Please note that this doesn't have to be a cross-browser solution (although that would be nice).
Also note that these elements will include a sub-navigation dropdown, so solutions which might include overflow: hidden may not be applicable in that case.
Here is the code:
a {
font-family: 'Trebuchet MS';
text-decoration: none;
}
nav {
background: #444;
}
nav > ul > li {
display: table-cell;
vertical-align: middle;
}
nav > ul > li img {
display: table-cell;
vertical-align: middle;
height: 24px;
padding: 24px;
}
nav > ul > li a {
display: table-cell;
vertical-align: middle;
padding: 24px;
color: #fff;
}
nav > ul > li:hover a {
cursor: pointer;
background: white;
color: #444;
}
<nav role="navigation">
<ul>
<li>
<img src="http://i.imgur.com/ZPB7f3l.png" />
</li>
<li>About
</li>
<li>Work
</li>
<li>Ideas
</li>
<li>Contact
</li>
</ul>
</nav>
Here is the fiddle: http://jsfiddle.net/0br6r0sh/1
Any advice is appreciated!
Thanks,
Ryan

I've tried to implement your requirements using Flexbox. Unfortunately not in a cross browser fashion as it only works on Chrome.
The <img> is given a display: block to remove all padding/margin around it. I've used three sets of display: flex, for the <ul>, <li> and <a>.
a {
font-family: 'Trebuchet MS';
text-decoration: none;
}
nav {
background: #444;
}
nav > ul {
display: flex;
flex-direction: row;
align-items: stretch;
}
nav > ul > li {
background-color: #555;
display: flex;
}
nav > ul > li img {
height: 24px;
padding: 24px;
background-color: #ccc;
display: block;
}
nav > ul > li a {
display: flex;
flex-direction: column;
justify-content: center;
padding: 0 24px;
color: #fff;
background-color: #666;
}
nav > ul > li:hover a {
cursor: pointer;
background: white;
color: #444;
}
<nav role="navigation">
<ul>
<li>
<img src="http://i.imgur.com/ZPB7f3l.png" />
</li>
<li>About
</li>
<li>Work
</li>
<li>Ideas
</li>
<li>Contact
</li>
</ul>
</nav>

Related

Make li element width the max of siblings, itself, and parent li

I've looked at several related posts here and none seem to cut to the core of my challenge.
The scenario is that I have an li element that contains a ul element. I want the widths of the li elements inside the contained ul to be at least as wide as the parent li.
Below are two examples. The first example displays the way I want it to. The second illustrates the issue. I want the items that start "Sub-Item 1" and "Sub-Item 2" to take on the width of the item that starts "Long Item". If you run the code snippet it should be pretty clear what I am after.
I am looking for a 100% CSS solution.
Any assistance would be appreciated.
<style>
ul {
padding:0;
}
ul li {
position: relative;
display: inline-block;
list-style: none;
text-decoration: none;
text-align: center;
float: left;
background-color: red;
white-space:nowrap;
}
ul li ul {
position: absolute;
display: flex;
flex-direction: column;
text-align: left;
background-color: lightgoldenrodyellow;
padding:0;
}
ul li ul li {
text-align: left;
width: 100%;
margin-left: 0;
border-style: none;
background-color: lightgoldenrodyellow;
padding:0;
}
</style>
<div style="position:absolute;top:0;">Example 1
<ul>
<li>
Short Item
<ul>
<li>This is longer than First Item and displays as desired.</li>
<li>Filler - width is same as sibling</li>
</ul>
</li>
</ul>
</div>
<div style="position:absolute; top:200px;">Example 2
<ul>
<li>
Long Item - This is deliberately longer. I want the width of li below to display as wide but it doesn't
<ul>
<li>Sub-Item 1: Shorter than Long Item and does NOT display as desired</li>
<li>Sub Item 2: Filler - width is same as sibling</li>
</ul>
</li>
</ul>
</div>
This can be accomplished by using flex and wrapping the "Short Item" text in a span tag.
ul {
display: flex;
padding:0;
}
ul li {
position: relative;
display: flex;
flex-basis: auto;
flex-direction: column;
list-style: none;
text-decoration: none;
background-color: red;
white-space:nowrap;
}
span{
flex-basis: auto;
flex-grow: 1;
}
ul li ul {
display: flex;
flex-direction: column;
text-align: left;
background-color: lightgoldenrodyellow;
padding:0;
}
ul li ul li {
text-align: left;
width: 100%;
margin-left: 0;
border-style: none;
background-color: lightgoldenrodyellow;
padding:0;
}
<div>Example 1
<ul>
<li>
<span>Short Item</span>
<ul>
<li>This is longer than First Item and displays as desired.</li>
<li>Filler - width is same as sibling</li>
</ul>
</li>
</ul>
</div>

show nested unordered list horizontally

I have a nested unordered list and I have to show them horizontally.
This is a link
enter code here JSFiddle link
Currenly it is showing first link in different line
but I want to display as :
Home News Contact About
You need to set the display to inline-block in li a, that will allow them to stack horizontally.
li a {
display: inline-block;
color: white;
text-align: left;
padding: 16px;
text-decoration: none;
}
To reverse the order use float:right;
If you want the same as in the link.. then just remove the second ul tag which is before News li
Hope this will help you.
The answer to your problem is flexbox, if the element has a style display: flex, you can define the direction of each items inside it (horizontal/ vertical).try this:
.main_menu {
display: flex;
flex-direction: row;
width: 100%;
}
ul {
list-style-type: none;
margin: 0;
padding: 0;
overflow: hidden;
background-color: #333333;
display: inline-block;
display: flex;
flex-direction: row;
}
li a {
display: block;
color: white;
text-align: left;
padding: 16px;
text-decoration: none;
}
li a:hover {
background-color: #111111;
}
<ul >
<li class="main_menu">Home
<ul>
<li>News</li>
<li>Contact</li>
<li>About</li>
</ul>
</li>
</ul>
This link will explain a lot about flexbox.
Hope it helps

Bootstrap nav-bar: how to vertical align wrapped-/multiple line text

I'm trying to vertical align text on a bootstrap navbar item. The text is wrapped on two lines. Its no problem to align a single line text but it gets much more difficult to vertical-align when its on two lines. I cant use line-height are there any alternatives? I havent seen any good solutions on wrapped text, many solutions doesn't take into account multiple lines of text.
HTML code
<ul class="nav navbar-nav">
<li class="dropdown">
SHORT SINGLE LINE
</li>
<li class="dropdown">
VERY LONG TEXT, WRAPPED TEXT
</li>
</ul>
CSS code
.navbar-nav > li > a
{
height: 58px;
line-height: 19px;
padding-top: 10px;
text-align: center;
}
You can use display:table-cell and display:table on the parent div instead of float:left; on the lis.
I am sure bootstrap nav elements are floated. Check this code:
.navbar-nav > li > a
{
height: 58px;
line-height: 19px;
text-align: center;
padding: 0 5px;
}
.navbar-nav{
display: table;
background: #f5f5f5;
padding: 0;
margin: 0;
}
.navbar-nav > li{
display: table-cell;
vertical-align: middle;
padding: 10px;
float: none !important;
text-align: center;
border-left: 2px solid #fff;
}
.navbar-nav > li:first-child{border: 0;}
<ul class="nav navbar-nav">
<li class="dropdown">
SHORT SINGLE
</li>
<li class="dropdown">
VERY LONG TEXT, <br> done WRAPPED TEXT
</li>
</ul>
this is all what you need :
.navbar-nav > li > a
{
text-align: center;
display: inline-block;
vertical-align: middle;
}
and you have to remove these two :
height: 58px;
line-height: 19px;
LIVE DEMO
.navbar-nav > li > a
{
height: 58px;
line-height: 19px;
padding-top: 10px;
text-align: center;
}
you just remove that part, its not neccesary, the text stays vertically centered on its own

CSS unable to get rid of UL's first and last child's dividers

I have a nav that holds a ul with several ils. The problem is that im unable to get rid of the ul's first and last child's divider.
here's a demo: http://jsfiddle.net/Rvs3C/1/
i've added this code to my CSS file but seems like it makes no difference:
nav ul a li:first-child{
content: none;
}
nav ul a li:last-child{
content: none;
}
You markup is wrong. The corret way is <a> tag being the children of tag <li>.
The way you made ​​the correct selector would:
nav ul a:first-child li{
content: none;
}
nav ul a:last-child li{
content: none;
}
But remembering, this is not the right way to do.
The correct is change you html to:
<ul class="showing">
<li>home</li>
...
As mentioned elsewhere your HTML structure is off, li must me a direct child of ul, no other element as a child is valid. With this said, you also need to change your selectors per the below.
Updated Fiddle
HTML
<nav>
<ul class="showing">
<li>home
</li>
<li>about me
</li>
<li>content
</li>
<li>browse
</li>
<li>rate
</li>
<li class="nav_arr"><img src="http://www.irvinewelsh.net/images/arrow-left.png" />
</li>
</ul>
</nav>
CSS
nav {
margin-right: 150px;
}
nav ul {
background-color: #494A4C;
overflow: hidden;
text-align: right;
}
nav li img {
margin-left: 20px;
vertical-align: top;
}
nav ul li a {
color: white;
text-decoration: none;
font-family:arial;
font-size: 14px;
padding: 0px;
font-weight: bold;
}
nav ul li:first-child:before {
content: none;
}
nav ul li:last-child:before {
content: none;
}
nav li:before {
content:"|";
padding: 5px;
font-weight: bold;
color:lightblue;
font-size: 20px;
}
nav ul li {
display: inline-block;
}

Make inline-block element take up no vertical space

I have an evenly distributed menu like :
HTML
<nav>
<ul>
<li>Home
</li>
<li>About
</li>
<li>Contact
</li>
<li>Blog
</li>
</ul>
</nav>
CSS
nav ul {
padding:0;
margin:0;
text-align: justify;
text-transform: uppercase;
background-color: #000;
}
nav ul:after {
content:'';
width: 100%;
display: inline-block;
height: 0;
line-height: 0;
font-size: 0px;
}
nav ul li {
display: inline-block;
}
nav ul li a {
color: #fff;
}
This works great to spread the menu items accross the whole width of the bar as can be seen in this fiddle: http://jsfiddle.net/SjDEX/.
However, you can also see that a result of the ::after element the height of the ul is increased making extra space below the menu items.
Is there a way to get rid of this by making the after element not take up vertical space?
Setting its height to 0 does nothing and changing its display to block or something else breaks the layout.
It is the ul itself that has that height, not the :after, so just add
nav ul {
height: 20px;
}
Fiddle
And this code can be reduced to this:
nav ul:after {
content:'';
width: 100%;
display: inline-block;
}

Resources