Using CSS to style a numbered list - css

I need HTML to produce output similar to:
1. Some title
1.1 blah blah
(a) blah blah blah
(b) blah blah
1.2 blah blah
I believe that because of the need for parenthesis round the letters that I cannot use the ordered list tag for this. Obviously it can be done with a table, but I'd much rather use CSS. However I'm at a loss as to how to do this.
If lines wrap to the next line, they should continue under the text like an ordered list would.
UPDATE
I have tried
OL {
counter-reset: numeric
}
OL LI OL LI OL {
counter-reset: latin
}
LI {
display: block
}
LI:before {
content: counters(numeric, ".") " ";
counter-increment: numeric
}
OL LI OL LI OL LI:before {
content: "(" counter(latin, lower-latin) ") ";
counter-increment: latin
}
and HTML such as:
xxx
<ol>
<li>one
<ol>
<li>onedotone</li>
<li>onedottwo
<ol>
<li>A</li>
</ol>
</li>
</ol>
<li>two</li>
</ol>
produces this
xxx
1 one
1.1 onedotone
1.2 onedottwo
(a) A
2 two
Unfortunately, my requirements are exactly as stated in the original question. So my CSS fails in these areas.
There needs to be a full stop after 1 and after 2 but not after 1.1 and 1.2
1 and 1.1 should not be indented and the text for both of them needs to be aligned to the same place. So the word onedotone needs to be exactly below the word one. Also there needs to be a bigger gap than one space between the number and the text.
The (a) needs to line up with the words onedottwo, and again there needs to be a bigger gap than one space between (a) and A.
padding-left is not the answer, as it does not help line up the text after the numbers, You get
1 one
1.1 onedotone
instead of
1. one
1.1 onedotone
This is beyond my CSS capabilities. Unless anyone has the expertise to point me in the right direction, I fear that I will have to fall back on using a table.

Below is a sample on how the desired result can be achieved using <ol> (ordered lists) and CSS counters. It has a bit of a hack-ish feel about it because of the expectation that when a line is wrapped around, it should not start from under the numberings. Otherwise, I feel this method is much better than manually keying in the numbers (or) using tables.
Consistent spacing between the numbering and text is obtained by setting a width to the li:before pseudo-element and making its display as display: inline-block. Modify the width based on how much spacing is required. Note that when modifying the width, the margin-left and padding-left also have to be modified accordingly to maintain the styling.
CSS Counters have reasonably good browser support also.
.level1, .level2, .level3 {
list-style-type: none;
}
.level1 {
counter-reset: level1; /* first level counter - for 1, 2, 3 */
}
.level2 {
counter-reset: level2; /* second level counter - for 1.1, 1.2 */
}
.level3 {
counter-reset: level3; /* third level counter - for (a), (b) */
}
li {
display: block;
}
li:not(:last-child):after, li > ol:before{
content: " ";
display: block;
position: relative;
height: 20px; /* this is filler where height should be equal to required line height */
left: 0px; top: 100%;
}
.level1, .level2, .level3 {
margin: 0;
padding: 0;
}
.level1 > li, .level3 > li {
padding-left: 40px;
}
li:before {
margin-left: -40px;
/* following 2 props are for consistent spacing between numbering and text */
width: 40px;
display: inline-block;
}
.level1 > li{
font-weight: bold;
}
.level1 > li:before, .level1 > li * {
font-weight: normal;
}
.level1 > li:before {
content: counter(level1)"."; /* display current item number + dot */
counter-increment: level1; /* increment counter everytime a new element of that level is encountered */
}
.level2 > li:before {
content: counter(level1)"." counter(level2); /* format level 1 counter + dot + level 2 counter */
counter-increment: level2;
}
.level3 > li:before {
content: "(" counter(level3, lower-latin)") "; /* format ( + level3 counter + ) */
counter-increment: level3;
}
<ol class='level1'>
<li>one
<ol class='level2'>
<li>one dot one - has some really really lengthy text which wraps around to the next line when it overflows the width.</li>
<li>one dot two
<ol class='level3'>
<li>A</li>
<li>B - has some really really lengthy text which wraps around to the next line when it overflows the width.</li>
</ol>
</li>
</ol>
</li>
<li>two - has some really really lengthy text which wraps around to the next line when it overflows the width.</li>
</ol>
Feedback to comments:
The {content: "\a"; white-space: pre;} trick does not quite work with inline-block elements. The inner level li tags are inline-block in our case (for reasons explained above in 2nd paragraph) and hence that particular trick doesn't work. The alternate is to insert a blank filler line with height of the line equal to the required line-height and position it below the li tag. Note that the selector used is li:not(:last-child):after because we don't need an extra line break after the last li (if we do not do it, we will have double line space after the inner li ends). This is a CSS3 selector and so might not work with lower versions of IE. If you need to support those versions also then we would need to tweak it further (or simpler would be to use br).
You were on the correct path here, but the :before pseudo-element (which has the numbering) is not on the element with class='level1'. It was on the .level1 > li and hence doing a reset of font-weight for selector .level1 > li:before, .level1 > li * would fix it. As you would have already known/guessed, .level1 > li * means every element under the level one li.

