views:

338

answers:

3

How to select and apply style on a specific line of text? Like the CSS pseudo-element :first-line, but I want to select any line, not limited to the first.

It seems that it can't be done by using only CSS... Anyway I don't mind a JS solution.


Update:

Well, actually it's only for interest. I'm trying to achieve something like highlighting every even row of a paragraph (for readability, like what everyone does for table rows)...

Pre-formating the text like:

<p>
<span class='line1'>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do </span>
<span class='line2'>eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad </span>
<span class='line3'>minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip </span>
<span class='line4'>ex ea commodo consequat. Duis aute irure dolor in reprehenderit in </span>
<span class='line5'>voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur </span>
<span class='line6'>sint occaecat cupidatat non proident, sunt in culpa qui officia </span>
<span class='line7'>deserunt mollit anim id est laborum.</span>
</p>

...it is ok for me, but how to know where to split? Even if the width of paragraph is given, it is still hard to determine...

A: 

If I understand you correctly you want to be able to apply a style to a specific line in the document, via CSS. For instance: to make the 5th line bold.

This is not possible - CSS is not line oriented but rather DOM-element oriented. So to achieve your goal you will have to wrap your line inside a <span> (or a <div>) element and then apply the style to that element.

CSS is not line oriented because line numbers are illusive: line numbers will change depending on screen resolution, the width of the browser window, the default fonts defined at the browser etc. Thus, styling that is based on line numbers will give you questionable results.

Itay
How about using JS?
Andy Li
A: 

If each line is a separate <li> or <p> you can select that, using CSS.

:nth-child(N)

Taken from sitepoint.com, works in in Opera 9.5+, Safari 4+, FF3.5+

Description

This pseudo-class matches elements on the basis of their positions within a parent element’s list of child elements. The pseudo-class accepts an argument, N, which can be a keyword, a number, or a number expression of the form an+b. For more information, see Understanding :nth-child Pseudo-class Expressions.

If N is a number or a number expression, :nth-child(N) matches elements that are preceded by N-1 siblings in the document tree.

The following example selectors are equivalent, and will match odd-numbered table rows:

tr:nth-child(2n+1) {
  ⋮ declarations
}
tr:nth-child(odd) {
  ⋮ declarations
}

This example selector will match the first three rows of any table:

tr:nth-child(-n+3) {
  ⋮ declarations
}

This example selector will match any paragraph that’s the first child element of its parent element:

p:nth-child(1) {
  ⋮ declarations
}

This is, of course, equivalent to the selector p:first-child.

Example

This example selector will match odd-numbered table rows:

tr:nth-child(odd) {
  ⋮ declarations
}

You can also use jQuery.

Jonny Haynes
+3  A: 

Interesting. You can do something like that with JavaScript, of course:

$(function(){ 
  var p = $('p'); 
  var words = p.text().split(' '); 
  var text = ''; 
  $.each(words, function(i, w){
                   if($.trim(w)) text = text + '<span>' + w + '</span> ' }
        ); //each word 
  p.html(text); 
  $(window).resize(function(){ 

    var line = 0; 
    var prevTop = -15; 
    $('span', p).each(function(){ 
      var word = $(this); 
      var top = word.offset().top; 
      if(top!=prevTop){ 
        prevTop=top; 
        line++; 
      } 
      word.attr('class', 'line' + line); 
    });//each 

  });//resize 

  $(window).resize(); //first one
});

Basically, we wrap each word with a span, and add a class based on the position of the span, whenever the window resizes. I'm sure it can be done more efficiently, but it works as a proof of concept. Of course, for even/odd lines, you can simplify the code.

Edge cases: I didn't test it where the class changes the size or width of the words. It may end up very wrong.

Here it is in action: http://jsbin.com/udehu3

Kobi
Wow. Respect. +1
Pekka
Great solution :) But what if we want to retain additional markups inside the paragraph? I mean in line 3 of your code, `text()` will remove html tags like `<span>` or `<strong>` inside the paragraph.
Andy Li
Thanks Andy! This is far from production code, as I've said. Using this approach, you'll have to separate the words from each child tag (or ignore it), and then take the free-text nodes (text with no parent tag - as in http://stackoverflow.com/questions/992472#992568 ). We can use `text` on each of them individually, and keep the markup. It will take thought, as I'm sure there are many more edge cases (In fact, most cases don't work here, so my code is for an edge case!).
Kobi