:last-child pseudo class confusion - css

In this JSFiddle, the last .tab class doesn't get the correct border-radius effect (top right rounded corner).
I think I have my logic correct in saying :last-child selects the last .tab of .tabbed in this case.
What am I doing wrong?
CSS:
body {
background: black;
color: white;
padding: 5px; }
.tabbed {
height: 550px;
}
.tabbed .tab {
padding: 6px 14px;
background: rgba(255,255,255,0.25);
border: 1px solid rgba(255,255,255,0.4);
border-radius: 0px;
border-left-width: 0;
float: left;
}
.tabbed .tab:first-child {
border-radius: 3px 0 0 0;
border-left-width: 1px;
}
.tabbed .tab:last-child {
border-radius: 0 3px 0 0;
}
HTML:
<ul class='tabbed'>
<li class='tab'>Menu 1</li>
<li class='tab'>Menu 2</li>
<li class='tab'>Menu 3</li>
<li class='tab'>Menu 4</li>
<li class='tab'>Menu 5</li>
<li> <br/><br/> </li>
<li class='dummy'>Content 1</li>
<li class='dummy'>Content 2</li>
<li class='dummy'>Content 3</li>
<li class='dummy'>Content 4</li>
<li class='dummy'>Content 5</li>
</ul>

According to this documentation:
The :first-child pseudo class means "if this element is the first
child of its parent". :last-child means "if this element is the last
child of its parent". Note that only element nodes (HTML tags) count,
these pseudo-classes ignore text nodes.
See also W3C doc
It is not applied in your case because the last .tab is not the last child of the parent ul.
If you create two lists, then the css is applied as expected.

In a comment, you state: "It needs to be on the same ul parent. Or another ul, below the last li on the first ul." If that is so, then do this:
<ul class='tabbed'>
<li class='tab'>Menu 1</li>
<li class='tab'>Menu 2</li>
<li class='tab'>Menu 3</li>
<li class='tab'>Menu 4</li>
<li class='tab'>Menu 5</li>
<li>
<ul>
<li class='dummy'>Content 1</li>
<li class='dummy'>Content 2</li>
<li class='dummy'>Content 3</li>
<li class='dummy'>Content 4</li>
<li class='dummy'>Content 5</li>
</ul>
</li>
</ul>
Then this css (with modern browsers):
.tabbed {
height: 550px; }
.tabbed .tab {
padding: 6px 14px;
background: rgba(255,255,255,0.25);
border: 1px solid rgba(255,255,255,0.4);
border-radius: 0px;
border-left-width: 0;
float: left; }
.tabbed .tab:first-child {
border-radius: 3px 0 0 0;
border-left-width: 1px; }
.tabbed .tab:nth-last-child(2) {
border-radius: 0 3px 0 0; }
.tabbed li:last-child {
clear: left;
}
See this fiddle.

To expand on Didier G.'s answer, what you should really be using here is the :first-of-type & :last-of-type pseudo selectors. However, the :nth-of-type selector (and its similar shorthand versions) does not appear to support using a classname for searching, only selecting, e.g. the following will select the first child of .tabbed, if and only if it has the class .tab:
.tabbed .tab:first-of-type
whereas this will select the first child of .tabbed that is of type li:
.tabbed li:first-of-type
I cannot find any reference explicitly stating this behavior, but it is vaguely implied in the specification:
The :nth-of-type(an+b) pseudo-class notation represents an element that has an+b-1 siblings with the same expanded element name
Where an expanded element name is the tag name, and cannot be a class or ID selector.
You can see this behavior live on JSFiddle.

Here's how i would do it:
body {
background: black;
color: white;
padding: 5px; }
.content {clear:both;}
.tall {
height: 550px;
}
.tabbed .tab {
padding: 6px 14px;
background: rgba(255,255,255,0.25);
border: 1px solid rgba(255,255,255,0.4);
float: left; }
.tabbed .tab:first-child {
border-radius: 3px 0 0 0;
border-left-width: 1px; }
.tabbed .tab:last-child {
border-radius: 0 3px 0 0; }
And because i think it seems inappropriate to include the content within a class called tabbed, change the HTML to be structured as:
<div class="tall">
<ul class='tabbed'>
<li class='tab'>Menu 1</li>
<li class='tab'>Menu 2</li>
<li class='tab'>Menu 3</li>
<li class='tab'>Menu 4</li>
<li class='tab'>Menu 5</li>
</ul>
<ul class="content">
<li class='dummy'>Content 1</li>
<li class='dummy'>Content 2</li>
<li class='dummy'>Content 3</li>
<li class='dummy'>Content 4</li>
<li class='dummy'>Content 5</li>
</ul>
</div>
<hr/><!-- just here to show you the height remains -->

