Celebrating 20 years online :)
Web Dev + WordPress + Security

Case of the Invisible CSS ::selection

[ Scooby Doo Intro ] Recently I noticed a weird bug in my free WordPress security plugin, Banhammer. For some reason, I could not select any text on the page. Usually when you click and move the mouse cursor over some text, it becomes highlighted and displayed in some other color. But this wasn’t happening on the Banhammer settings screen. No matter which HTML/text I tried to select, it just wasn’t working. T’was a real mystery..

Update: The issue described in this post is resolved in newer versions of Chrome and Opera (tested in Opera 95.0 and Chrome 109.0). The issue is not yet resolved in Firefox (latest test with Firefox 110.0). Other browsers may vary.

Live Demo

Here is a simple Demo where text selection seems impossible, using Chrome, Firefox, Opera, and possibly other browsers.

Cracking the Case

After trying all the usual fixes, like clearing browser cache, different browsers, force reload, et al, I was coming up empty. So I donned my detective gear and began troubleshooting all related files. I figured the issue was somehow related to either CSS or JavaScript, so I applied the halving method to diagnose each of the CSS and JavaScript assets that were loaded on the page.

Luckily, the first file I checked was the plugin’s primary stylesheet. Turns out the issue was with empty ::selection declarations:

::-moz-selection {}
::selection {}

At the time, I added these rules as a placeholder for future styles. What I had failed to recognize was that, when the ::selection selectors are defined AND empty, the color property defaults to inherit in Chrome, Firefox, and Opera. So it’s the same as including this in your CSS:

::-moz-selection { 
	color: inherit; 
	background-color: transparent;
::selection { 
	color: inherit;
	background-color: transparent; 

The inherit value instructs browsers to inherit the property from the parent element. So what exactly is the parent of ::selection? Based on the exhibited behavior, the parent element must be undefined. Hence, no color is applied, and the text remains its current color.

What about background-color? By default, browsers apply a background color to selected text (usually a blue-ish color). But when it is not defined in the ::selection declaration, background-color falls back to its default value, transparent. Hence, no background-color is applied, and the text background remains its current color. Like an invisible selection.

Seeing is Believing

To see the issue for yourself, check out the Demo showing the strange invisible selection behavior. Try to select and copy any text on the page. It appears as if you aren’t selecting anything, but in fact you are.

The Solution

Once the mystery had been solved, resolving the issue was simple. Either:

  • Define some style(s) (like color or background-color) for ::selection
  • OR simply remove the empty ::selection declaration

Amazing how simple this turned out to be. Lesson learned: if it seems like you can’t select any text on the page, try copying and pasting anyway. It could be that the selection styles are hiding from you.

The Twist

Just like any good mystery story, this one has a twist: the “invisible selection” issue only happens when adding empty ::selection rules via external stylesheet. If the styles are added inline, like via <style> tags, text highlighting works fine.

Here is a Demo where empty ::selection rules are added via inline styles.

As you can see in Chrome, Firefox, and Opera, the inline-style demo works normally: when you highlight some text, the background-color changes to the default blue color as expected. To understand the difference, compare with the external stylesheet demo.

1 Weird Little Bug

I’m not sure if the “invisible selection” behavior is intentional or a weird little bug. Should empty selectors like ::selection have any effect on anything? Logically they should not have any effect, like if you add an empty class .whatever{}, absolutely nothing changes and no properties are presumed or affected. Why should ::selection behave any differently?

Also, why does the weird behavior happen only when adding styles via external stylesheet? Should the mode of CSS delivery have any effect on applied styles? Rhetorical question: it should not.

This is why I think this is a bug on the browser side of the equation. Specifically with Chrome, Firefox, and Opera. Safari does not exhibit any weird invisible selection behavior. Not sure about other browsers; fortunately I have a life ;)


So the empty-selection, invisible-highlighting behavior seems like a bug that’s specific to certain (major) browsers. I’m no CSS guru, but in my opinion it would be better for empty selectors to not have any effect on anything. If nothing else, I mean, if the browser vendors decide that this for whatever reason is not a bug, then at least the same behavior should apply regardless of whether the CSS is applied via external stylesheet or inline <style> tags.

About the Author
Jeff Starr = Web Developer. Book Author. Secretly Important.
Banhammer: Protect your WordPress site against threats.

4 responses to “Case of the Invisible CSS ::selection”

  1. Hi Jeff,
    How interesting!! It shows to go that you just never know!

    That being said, your inline and external demos act as you indicated… In Chrome.
    If I use your demos in my Firefox (69.0.3) BOTH of your examples have the invisible highlighting anomaly.

    Out of curiosity, are you using Windows or an Apple product? (I’m Windows) I’ve frequently run into CSS rendering differences between different operating systems. All iOS browsers are based on the WebKit engine even if they wear the Firefox or Chrome name.

    • Jeff Starr 2019/10/25 9:07 am

      Hi Ken, great to hear from you! Yeah I switched from Windows to Mac about nine years ago. I also have encountered differences in CSS rendering on Macs vs PC/Win, probably this obscure bug as well. It’s part of what makes front-end design so exciting: all the little nuances and quirks among the various browser incarnations.

  2. Jim S Smith 2019/10/27 11:38 am

    Most interesting.

    Reminds me of the old bug I kept having problems with some years ago in Mozilla’s browsers:

    That of being unable to “position” elements with the TOP and LEFT properties when a DOCTYPE was declared. – So glad when they finally fixed it!

    Sounds to me like this was an innocent oversight? Pretty interesting that you see the slight differences in performance across different browsers too. This is why a have problems when the developers want to rush their upgrades, as this is usually what leads to “regression bugs” and “new bugs” in what was a clean product beforehand.

    Also saw a few problems like this creep into the JavaScript side. Nothing more unnerving when you HAD a working JavaScript in one browser version, only to have a “bug” in the newer browser ruin it.

    Oh well!

    Life goes on.

    – Jim S.

  3. kristina ponting 2019/11/14 12:47 am

    HI:) Bought BBQ Pro and blackhole pro = amazing and love them, they works well! But: Now the tries to get my blog by changing admin adress!!!

    and thats opion is impossible, you need an extra log in for getting in mysql. I wonder if there is some more out there? With the same problem.

    I recomend plugins above to all:) who is serios bloggers:) LOVE YA:) //KP

Comments are closed for this post. Something to add? Let me know.
Perishable Press is operated by Jeff Starr, a professional web developer and book author with two decades of experience. Here you will find posts about web development, WordPress, security, and more »
SAC Pro: Unlimited chats.
Crazy that we’re almost halfway thru 2024.
I live right next door to the absolute loudest car in town. And the owner loves to drive it.
8G Firewall now out of beta testing, ready for use on production sites.
It's all about that ad revenue baby.
Note to self: encrypting 500 GB of data on my iMac takes around 8 hours.
Getting back into things after a bit of a break. Currently 7° F outside. Chillz.
Get news, updates, deals & tips via email.
Email kept private. Easy unsubscribe anytime.