1

I'm making my website and I ran into a problem.

I'm trying to invert colors in text selection. I tried this, but it doesn't work:

::selection {
    fiter: invert();
}

::selection {
  color: white;
  background-color: black;
}
.p1 {
    color: black;
    background-color: white;
}
.p2 {
    color: red;
    background-color: white;
}
.p3 {
    color: cyan;
    background-color: black;
}
<p class="p1">Paragraph 1</p>
<p class="p2">Paragraph 2</p>
<p class="p3">After select I want paragraph 2 to look like this:</p>

Can you help me please?

Jurakin
  • 832
  • 1
  • 5
  • 19

3 Answers3

2

I cannot see how to do this in a complex case, where the selection contains several HTML elements that might be setting color and background color individually (though of course some complex HTML/CSS parsing must be able to do that but I'm not capable).

However, we can fairly simply deal with the straightforward case where the color and background color are consistent across the parent div of the selection.

On a selection event this snippet reads the computed style of the parent element, calculates the inverse of the color and backgroundColor and sets CSS variables to these which are picked up and used in the selection pseudo element.

document.addEventListener('selectionchange', (e) => {
  function invert(color) {
    color = color.replace('rgb(', '');
    color = color.replace(')', '');
    color = color.replace('rgba(', '');
    let colors = color.split(',');
    let r = colors[0].replace(' ', '');
    let g = colors[1].replace(' ', '');
    let b = colors[2].replace(' ', '');
    let a = (colors.length > 3) ? colors[3].replace(' ', '') : 1;
    r = ~r & 255;
    g = ~g & 255;
    b = ~b & 255;
    return 'rgba(' + r + ', ' + g + ', ' + b + ', ' + a + ')';
  }
  selection = window.getSelection();
  if (selection.anchorNode) {
    const parent = selection.anchorNode.parentElement;
    const style = window.getComputedStyle(parent);
    parent.style.setProperty('--color', invert(style.color));
    parent.style.setProperty('--background-color', invert(style.backgroundColor));
  }
});
.invertSelectionColors::selection {
  color: var(--color);
  background-color: var(--background-color);
}
<div class="invertSelectionColors" style="background-color: cyan;color:#000000;">
  here is some text originally background color cyan and color #000000
</div>
<div class="invertSelectionColors" style="background-color: rgba(255, 0, 0, 0.5);color:#0000ffff;">
  here is some text originally background color rgba(255, 0, 0, 0.5) and color #0000ffff
</div>
A Haworth
  • 30,908
  • 4
  • 11
  • 14
1

For now you simply can't do it by pure styling. You would have to write javascript code for that.

Only certain CSS properties can be used with ::selection:

color

background-color

text-decoration and its associated properties

text-shadow

stroke-color, fill-color and stroke-width

From moz documentation, but I guess it applies to all browsers.

Flash Thunder
  • 11,672
  • 8
  • 47
  • 91
0

"Filters are commonly used to adjust the rendering of images, backgrounds, and borders." Filters are not used with ::selection.

You should use:

::selection {
  color: red;
  background: yellow;
}

::selection {
  color: red;
  background: yellow;
}
<p>Lorem ipsum</p>
Rifky Niyas
  • 1,737
  • 10
  • 25
Azu
  • 1,494
  • 2
  • 6
  • 11