Mr. Alien Mr. Alien - 6 months ago 27
jQuery Question

How to target alternate odd/even text lines

Say I've a

p
element or
div
element having a text say about 10-15 lines, now my client has a weird call on this, he needs odd/even lines having different text color. Say Line 1 - Black, so Line 2 should be Grey, Line 3 should be again black and so on...

So I decided using span's and changed the color but variable resolution is killing things here, Am aware of the
:first-line
selector (Which won't be useful in this case), also selectors like
:odd
&
:even
will be ruled out here as am not using tables, so is there any way I can achieve this using CSS or do I need to use jQuery?


TL; DR : I want to target odd/even lines in a paragraph or a div


I need a CSS solution, if not, jQuery and JavaScript are welcome

Answer

Demo 1

A rather ugly little solution, compounded by the fact that it's 3:30 AM. Still, it works on plain text blocks and allows each line to be individually styled.

Fiddle: http://jsfiddle.net/Fptq2/2/
Chrome 26, FF 20, Safari 5.1.7, IE 8/9/10 (7 could probably be made functional)

Essentially it:

  1. Splits the source into individual words once
  2. Wraps each word in a span (ugly but effective-any style can now be applied to the span)
  3. Uses a simple position calculation to determine if the element is lower than the previous
  4. Changes colors based on index change
  5. Performs #3-5 on resize (this should definitely be throttled!)
$(".stripe").each(function(){
  var obj = $(this);
  var html = obj.html().replace(/(\S+\s*)/g, "<span>$1</span>");
  obj.html(html);
});

function highlight(){
    var offset = 0;
    var colorIndex = 0;
    var colors = ["#eee","#000"];
    var spans = $(".stripe span");

    // note the direct DOM usage here (no jQuery) for performance
    for(var i = 0; i < spans.length; i++){
        var newOffset = spans[i].offsetTop;  

        if(newOffset !== offset){
            colorIndex = colorIndex === 0 ? 1 : 0;
            offset = newOffset;
       }

       spans[i].style.color = colors[colorIndex];
    }
}

highlight();
$(window).on("resize", highlight);

Demo 2

Fiddle: http://jsfiddle.net/Fptq2/4/

  • Uses a larger block of text
  • Shows effect applied to multiple elements
  • Caches the "all spans" selector
  • Adds resize throttling
(function () {
    $(".stripe").each(function () {
        var obj = $(this);
        var html = obj.html().replace(/(\S+\s*)/g, "<span>$1</span>");
        obj.html(html);
    });

    var offset = 0;
    var colorIndex = 0;
    var colors = ["#ccc", "#000"];
    var spans = $(".stripe span");

    function highlight() {
        for (var i = 0; i < spans.length; i++) {

            var newOffset = spans[i].offsetTop;
            if (newOffset !== offset) {
                colorIndex = colorIndex === 0 ? 1 : 0;
                offset = newOffset;
            }

            spans[i].style.color = colors[colorIndex];
        }
    }

    highlight(); // initial highlighting

    var timeout;
    function throttle(){
        window.clearTimeout(timeout);
        timeout = window.setTimeout(highlight, 100);
    }

    $(window).on("resize", throttle);
})();

Output

enter image description here