Related

Semantically correct separators in list (directly in HTML, not CSS generated)

To achieve this layout of a fully justified menu list, I can not use CSS pseudo-classes to display separators between list items; instead, I have to put the separator directly in the HTML.
Since according to HTML5 standard in an <ul> only <li> and script-supporting elements are allowed, I made the below code. It is valid HTML5 but it seems quirky to me. Any concerns?
ul {
list-style: none;
padding: 0;
margin: 0;
display: flex;
justify-content: space-between;
}
li.home {
padding: 0;
}
li,
script::after {
vertical-align: middle;
padding-top: 10px;
}
nav {
border-bottom: 1px solid black;
border-top: 1px solid black;
height: 40px;
}
script.separator {
display: block;
}
script.separator::after {
content: "*";
}
<nav id="main-menu">
<ul>
<li class="home">
<img src="http://dummyimage.com/40x40/000/fff">
</li>
<script class="separator"></script>
<li class="second">Item 1</li>
<script class="separator"></script>
<li>Item 2</li>
<script class="separator"></script>
<li>One more Item</li>
<script class="separator"></script>
<li>Another Item</li>
<script class="separator"></script>
<li class="last">Contact</li>
</ul>
</nav>
Replace the <script> with another <li> and simply assign a style to it with
ul li:nth-of-type(even) {
display: block;
content: "*";
vertical-align: middle;
padding-top: 10px;
}
This will have the same effect but will look much neater on the code view.
<nav id="main-menu">
<ul>
<li class="home">
<img src="http://dummyimage.com/40x40/000/fff">
</li>
<li></li>
<li class="second">Item 1</li>
<li></li>
<li>Item 2</li>
<li></li>
<li>One more Item</li>
<li></li>
<li>Another Item</li>
<li></li>
<li class="last">Contact</li>
</ul>
</nav>
You may have to tweak the actual CSS in the rule above to suit your look and feel but as a concept I think it's neater and cleaner to have all <li> elements and then use CSS to intelligently select all of the correct ones. This also reduces the number of class=" ... " laying around too.
You can also potentially add further rules so that for example you do not do the seperator CSS on the last of type, so the final li would never be the seperator either:
ul li:nth-of-type(even), ul li :not(:last-of-type) {
display: block;
content: "*";
vertical-align: middle;
padding-top: 10px;
}
I'm not sure this is the exact layout you're after, but can you not use display: table and a border?
ul {
margin: 0;
padding: 0;
list-style: none;
display: table;
width: 100%;
}
li {
display: table-cell;
text-align: center;
}
li:not(:last-child) {
border-right: 1px solid #333;
}
<ul>
<li>Menu 1</li>
<li>Menu 2</li>
<li>Menu 3</li>
<li>Menu 4</li>
<li>Menu 5</li>
</ul>

Ul li with bullets made with ":before" - how to indent 2nd line of text

