Select all but last list-element - html

I have a list of tags I want to display horizontally. Now for each <li>, but the last one, I want to add a , after the item.
Now, I can do that of course:
ul.tags {
list-style: none;
}
ul.tags > li {
display: inline;
}
ul.tags > li:after {
content: ", ";
}
ul.tags > li:last-of-type:after {
content: "";
}
Now I thought about combining the last two rules, like:
ul.tags > li:not(ul.tags > li:last-of-type):after {
content: ", ";
}
But this does not work. How can I select all but the last <li>?

All that you need is just the :last-of-type within the :not (like in the below snippet). The :not accepts only simple selectors as argument.
Below is what the specifications say about simple selectors:
A simple selector is either a type selector, universal selector, attribute selector, class selector, ID selector, or pseudo-class.
ul.tags > li:not(:last-of-type):after {
content: ", ";
}
ul.tags {
list-style: none;
}
ul.tags > li {
display: inline;
}
<ul class='tags'>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>

Related

How to remove whitespace between ::before and actual content

I want to create a custom numbering style for an ordered list that immitates footnotes.
However, when I do this, via an li::before pseudoelement (see snippet below), if there is a whitespace between the <li> tag and its actual content in the HTML code, there is a space rendered between the custom number and the item content.
What do I have to do to get rid of the whitespace, or at least make it behave consistently (i.e. it always is or is not there), regardless of whether there is one in the HTML code?
ol {
list-style: none;
counter-reset: x;
}
ol li {
counter-increment: x;
}
ol li::before {
content: counter(x);
vertical-align: super;
font-size: smaller;
}
<ol>
<li>no leading space</li>
<li>
leading space
</li>
<ol>
Let's normalize it to be with white space. For all the good reasons. This is done by adding " " to the counter(x) content.
ol {
list-style: none;
counter-reset: x;
}
ol li {
counter-increment: x;
}
ol li::before {
content: " " counter(x) " ";
vertical-align: super;
font-size: smaller;
}
<ol>
<li>no leading space</li>
<li>
leading space
</li>
</ol>
Picking up on #IT goldman's answer: If you don't want that "normalized" space, you could still do it that way, but add position: relative; and a negative rightsetting to the ol li::before rule to move the number towards the beginning of the li contents:
ol {
list-style: none;
counter-reset: x;
}
ol li {
counter-increment: x;
}
ol li::before {
content: " " counter(x) " ";
vertical-align: super;
font-size: smaller;
position: relative;
right: -0.2em;
}
<ol>
<li>no leading space</li>
<li>
leading space
</li>
</ol>

Apply list-style-type only on the parent, not the children

I have an ordered list with a specific value for the list-style-type property and I want it to not affect its children.
Currently, the ordered list has another ordered list nested inside and it inherits the list-style-type value. How can I disable that?
<ol class='custom-ol'>
<li> cat1:
<ol style="list-style-type:lower-alpha">
<li>text 1</li>
<li>text2</li>
</ol>
</li>
<li>
cat2:
<ol style="list-style-type:lower-alpha">
<li>text 3</li>
<li>text 4</li>
</ol>
</li>
the css style
<style>
.custom-ol ol
{
counter-reset: custom-counter;
list-style-type: none;
}
.custom-ol ol li
{
counter-increment: custom-counter;
}
.custom-ol ol li:before
{
content:"(" counter(custom-counter) ") ";
font-weight:bold;
}
</style>
I tried to fix to that way but it's not working at all (update version)
that's what i get
ol.custom-ol
{
counter-reset: custom-counter;
list-style-type: none;
}
ol.custom-ol li
{
counter-increment: custom-counter;
}
ol.custom-ol li:before
{
content:"(" counter(custom-counter) ") ";
font-weight:bold;
}
ol ol {
list-style-type: lower-alpha;
}
I want the parent (where is 1 now will be (1) with the . custom-ol class
and his children be as they are a,b,c without the (1), (2)
You're not targeting your parent ol at all and you're targeting the children ol elements twice. Once through inline styling:
style="list-style-type:lower-alpha"
and once through your CSS file:
.custom-ol ol
{
counter-reset: custom-counter;
list-style-type: none;
}
If you want to disable list-style-type: none on the children elements, then change .custom-ol ol to .custom-ol. This will target your parent ol only.
Alternatively, try adding !important to style="list-style-type:lower-alpha" like this:
style="list-style-type: lower-alpha !important"
This will override any other styles applied to the child ol.
This is what your CSS should look like:
ol.custom-ol
{
counter-reset: custom-counter;
list-style-type: none;
}
ol.custom-ol li
{
counter-increment: custom-counter;
}
ol.custom-ol li:before
{
content:"(" counter(custom-counter) ") ";
font-weight:bold;
}
ol ol {
list-style-type: lower-alpha;
}
ol ol li:before {
content: "";
}

remove pseudo class of first item [duplicate]

This question already has answers here:
Select all 'tr' except the first one
(10 answers)
Closed 8 years ago.
I have a simple unordered list:
<ul id="sub_menu">
<li></li>
<li></li>
<li></li>
<!-- and some more -->
</ul>
I removed any of the list-style-types and created my own with a :pseudo class
#sub_menu ul li:before {
content: "• ";
color: #FFFFFF;
}
what I know would like to know is, what would be the CSS selector look like, if I would like to remove the pseudo class for the first li item of this list.
Thanks
You can exclude the first li, using the :not() selector:
#sub_menu ul li:not(:first-child):before {
content: "• ";
color: #FFFFFF;
}
If you need IE8 compatibility, you may use a combination of sibling selectors, like:
#sub_menu ul li:first-child ~ li:before {
content: "• ";
color: #FFFFFF;
}
EDIT
Also, just a side-note... According to your html, the selector is wrong. If the ul has the id of #sub_menu, it should be
#sub_menu li
instead of
#sub_menu ul li
The following selectors will both work down to IE7:
#sub_menu ul li + li::before
#sub_menu ul li ~ li::before
They behave the same as:
#sub_menu ul li:not(:first-child)::before
Another alternative is the
#sub_menu ul li:nth-child(n+2):before {
content: "• ";
color: #FFFFFF;
}

