treehouse : what would you like to learn today?
Web Design Web Development iOS Development

Doing more with ::selection than changing the selection color. [question]

  • I know that you can style the "background" and "color" attributes of a selection with CSS, but I want to do something more. Is there a way to use an image as the selection background, perhaps using javascript?

    I'm trying to think of a way to create a 'highlight' effect similar to what is achieved in the iBooks app when text is highlighted.

    I think this could be a cool extra in any sites I design. Thanks all!
  • If I remember correctly, I've seen an example of this being used to 'reveal' an image that is only visible when text blocks are selected, but I can't seem to find it. If anyone knows of this, please post.
  • I made this one time:

    http://css-tricks.com/examples/SecretMessageGenerator/

    But no, I just tried using a real image with ::selection and it ignores it. http://jsbin.com/ejoye3/edit

    I'd love it if someone did some testing on ::selection trying all the different CSS properties and seeing which ones take and which ones don't (and also what the spec says). That'd be a fun CSS-Tricks guest post eh? =)
  • @chriscoyier - That definitely would be a fun guest post. If I come up with anything I'll let you know.

    I'm hell bent on making this work, so once I defeat my ignorance of javascript I'll update everyone. I have a solution in my head which should allow authors to style the highlight color via css - I just need to figure out how to implement this.

    BTW, its really odd nobody has done this yet. Google has given me nothing. :(
  • @chriscoyier - Your wish of testing on ::selection has been granted. I put together a little demo page explaining what the spec 'did' say (before ::selection was removed), and using short bits of text styled with different ::selection properties.

    http://meetaaronsilber.com/selectionpsuedo/index.html

    Most of these properties I'm not surprised to see ignored. The old spec indicated that it was possible that 'cursor' and 'outline' could be implemented, but I have yet to find a browser that does.

    I was glad to see that hex, rgba, and hsla values are used with the color and background-color properties. Other than those, nothing else really seems to work. In fact, some of the properties seem to disable the default ::selection all together.

    Aside from all this testing, I've started to get an idea of how a background-image could be applied using javascript;

    What I really need is to do is wrap text in a span with a class of 'hightlight' when it is selected by the user. This 'hightlight' class can be given a background-image (or an assortment of other properties).

    Apparently, using the Range object I can begin to capture what is being selected.

    http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Containment

    http://www.quirksmode.org/dom/range_intro.html

    So far I've figured out that I could do something like this;


    Kolich.Selector.mouseup = function(){

    var text = (document.all) ? document.selection.createRange().text : document.getSelection();
    var paragraph = $('p.pattern').html();

    $('p.pattern').html(paragraph.replace(text, '<span class="highlighted">' + text + '</span>'));
    }


    Problem is, that would only apply the highlighted class and markup on mouseup - not in real-time, only after the user selects. I guess I'd need to create some kind of loop that checks the selection begin and end positions frequently, and changes the markup accordingly.

    If I could get this to work, I could disable the default ::selection style on specified text and apply any styling I wanted to the 'highlight' span - including :before and :after. You could even create a transparent .png that works as a mask in the form of a highlighter stroke, while applying a background-color behind it. This way, you could use one image, but change the highlighter stroke color in CSS. =)

    In other words, this would be sweet, and definitely a 'trick.' I'm at the edges of my javascript knowledge, so if anyone is interested in helping that would be great!
  • lol, you're not a Minecraft fan are you?
  • On your demo/test page, you should include the ::-moz-selection {} too, so you can test Firefox.
  • Hey @chriscoyier - I've updated. There are a few things that moz does differently (although nothing amazing);

    1. It renders background colors differently. Webkit seems to fill in the entire area between lines of text, while moz lets them overlap (and darken with opacity), and space out if the line-height is large enough.

    2. Moz didn't render the :after and :before psuedo elements.

    3. You can't declare multiple ::selection psuedo classes like this;


    p::selection,
    p::-moz-selection { color: #ac8; }


    It just doesn't work - everything reverts back to the default.

    They need to be declared with their own declaration blocks. I guess they don't like to share;


    p::selection { color: #ac8; }
    p::-moz-selection { color: #ac8; }
  • Yep, that sucks but that's the case. If there is something in a selector that a rendering engine doesn't understand, the whole sector doesn't take effect. It's by design.

    Thanks for the work on this, I'm going to post about it hopefully this week.
  • I had figured it had something to do with that, but couldn't find any info. You're very welcome sir - and thanks for all your posts (and this community).

    If the trip makes it into my cost plan, I'll be listening to you at the Converge conference in June, a day before my birthday. Looks like quite a few of my heroes will be there.
  • Hey I've updated with text-shadow. It works in webkit. Glad I found something outside the spec.

    I realized that the HTML5 boilerplate resets background, color, and text-shadow - so that's what made me think of it. It references this tweet;

    http://twitter.com/#!/miketaylr/status/12228805301
  • anyway to take this a step further and keep highlights from "disappearing". I am working on an ipad app in html 5. its a text book and i would love to be able to add a highlight feature. This works great but each "chapter" is a new html page that when you go back "highlights" are removed.
  • I'm not sure jeffm2 - but I love the way iBooks has implemented the highlight feature. Too bad you can't just push your HTML5 book in that app. ;-)
  • yeah i would lose the nice layout that i am getting with html 5
  • I understand.. I have something at home (I'm at work) that I was messing around with so I'll send it your way this evening. Maybe you can have a go at it.
  • Right then, here is a jsfiddle - javascript courtesy of Mark S. Kolich. I haven't a reason to develop on this at the moment, so I'm afraid the project has been pushed back to the personal/curiosity list. lol. Anyways, if you're interested in having the highlight be similar to the organic highlight color in the iBooks app you can simply change that span.highlight background to an image. Looks very nice. Hope this helps.

    http://jsfiddle.net/meetaaronsilber/eU6WP/
  • Yup. Thanks. I had actually stumbled across this myself. Works pretty good on the ipad. I think the problem still remains, how to retain the highlights. I don't know enough about local storage or the like to make that work just yet.