1

I've seen lots of questions about setting the background color of selected text in Chrome and other browsers using the ::selection selector, but I haven't been able to find anything that discusses getting the color currently being used by the browser on the user's OS.

For a Chrome extension I've created a fake input element, and would like to style the "selected" text in that element with the same foreground and background colors as used in real input elements. So I'm wondering if there's an extension API in Chrome that lets JavaScript look up the colors currently being used by the browser for selected text. Given different combinations of platform, OS version and desktop theme, those colors may change from user to user, so simply hard-coding a couple of values isn't sufficient (though that's what I'm doing currently).

One approach might be to render an input with selected text into a canvas and sample the colors, though I haven't investigated whether taking what's essentially a screenshot is possible via an extension without user interaction (the desktopCapture API seems to show a dialog to the user). So I'm hoping there's an API for looking up the colors used by various UI elements. Simply getting access to the browser's default user agent style sheet would suffice.

jdunning
  • 1,356
  • 1
  • 14
  • 26
  • 1
    Why don't you use a real `` element? Do you want to match up the default UA styles, or also take the stylesheets on the current page into account? Did you know about `getComputedStyle(node, '::selection').getPropertyValue('background-color');` ? – Rob W Dec 13 '14 at 10:34
  • I can't use a real `` because putting the focus there will cause the page to hide the element the extension is modifying. I'm trying to hack around something I can't control directly. Matching the default UA styles would be enough, as I don't think the page changes the defaults. – jdunning Dec 14 '14 at 02:21
  • No, I didn't know about the pseudo element parameter. Running `getComputedStyle($("#search input")[0], "::selection")["background-color"]` in the console to get the search field on this page, it returns `"rgba(0, 0, 0, 0)"`, which is transparent. Getting the `color` attribute returns `rgb(136, 136, 136)`, which seems to be the unfocused and unselected color. I tried adding `:focus` to the pseudo element param, but that didn't change anything. – jdunning Dec 14 '14 at 02:23
  • Could you explain a bit more about the structure of the selection that you want to clone, the purpose of your extension, and how you insert the wrapper element in the document? A generic answer to your question would be long and imperfect, but if you have some additional constraints (such as "there is only one selected element"). – Rob W Dec 14 '14 at 09:50
  • And how would using a different element instead of the input solve the focus problem? If the original element is an `` field, and your new element is clicked, then the old element loses its focus, right? – Rob W Dec 14 '14 at 09:52
  • The structure of the selection doesn't matter. All I want to know is what colors Chrome is currently using to style selected text in an ``. On Windows, it's currently white text on #3297fd background, and on Mac it's black text on #accef7. But that can obviously change, e.g., the user has set the OS to use a high contrast theme. So is there a way for an extension to look up those color values at runtime? – jdunning Dec 15 '14 at 06:26
  • I had drafted an answer, but did not post it because it is not quite accurate for generic cases. That is why I want to know your use case for wanting to know this information (in particular why `` cannot used). You only talk about colors, but what about background images or fonts? That's why it is also relevant to know more about the selection's structure itself. – Rob W Dec 15 '14 at 08:50
  • There's no background image applied to selected text in an input on this particular page. The font is inherited from the CSS already on the page, and it could also be looked up via `getComputedStyle()`. The structure of the fake input is just a `` for the user-typed text inside a `
    ` representing the ``. A class is applied to the `` to flip the selection state on and off. I'd happily use a real ``, but I can't. Hence the fakery.
    – jdunning Dec 15 '14 at 23:56
  • Could you give a concrete example of what your extension does? I tried to pinpoint your problem by asking for clarifications, but somehow your answers don't help with narrowing down your original question to a situation with a practical solution. – Rob W Dec 16 '14 at 00:00
  • It's a company-internal extension and webpage, so I can't really get into specifics. But the specifics don't matter. It's a completely generic question: Can a Chrome extension (I'm pretty sure it's impossible with JS on a regular webpage) look up the fore- and background colors that the browser is using to render selected text? Just getting the colors the browser uses before they're modified by any on-page CSS would suffice (since this particular page doesn't modify the selection color). – jdunning Dec 16 '14 at 02:18
  • You could use [`chrome.tabs.captureVisibleTab`](https://developer.chrome.com/extensions/tabs#method-captureVisibleTab) to get the pixel data, paint it on a canvas and extract the colors. Make sure that the input element is large; use whitespace to find the background color, and a character that is known to have a high density to find the font color. This method will fall apart if the UA renders gradients though... Anyway, this is the best solution that you can get for a general question. – Rob W Dec 16 '14 at 11:42
  • Thanks for the pointer. `captureVisibleTab` isn't ideal, as it requires that the extension have full access to any page you view, which is overkill. But it sounds like it's the only option. Thanks for your help. – jdunning Dec 17 '14 at 01:13
  • @jdunning I recommend that you take the partial solution out of the question itself and post it as an answer. Keep to the Q&A format. – Xan Dec 18 '14 at 09:51
  • Ah, I didn't realize I could answer my own question. – jdunning Dec 18 '14 at 20:37

2 Answers2

1

Rob W points out that the chrome.tabs.captureVisibleTab call can capture the visible area of the current tab into a dataUrl, which could then be rendered into a canvas. By inserting an <input> element at a known location, putting some text into it, focusing the element, selecting the text and then doing the screen capture, you could scan the canvas for the element's pixels and pick out the selection's foreground and background colors. Bit kludgy, but it should work.

The drawback is that this feature requires the <all_urls> permission, even if your extension only needs to work on one domain. It would also mean that a focused input field would briefly flash when the extension loads, which could be distracting.

Community
  • 1
  • 1
jdunning
  • 1,356
  • 1
  • 14
  • 26
-2

You could use this:

function elemPropVal(elem, prop){
  var r = getComputedStyle(elem) || elem.currentStyle;
  return r[prop];
}
console.log(elemPropVal(document.getElementById('someId'), 'backgroundColor'));
StackSlave
  • 10,613
  • 2
  • 18
  • 35
  • That will return the background-color of the `` element itself, not the selected text inside of it. I tried `getComputedStyle(getSelection())` to get the styles on the selection itself, but that didn't work, unsurprisingly. – jdunning Dec 13 '14 at 02:03
  • `currentStyle` is IE-only and `getPropertyValue` takes CSS property names, not camelCased property names. Moreover, it doesn't tell the real painted color – Rob W Dec 13 '14 at 10:01
  • I think I see what you're looking for now, and this probably won't do the trick. I don't think you can get the highlighted (as in that bluish) color of the selected text. Use a graphics editor to find the color. It probably Universal – StackSlave Dec 15 '14 at 00:46