Related

Unordered list item bullet point sitting above text

I'm still pretty new to CSS so this might be a silly question.
The list uses a hyphen rather than a bullet style. The bullet is sitting above the text line rather than next to the text. I've tried a range of methods that have been offered on here but it's not budging.
Here is the css I've got at the moment:
li {
list-style-position: inside;
position: relative;
padding-left: inherit;
}
ul, li:before {
content: '–';
vertical-align: middle;
position: relative;
display: list-item;
}
You can target the list style marker with ::marker pseudo class:
ul {
list-style-position: inside;
}
li {
background: dodgerblue;
}
li::marker {
content: '-';
color: hotpink;
}
<ul>
<li><br>
God's own country</li>
</ul>
I had a similar issue once, I solved it removing the p tags from the text inside the list on the HTML file, there was no need to change anything in the CSS.
You can put the text inside the li tags without the paragraph tags. This must have something to do with inline and block elements behaviour.
li {
list-style-position: inside;
}
<!-- notice that the first item has the <p> tag while the second has not -->
<ul>
<li><p>Some text with the paragraph tag.</p></li>
<li>Some text without the paragraph tag.</li>
</ul>

Seemingly over-complicated CSS list styling that SHOULD be easy

I need to create a style for ordered lists that follows this format:
(a) List Item 1
(b) List Item 2
(1) List Item 2.1
(2) List Item 2.2
(i) List Item 2.2.1
(ii) List Item 2.2.2
Unfortunately, list-style-type doesn't work because there are no options that show the numbers as listed above, with parentheses.
LOTS of researching has brought about nothing but ugly hacks, for example:
ol {
list-style-type: none;
}
ol>li:before {
content: "(" counter(lvl1, lower-alpha) ") ";
}
ol li {
counter-increment: lvl1;
}
ol ol>li:before {
content: "(" counter(lvl2, decimal) ") ";
}
ol ol>li {
counter-increment: lvl2;
}
ol ol ol>li:before {
content: "(" counter(lvl3, lower-roman) ") ";
}
ol ol ol>li {
counter-increment: lvl3;
}
which works to some extent, removing the list numbering with list-style-type: none; and inserting the number surrounded with parentheses at the beginning of the li. This makes modifying other related styling horrific, as I can't figure out how to line things up nicely etc (I don't think its even possible). It also makes list-style-position redundant, because the numbers are ALWAYS inside the li.
Basically, I'm looking for a way to reproduce this kind of list numbering in CSS: (note text alignment etc)
ANY help VERY MUCH appreciated!!
You're almost there.
Since you're removing list-style, you can restore the position of the counters by applying padding to the list items and then pulling the counters into that padding with a negative margin (or one of many similar techniques e.g. hanging indent)
li {
padding: 2em;
}
li:before {
/* Take counter out of flow and pull it into padding space */
float: left;
margin-left: -2em;
}
You also need to sprinkle some counter-reset into the mix for each level of ol nesting.
JSFiddle showing a full working example with all the nesting code here: http://jsfiddle.net/thefrontender/tzzbh/2/

Bullets disappear with CSS3 columns

The bullets on my list items disappear when I convert them to columns using CSS3. Any ideas why or suggestions on how to correct it?
See the example: http://jsfiddle.net/gduDm/1/
ul li {
list-style-type: disc !important;
column-break-inside: avoid;
}
ul {
list-style-type: disc !important;
margin-top: 1em;
column-count: 2;
column-gap: 0.5em;
}
I think the bullets are there, but they're being rendered to the left of the viewing area. Try:
list-style-position: inside;
Adding both padding-left and a negative text-indent to the list elements seems to produce the desired result:
ul li {
padding-left: 1em;
text-indent: -1em;
}
ul {
list-style: inside disc;
}
http://jsfiddle.net/mblase75/gduDm/4/
Alternatively, add a margin-left to the list element (instead of the list) and use outside bullets:
ul li {
margin-left: 1em;
}
ul {
list-style: outside disc;
}
http://jsfiddle.net/mblase75/gduDm/9/
Setting margin-left:1em makes the bullets appear without messing with the text indentation.
After trying the first answer here, I was having issues with my list items spilling onto a second row and not lining up. Using column-gap I was able to move the second column over and see the bullets.
Source: http://karlikdesign.com/how-to-split-a-list-into-two-columns-with-pure-css/
<!– CSS CODE –>
.two-columns {
-webkit-column-count: 2;
-moz-column-count: 2;
column-count: 2;
-webkit-column-gap: 40px;
column-gap: 40px;
-moz-column-gap: 40px;
}
Some of the other solutions are pretty good, but all the ones I tried caused various side effects for me. I made some small tweaks and tried to get it as close to perfect as possible.
ul {
column-count:2;
}
ul.solution {
margin-left:-0.6em;
margin-right:0.6em;
}
ul.solution > * {
margin-left:0.6em;
margin-right:-0.6em;
}
Experimental Group
<ul class="solution">
<li>
This solution is pretty similar to the others.
</li>
<li>
It does not require you to put the bullets inside, so you can keep your left edge clean if you want.
</li>
<li>
This fixed it for me in IE11 while also not impacting the appearance on Chromium, so I didn't have to do any browser filtering.
</li>
</ul>
Control Group
<ul>
<li>
This solution is pretty similar to the others.
</li>
<li>
It does not require you to put the bullets inside, so you can keep your left edge clean if you want.
</li>
<li>
This fixed it for me in IE11 while also not impacting the appearance on Chromium, so I didn't have to do any browser filtering.
</li>
</ul>