I have a list with up to four sub levels. Bullets are made with :before.
I have some trouble getting the 2nd line of text line up with the first one.
I have tried setting padding and text-indent like this:
ul {
padding-left: 1em;
text-indent: -1em;
}
- but it doesn't work. Setting list-style-position: outside doesn't seem to work either.
JSFIDDLE here
Any ideas?
Its better to use position: absolute instead of float to align bullets.
.menu {
width: 250px;
}
ul.nav>li>a {
position: relative;
}
/* First level */
ul.nav>li>a:before {
position: absolute;
font-family: 'Glyphicons Halflings';
font-size: 7px;
color: #901a1e;
content: "\e080";
border: 1px solid #d7d7d7;
left: 0;
top: 13px;
}
/* Sub levels */
ul.nav>li ul li>a {
display: inline-block;
vertical-align: top;
padding-left: 10px;
position: relative;
}
ul.nav>li ul li>a:before {
position: absolute;
font-size: 9px;
color: #901a1e;
content: "\25A0";
left: 0;
top: 3px;
}
ul li {
list-style-type: none;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.css" rel="stylesheet"/>
<div class="menu">
<ul class="nav">
<li>Home</li>
<li>Sub menu here
<ul>
<li>Link 2.1 - one more very, very, very, long text</li>
<li class="active">Link 2.2 - active</li>
<li>Link 2.3</li>
</ul>
</li>
<li>Separated link
</li>
<li>Separated link
<ul>
<li>Link 2.1
<ul>
<li>Link 3.1</li>
<li>Link 3.2</li>
<li>Link 3.3
<ul>
<li>Link 4.1 - one more very, very, very, long text</li>
<li>Link 4.2</li>
<li>Link 4.3</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li>One more very, very, very, long separated link</li>
<li>One more separated link</li>
</ul>
</div>
use the same line-height on :before as on the a element
see snippet :
.menu {
width: 250px;
}
/* First level */
ul.nav>li>a:before {
float: left;
margin: 3px 6px 4px 0;
font-family: 'Glyphicons Halflings';
font-size: 7px;
color: #901a1e;
content: "\e080";
border: 1px solid #d7d7d7;
}
/* Sub levels */
ul.nav>li ul li>a:before {
float: left;
margin-right: 6px;
font-size: 9px;
color: #901a1e;
content: "\25A0";
line-height:16px;
}
ul li {
list-style-type: none;
}
ul li a {
line-height:16px;
}
<div class="menu">
<ul class="nav">
<li>Home</li>
<li>Sub menu here
<ul>
<li>Link 2.1 - one more very, very, very, long text</li>
<li class="active">Link 2.2 - active</li>
<li>Link 2.3</li>
</ul>
</li>
<li>Separated link
</li>
<li>Separated link
<ul>
<li>Link 2.1
<ul>
<li>Link 3.1</li>
<li>Link 3.2</li>
<li>Link 3.3
<ul>
<li>Link 4.1 - one more very, very, very, long text</li>
<li>Link 4.2</li>
<li>Link 4.3</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li>One more very, very, very, long separated link</li>
<li>One more separated link</li>
</ul>
</div>
Below code should work:
.menu {
width: 250px;
}
ul{
list-style:none;
}
/* Setting the position of <a> and a:before*/
ul.nav li a{
position:relative; /* Setting this to relative so that we position a:before absolute to <a> */
padding-left:10px; /* We are moving the text to right by 10px */
display:block;
}
ul.nav li a:before{
position:absolute; /* This is the main css rule which gets our desired result */
left:-5px; /* setting the left position */
top:4px; /* setting the top position */
}
/* Setting Styles of <li> */
ul.nav>li>a:before {
font-family: 'Glyphicons Halflings';
font-size: 7px;
color: #901a1e;
content: "\e080";
border: 1px solid #d7d7d7;
}
ul.nav>li ul li>a:before {
font-size: 9px;
color: #901a1e;
content: "\25A0";
}
<div class="menu">
<ul class="nav">
<li>Home</li>
<li>Sub menu here
<ul>
<li>Link 2.1 - one more very, very, very, long text</li>
<li class="active">Link 2.2 - active</li>
<li>Link 2.3</li>
</ul>
</li>
<li>Separated link
</li>
<li>Separated link
<ul>
<li>Link 2.1
<ul>
<li>Link 3.1</li>
<li>Link 3.2</li>
<li>Link 3.3
<ul>
<li>Link 4.1 - one more very, very, very, long text</li>
<li>Link 4.2</li>
<li>Link 4.3</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li>One more very, very, very, long separated link</li>
<li>One more separated link</li>
</ul>
</div>

Constrain height of a Bootstrap dropdown with hierarchical submenus

I'm trying to constrain the height of a dropdown menu which itself has dropdown submenus. Using max-height: 150px; overflow-y: scroll; on the parent menu successfully prevents it from scrolling, but it causes the submenu to no longer render.
How can I constrain the height of the parent menu without breaking the submenu? I've tried the following without success: bootply
HTML
<nav class="navbar navbar-inverse navbar-static-top marginBottom-0" role="navigation">
<ul class="nav navbar-nav">
<li class="dropdown">Dropdown <b class="caret"></b>
<ul class="dropdown-menu fixed-height">
<li>Dropdown Link 1</li>
<li>Dropdown Link 2</li>
<li>Dropdown Link 3</li>
<li>Dropdown Link 4</li>
<li>Dropdown Link 5</li>
<li>Dropdown Link 6</li>
<li class="divider"></li>
<li class="dropdown dropdown-submenu">Dropdown Link 7
<ul class="dropdown-menu">
<li>Dropdown Submenu Link A</li>
<li>Dropdown Submenu Link B</li>
<li>Dropdown Submenu Link C</li>
<li>Dropdown Submenu Link D</li>
</ul>
</li>
</ul>
</li>
</ul>
</nav>
CSS
.fixed-height {
overflow-y: scroll;
max-height: 150px;
}
.dropdown-submenu {
position:relative;
}
.dropdown-submenu > .dropdown-menu {
top:0;
left:100%;
margin-top:-6px;
margin-left:-1px;
-webkit-border-radius:0 6px 6px 6px;
-moz-border-radius:0 6px 6px 6px;
border-radius:0 6px 6px 6px;
}
.dropdown-submenu > a:after {d
isplay:block;
content:" ";
float:right;
width:0;
height:0;
border-color:transparent;
border-style:solid;
border-width:5px 0 5px 5px;
border-left-color:#cccccc;
margin-top:5px;
margin-right:-10px;
}
.dropdown-submenu:hover > a:after {
border-left-color:#555;
}
.dropdown-submenu.pull-left {
float:none;
}
.dropdown-submenu.pull-left > .dropdown-menu {
left:-100%;
margin-left:10px;
-webkit-border-radius:6px 0 6px 6px;
-moz-border-radius:6px 0 6px 6px;
border-radius:6px 0 6px 6px;
}
JS
(function($){
$(document).ready(function(){
$('ul.dropdown-menu [data-toggle=dropdown]').on('click', function(event) {
event.preventDefault();
event.stopPropagation();
$(this).parent().siblings().removeClass('open');
$(this).parent().toggleClass('open');
});
});
})(jQuery);

Gap on top and bottom when selecting button with jQuery

I'm trying to change the background color of a button after hovering over it with jQuery. However, everytime I try I seem to be getting a gap on the top and bottom of each button rather than the whole button. Here's my jsFiddle: http://jsfiddle.net/Z5M2a/
HTML:
<div id="side-bar">
<ul class="side-nav">
<li class="divider"></li>
<li class="menuOption">Link 1</li>
<li class="divider"></li>
<li class="menuOption">Link 2</li>
<li class="divider"></li>
<li class="menuOption">Link 3</li>
<li class="divider"></li>
<li class="menuOption">Link 4</li>
<li class="divider"></li>
</ul>
</div>
CSS:
div#side-bar {
float: left;
width: 187px;
height: 100%;
min-height: 300px;
text-align: center;
background-color: #e9e9e9;
}
.side-nav {
padding-top: 0px;
}
.menuOption {
width: 187px;
height: 25px;
line-height: 25px;
}
div#side-bar ul li a {
color: #000;
text-decoration: none;
}
You need to reset the margin values for you li's. Currently foundation is giving them a margin-bottom of 0.4375em.
Add something like this to your CSS:
.side-bar li {
margin-bottom:0:
}
UPDATE:
Working link here:
http://codepen.io/alexbaulch/pen/wKFvf

