Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Line Numbers every nth Line with CSS Counters?

Tags:

css

I had to cut out certain referring links (italicized) as I don't have enough reputation yet, but can perhaps replace them later.

I've created a jQuery plug-in that displays incremented line numbers for poetry and drama; The lines of a poem are represented as the children of an ordered list (ol.verse). When javascript is enabled, the plug-in generates line numbers every nth interval based on a minimum of inline list values. These numbers can then be manipulated through the DOM. When JS is disabled, numeric list markers every fifth line kick in as fallback line numbers.

I wonder now whether it is possible to get the plugged poem to degrade as a list powered by CSS Counters. IE 6-7 get served plain ordered lists with the trailing periods of the numerals, but superior browsers should get counters or the numbers generated by the plugin. Here's the catch. The CSS counter rules should be able to accommodate situations where the line numbering and the child-indexing of the poem list do not sync. I've seen a number of posts on formatting counters and skipping children, as well as the right and wrong ways of formatting poems semantically and typographically (the W3C proposals recommending paragraph and pre tags are questionable at best); I have come up empty, however, on the problem of using counters to do incremented line numbers, so I am sharing my own efforts towards a solution and hope you guys can help me towards a better one.

The base rules I've been experimenting with limited success:

ol.verse { counter-reset: line 0;
ol.verse li {
   display: block;       
}

ol.verse li:before {
   counter-increment: line;
   content: counter(line) " ";
}

/* hide lines, or more precisely, children, that are not a multiple of 5 */

ol.verse li:not(:nth-child(5n)):before {
   visibility: hidden;
}

As you can see from this fiddle, these rules display numbers every 5th line SO LONG AS every list child is to be counted as a line of the poem and SO LONG AS the passage begins from line 1, 6, 11, 16, etc. (i.e. the counter-reset is 0 or a multiple of 5). That last rule may be of interest to those wanting to do incremented line numbers for some simpler task (a simple poem for a blog entry, e.g.), but these conditions are too restrictive for our needs (a TEI-structured repository of critical editions of poetry/drama online).

Problem 1: When I have several excerpts or divisions of one or more works whose counter-resets are non-multiples of the default increment, I have to reference the excerpts by id and offset the hiding rule for each id'd ol.verse by the remainder. For example, an excerpt beginning from line 43 requires adjusting the counter-reset to 42, and adjusting the nth-child parameter of the hiding rule to 5n+3 (since 42 % 5 = 3). Suddenly, counters become less appealing than numbering list values by hand. This at least is better than....

Problem 2: Getting the browser to uncount certain lines such as subheadings or stage directions that may be embedded within the poem. To these lines, I've tried attaching a nocount class and turning off the display property or the visibility property, e.g.

ol.verse li.nocount:before {
   display: none;     
}  

OR

ol.verse li.nocount:before {
   visibility: hidden;
}

In combination with the rule hiding lines that are non-multiples of the increment, neither gives the desired results. See this fiddle. The first triggers incorrect line numbering on the right numbers; the latter, correct numbering on the wrong ones. Is there any way to write CSS counter rules that would work whether or not the automated line numbers correspond with the correct child indexes? Perhaps there's some other combination of CSS selectors that will do the job?

like image 697
jeffclef Avatar asked Jun 01 '12 19:06

jeffclef


1 Answers

Fixing the counting is not a problem as you can use counter-increment: line 0; for rules you want to be excluded (if they apply on the same element as the +1 increment) with a higher specificity or !important.

(if like in your case where you apply the rule to the :before pseudo-element, but want to exclude based on the li you can apply a counter-increment:line -1;

Demo at http://jsfiddle.net/gaby/qpsGv/3/


To display it on the right line though that is another issue as that has to do with the nth-child selector which does not allow for modifications... (if it finds a child it gets counted for its purposes..)


Update

I do not know what flexibility you have which changing the actual html, but the only solution i can see is to wrap the elements you want to not be counted in another element.

That way you can use the nth-of-type instead of the nth-child, so that you can indeed show only on multiples of 5.

In order to keep the html valid, you would need to use the menu element as that is the only one that allows both li and ol as children.. (you could ofcourse use entirely different elements .. just make sure that the counting elements are different that the non-counting ones)

So just counting on

menu.verse > li { counter-increment: line 1;}

and displaying on

menu.verse > li:nth-of-type(5n):before {
    content: counter(line);
    width: 2em;
    display: block;
    float: left;
    margin-left: -2em;  
}

when the html is

<menu class="verse">
 <li>countable</li>
 <ol><li>non countable</li></ol>
 <li> countable</li>
</menu>

should work.. (the <ol><li> could just become a div with appropriate styling..)

Demo at http://jsfiddle.net/gaby/qpsGv/7/

like image 167
Gabriele Petrioli Avatar answered Nov 05 '22 10:11

Gabriele Petrioli