CSS property to make text wrappable at any place

Is there a CSS property that tells the browser to word-wrap at any position, not only at word boundaries?
My current issue is this. I am faced with HTML similar to this: (I cannot change the HTML, unfortunately)
<div id='categories'>Categories:
<ul>
<li>Category One</li>
<li>Category Two</li>
<li>Category Three</li>
</ul>
</div>
I want it to display in a flowing manner according to the width of the viewport:
Categories: • Category One • Category Two • Category Three
|----------------------------------------------------------------| (viewport)
Categories: • Category One • Category Two
• Category Three
|----------------------------------------------| (viewport width)
Categories: • Category One
• Category Two • Category Three
|----------------------------------| (viewport width)
... but NOT word-breaking within a category name.
So I tried this:
#categories ul {
display: inline;
}
#categories li {
display: inline;
padding: 0 1em;
white-space: nowrap;
}
#categories li:before {
content: '• ';
}
Unfortunately this causes them all to run in one line. So I need to be able to tell the ul to allow wrapping anywhere between any adjacent lis. How do I do that?
I need a CSS-only solution; I cannot change the HTML...
A useful trick for wrapping boxes is to make them all float: left. If I do this to your example, then I get the layout you want except for "Categories:" being pushed to the right. Unfortunately, I don't know of a way to select the text so as to make it floated.
We can use content to re-insert "Categories:" as one of the floated boxes, which leaves the problem of how to hide the existing "Categories:" text without hiding the other contents of #categories. The cleanest way I thought of was to make it transparent. However, this is a CSS3 feature; also, this loses any inherited color due to the need to explicitly set it on the ul.
This stylesheet produces everything you want, but needs some tweaking for spacing.
#categories {
color: transparent;
}
#categories ul {
color: black;
}
#categories li {
display: inline;
float: left;
padding: 0 1em;
white-space: nowrap;
}
#categories li:before {
content: '• ';
}
#categories li:first-child:before {
content: 'Categories: • ';
}
Maybe this?
<ul>Categories: <li>Category One</li><wbr><li>Category Two</li><wbr><li>Category Three</li></ul>

Getting rid of li last item counter

I have a annoying problem .. I want my first 4 items in a list to be numbered but I wanna leave fifth item out of numbering .. here is my css :
#alternate_navigation ol
{
display:block;
padding:0;
margin:0;
counter-reset: item;
}
#alternate_navigation li
{
display:block;
padding:0px 0px 0px 10px;
margin:0;
background: url('images/list_bg.jpg') no-repeat;
height:19px;
width:99%;
border-bottom:1px solid #B9B5B2;
}
#alternate_navigation li:before
{
content: counter(item) ". ";
counter-increment: item ;
}
RESULT :
Online Booking
Coupon Ordering
Print Letters
Send Emails
View orders
How could I achieve for last item not to be numbered like this :
Online Booking
Coupon Ordering
Print Letters
Send Emails
View orders
and yes HTML
<div id="alternate_navigation">
<ol>
<li>Online Booking</li>
<li>Coupon Ordering</li>
<li>Print Letters</li>
<li>Send Emails</li>
<li>View orders</li>
</ol>
<div>
Thank you for any response
After your current CSS, add:
#alternate_navigation li:last-child:before {
content: "";
counter-increment: none;
}
That should 'reset' the style for the last element.
EDIT: I should just mention that this will not work in IE8 due to the use of :last-child. If you need IE6/7/8 compatibility, I would use something like JQuery instead of manually inserting HTML markup.
Is it possible that the browser you are using doesn't support content, counter-reset, :before, or counter-increment?
I'm pretty sure IE doesn't, and I'm not certain about others. If that is the case, you're just recieving the default numbered list: in short, the browser would ignore the newer CSS.
You can aplly a css class to reset that counter, like this example :
#alternate_navigation li.last:before
{
content: "";
counter-increment: none ;
}
Check my example :
http://www.aeon-dev.org/tests/before_pseudo_ie.html
Out of curiousity, in this case why are you using the counter-reset at all? Why not set
list-style: decimal;
and then for your html add a class to your last <li> tag like <li class="last">?
Then you can set
li.last { list-style: none; }

Resources