How to use :before for the third <li> element?

How to add > before the third <li> element without adding new any classes or id's?
Here is the JsFiddle.
HTML:
<ol class="breadcrumb-tasks">
<li>Ethernet</li>
<li>Compputer</li>
<li>Design</li>
</ol>
CSS:
.breadcrumb-tasks{
padding: 0;
list-style: none;
}
.breadcrumb-tasks li {
color: #999;
display: inline-block;
}
.breadcrumb-tasks li + li:before {
color: #ccc;
content: "/\00a0";
}
For the old browsers which don't support :nth-child() pseudo class you could use adjacent sibling selector as follows:
.breadcrumb-tasks li + li + li:before {
content: ">\00a0";
}
And override the content for 4th, 5th,... list items as:
.breadcrumb-tasks li + li:before, /* selects 2nd+ list items */
.breadcrumb-tasks li + li + li +li:before { /* selects 4th+ list items */
color: #ccc;
content: "/\00a0";
}
WORKING DEMO
But for modern browsers support CSS3 selector (including IE9+):
.breadcrumb-tasks li:nth-child(3):before {
content: ">\00a0";
}
WORKING DEMO.
This way, it is always the last one (if you have more than 3).
ol li:last-child:before{
content: ">";
}
JsFiddle
li:nth-child(3):before
{
content: ">";
}
FIDDLE
.breadcrumb-tasks li:last-child:before { content: "› "; }

Are letter/number combinations in HTML lists possible?

Quite simply, I want an ordered list to work like this:
1. Foo
2. Bar
3a. Baz
3b. Qux
4. Etc...
Is there any way to easily do something along these lines in HTML?
Given the following mark-up:
<ol>
<li>Foo</li>
<li>
<ol>
<li>bar</li>
<li>baz</li>
</ol>
</li>
<li>Something else...</li>
</ol>​
The following CSS almost works:
ol {
counter-reset: topLevel;
}
li {
counter-increment: topLevel;
margin-left: 1em;
}
li::before {
content: counter(topLevel) '. ';
margin-right: 0.3em;
}
ol ol {
counter-reset: secondLevel;
}
ol ol li {
counter-increment: secondLevel;
}
ol ol li::before {
content: counter(topLevel) counter(secondLevel, lower-alpha) '. ';
}
JS Fiddle demo.
The only problem with this, so far, is that it contains the topLevel count against both the inner li elements (as you wanted), but also against the outer li (that contains those inner elements), so...not quite there, yet.
And the above problem resolved! ...in those browsers that support the CSS :not() selector:
ol {
counter-reset: topLevel;
}
li {
counter-increment: topLevel;
margin-left: 1em;
}
li:not(.hasChild)::before {
content: counter(topLevel) '. ';
margin-right: 0.3em;
}
ol ol {
counter-reset: secondLevel;
}
ol ol li {
counter-increment: secondLevel;
}
ol ol li::before,
ol li.hasChild ol li::before {
content: counter(topLevel) counter(secondLevel, lower-alpha) '. ';
}
JS Fiddle demo.
I forgot (originally) to note that for this to work (because CSS doesn't have a parent selector (as yet) I had to add a specific class to those li elements with child ol elements in order to appropriately hide the duplication of the number. In this case I chose the class-name .hasChild (as can be seen in the Fiddle).
Incidentally, a small change to the li:not(.hasChild)::before rules, allows for the right-aligned text:
li:not(.hasChild)::before {
content: counter(topLevel) '. ';
width: 2em;
margin-right: 0.3em;
display: inline-block;
text-align: right;
}
JS Fiddle demo.
It doesn't meet your requirements fully and requires some (annoying) changes to your html, but I think it's about as close as you'll get.
http://jsfiddle.net/qGCUk/30/
<ol>
<li>one</li>
<li class="has_children">
<ol>
<li>two.one</li>
<li>two.two</li>
<li>two.three</li>
</ol>
</li>
</ol>
ol,li{
padding:0;
margin:0;
}
ol { counter-reset: item }
li { display: block; padding-left: 0 }
li:before {
content: counters(item, ".") " ";
counter-increment: item
}
LI.has_children:before {
content: " ";
counter-increment: item
}
This is only numbers, as I don't think you can mix numbers and letters. And since there is no selector to select and li which contains and ol, you have to add a class to any li which has a child ol.