CSS display li in special format

If I have an Ul that contains
<UL class="level2">
<li>
<a>Link1</a>
</li>
<li>
<a> Link2</a>
</li>
<li>
<a> Link 3</a>
</li>
<li class="hasChildren">
<a>Navigation</a>
<ul>
<li>Navigation 1 </li>
<li>Navigation 2</li>
<li>Navigation 3 </li>
<li>Navigation 4</li>
<li>Navigation 5</li>
</ul>
</li>
I need to display the li that don't have children in block and I need the li that haschildren to be displayed inline next to it not under it any idea
I need to have :
Link1 Navigation
Link2 Navigation1 Navigation4
Link3 Navigation2 Navigation5
Navigation3
Something like this?
CSS:
ul {
width: 600px;
position: relative;
margin: 0;
padding: 0;
}
li {
display: block;
width: 300px;
background: Red;
}
li.hasChildren {
position: absolute;
top: 0;
right: 0;
background: Green;
}
li.hasChildren ul {
width: auto;
margin: 0;
padding: 0;
}
li.hasChildren ul li {
background: Green;
}
HTML:
<ul>
<li>Item #1</li>
<li>Item #2</li>
<li class="hasChildren">
Item #3
<ul>
<li>Sub-item #1</li>
<li>Sub-item #2</li>
</ul>
</li>
<li>Item #4</li>
<li>Item #5</li>
</ul>

Resources