Search code examples
htmlcsspre

Hover over a pre - how to highlight a single line with plain CSS?


I have some <pre> blocks.

Would it be possible, using just CSS, to highlight single lines when hovering over them?

== Update ==

Here is some sample code:

<pre>
#include <stdio.h>

int main()
    {
       printf("Hello World");
       return 0;
    }
</pre>

When lines become longer it would be useful to have them highlighted when hovering.

The source file can't be read via PHP, or I'd split it into separate <pre> lines, with a trivial pre:hover CSS.

pre:nth-child is not a solution, because code lines are not "children" in the CSS sense.

pre:first-line works, but of course just for the first line.

== Update 2 ==

Since CSS seems to be limited to first-line, and thanks to Zeke suggestion, I found an almost simple way to have what I want.

HTML:

<pre id="raw">
#include <stdio.h>

int main()
    {
       printf("Hello World");
       return 0;
    }
</pre>
<!-- 1×1 transparent PNG for the onload -->
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP4/x8AAwAB/2+Bq7YAAAAASUVORK5CYII=" onload="PreHover()" />

CSS:

#pre div:hover {
    background: #ff0;
}

Vanilla Javascript:

function PreHover() {
    var output = '';
    var preBox = document.getElementById('raw');
    var txt = preBox.innerHTML.split('\n');
    for(var x=0;x<txt.length-1;x++) {
        output = output + '<div>'+txt[x]+'</div>';
    }
    preBox.innerHTML = output;
}

JSFiddle here


Solution

  • This will help you wrap div for each line

    var txt = $('pre').html().split("\n");
    var output = "";
    for(var x=0;x<txt.length-1;x++)
        output = output + "<div>"+txt[x]+"</div>";
    }
    $('pre').html(output);
    

    You can write one line css then for highlighting:

    pre div:hover { background-color: rgba(0,0,0,0.2); }
    

    Demo here

    Note: This requires jQuery

    Optional: Add white-space:nowrap to prevent wrapping each line

    Why do this?

    Because if just have <pre>, it will be a DOM element containing just text inside it, on which you can make changes as a whole, and not line by line.

    To have much better control over every line, build a new DOM element by manipulating the text contained in <pre> with pre containing many div each of which contains one line of text. And now you can master each and every div