Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detect Browser lost focus in CSS

Tags:

html

css

I saw this functionality in a design a while back and thought "hay, that looks like a good idea". But looking further into it, I'm not sure it's entirely possible using 'just css'.

There was a navigation bar down the left hand side:

ul{
  background:red;
  display:inline-block;
  padding:20px;
  }
<ul>
  <li>link 1</li>
  <li>link 2</li>
  <li>link 3</li>
  <li>link 4</li>
</ul>

Is there a way to change this when the browser window looses focus?

I.e. when the user clicks off the browser, to make this nav's background color, for example, change?


The only possible (probably more inefficient way would be to do something like):

body:hover ul {
  background: red;
}
body ul {
  display: inline-block;
  padding: 20px;
  background: blue;
}
<ul>
  <li>link 1</li>
  <li>link 2</li>
  <li>link 3</li>
  <li>link 4</li>
</ul>
that i could think of.

But this obviously

  • (A) doesn't work well
  • (B) doesn't actually do this correctly.

It's more that I would like the browser to physically 'lose focus' before changing the css.

Would anyone have any ideas on how to achieve this?

like image 480
jbutler483 Avatar asked Jan 23 '15 09:01

jbutler483


2 Answers

Neither the current nor upcoming CSS standards define any selector or media query for when the user agent is not in the foreground.1

The Page Visibility API mentioned in the comments doesn't quite do what you're looking for, as that does not tell you whether the browser is in the foreground, only whether the page is visible. A browser window can be in the background but its current tab can still be visible if the window isn't minimized or isn't being completely obscured by another window (and you won't even get consistent results with the latter with the aforementioned API).

The best you can do is to listen for window focus and blur events using JavaScript:

window.addEventListener('focus', function() {
  document.body.classList.add('blur');
});

window.addEventListener('blur', function() {
  document.body.classList.remove('blur');
});
ul {
  display: inline-block;
  padding: 20px;
  background: red;
}
.blur ul {
  background: blue;
}
<ul>
  <li>link 1</li>
  <li>link 2</li>
  <li>link 3</li>
  <li>link 4</li>
</ul>

The caveat is that this will not work correctly if the page is in an iframe (such as in a Stack Snippet, as above), since the iframe's window object will lose focus when the iframe itself loses focus.

I am not aware of any methods to reliably detect when the browser window becomes active or inactive.


1Firefox uses a :-moz-window-inactive pseudo-class internally which works exactly as you would expect, but obviously this is a browser-specific feature and as such shouldn't be used in production code:

ul {
  display: inline-block;
  padding: 20px;
  background: red;
}
ul:-moz-window-inactive {
  background: blue;
}
<ul>
  <li>link 1</li>
  <li>link 2</li>
  <li>link 3</li>
  <li>link 4</li>
</ul>

WebKit has its own :window-inactive pseudo-class as well, which is actually what inspired the same feature in Firefox, except that WebKit does not prefix it for some strange reason, and it currently only applies to scrollbar pseudo-elements.

like image 74
BoltClock Avatar answered Oct 02 '22 12:10

BoltClock


You definitely cannot detect focus on window in css since css executed in scope of document. But you can detect it on, say body, using html5 tabindex attribute:

body:focus ul {
  background: red;
}
body ul {
  display: inline-block;
  padding: 20px;
  background: blue;
}
<body tabindex="0">
  <ul>
    <li>link 1</li>
    <li>link 2</li>
    <li>link 3</li>
    <li>link 4</li>
  </ul>
</body>
like image 23
Roman Bekkiev Avatar answered Oct 02 '22 12:10

Roman Bekkiev