1

I have a site with a changing background image, on hover of certain elements. The image is usually dark, but sometimes light. The light images have the class .whiteImg applied to them.

I have gotten this to work with just CSS, by having the 'background' images set as the sibling of the element that is hovered. For example:

HTML:

<ul>
  <li>
    <a>link 1</a>
    <img src="http://foo.com/" />
  </li>
  <li>
    <a>link 2</a>
    <img src="http://foo.com/" />
  </li>
  <li>
    <a>link 3</a>
    <img src="http://foo.com/" class="whiteImg" />
  </li>
</ul>

CSS:

img{
  position: absolute;
  top: 0; left: 0; bottom: 0; right: 0;
  opacity: 0;
  transition: opacity 1s;
}
li a:hover + img{
opacity: 1;
}

Now that all works fine. But I have body{color: #fff;} by default but that needs to change to #000 when .whiteImg is visible. I've tried solving this with jQuery (and it's color plugin) but the animation happens after the CSS animation. So I'm looking for a pure CSS solution to *make the body color change to black at the same time as .whiteImg is shown.

Is there anyway to do this? I'm looking for something similar to

 li a:hover + img.whiteImg < body {
    color: #000;
 }

which is inspired by the end of this post but obviously doesn't actually work.

Thanks.

sanjaypoyzer
  • 3,182
  • 10
  • 32
  • 46
  • Do you really want to change the whole page's color? Or just the hovered link? If the latter then simply `li a:hover {color: #000}` is enough. Edit: also, why not use normal background-images instead of absolutely positioned `img` elements? Also 2, why not put the images inside the links? – powerbuoy Sep 16 '13 at 12:27
  • 2
    There's not yet a parent selector in CSS3. You have to use Javascript for this. http://stackoverflow.com/questions/1014861/is-there-a-css-parent-selector – Fez Vrasta Sep 16 '13 at 12:30
  • @Mr. Alien: It's not. It's just a hypothetical selector dreamed up by the author of that article (i.e. "wouldn't it be nice if we had a parent selector like this?"). Fortunately OP knows it's hypothetical and knows it's invalid, but it's very commonly mistaken to be a real selector. – BoltClock Sep 16 '13 at 12:33
  • @BoltClock Yes I know that, we also had a question few weeks back which said why don't we use ` – Mr. Alien Sep 16 '13 at 12:35
  • In my opinion the best parent selector would be `body:target .children { }` where the element with `:target` pseudo-class would be the target of the CSS rules applied. – Fez Vrasta Sep 16 '13 at 12:35
  • @Fez Vrasta: `:target` is already used to mean something else: http://www.w3.org/TR/css3-selectors/#target-pseudo The proper term for what you're suggesting is "subject", and a subject selector has already been proposed, albeit in the form of a symbol and not a pseudo-class. See Selectors 4: http://www.w3.org/TR/selectors4/#subject – BoltClock Sep 16 '13 at 12:36
  • `:target` was just an example :) – Fez Vrasta Sep 16 '13 at 12:37
  • Your images are formatted so that they span the whole viewport already – so wrap them in a span, make that span as big as the viewport as well, and give that span the background color – since those spans come after your links, you _can_ select them when the links are hovered. – CBroe Sep 16 '13 at 12:39
  • But it's the text on the rest of the page that I'm trying to affect. – sanjaypoyzer Sep 16 '13 at 13:05
  • @sanjaypoyzer add jsfiddle – sun Sep 16 '13 at 13:21

2 Answers2

2

This is the only pure CSS solution I can think:

http://jsfiddle.net/7K83g/3/

li, li * {
    position: relative;
    z-index: 2;
}
.whiteImg ~ .fakebg {
    display: block;
    position: absolute;
    z-index: 1;
    top: 0; left: 0;
    width: 100%;
    height: 100%;
    background: black;
}

This is a 100% solution, uses direction: rtl to apply the right position to the links.

With jQuery instead:

 $(document.body).toggleClass("dark");

CSS:

 .dark { background: black; color: white; }

Will do the trick.
Example: http://jsfiddle.net/QKAh6/

Fez Vrasta
  • 11,462
  • 19
  • 73
  • 135
  • I'm not trying to affect the background on hover, that's already done. I'm trying to affect the color of the text. – sanjaypoyzer Sep 16 '13 at 12:57
  • watch the edit. And by the way I've said it was just a concept, the trick works, you have to use it in the right way, but the trick itself works. – Fez Vrasta Sep 16 '13 at 12:58
  • I know but I'm trying to affect the color of all of the text on the body, because the fake background of the entire page is changing – sanjaypoyzer Sep 16 '13 at 13:04
  • just make two classes "light" and "dark" to apply to the body element and switch them with jQuery, watch this site, has the exact effect you are trying to archieve: http://subtlepatterns.com/ – Fez Vrasta Sep 16 '13 at 13:06
  • As said, I've tried using jquery already but it clashes with the css transition for timing. – sanjaypoyzer Sep 16 '13 at 13:24
  • As said, subtlepatterns does it, so it's possible, and if you don't give us your complete CSS we can't understand where is the problem with **your code**. – Fez Vrasta Sep 16 '13 at 13:34
  • That does look really nice, however it just misses out the CSS in my question which sets the images as a kind of fake background (with opacity transition). I've forked your fiddle [here](http://jsfiddle.net/8mwD3/) but those transitions/hover effects don't work. Is there a reason for this? – sanjaypoyzer Sep 16 '13 at 13:52
  • CSS transitions can't be used to fade a background-image, but with a `` tag as you did should work, just check the code and fix the errors. – Fez Vrasta Sep 16 '13 at 14:02
  • I'm confused... What is the error? Something to do with the `a:hover` not working on an `li`? – sanjaypoyzer Sep 16 '13 at 14:07
  • Ah, ok. Thanks. I didn't notice you'd put the imgs into the li, makes sense. – sanjaypoyzer Sep 16 '13 at 14:12
0

As the post your refer to suggests, the > selector is a wish, not an actual implementation. Reality is you can't select a parent in CSS.

It also states an alternative jQuery method:

$('p:has(img)');

In your case, this would be:

$('body:has(img.whiteImg)').css('color', '#fff');

Just run this when you are triggering the image change.


Alternatively, to make it easier, you can just add or remove a class to the body when you are starting to fade in the new image.

body {
    color: #000;
    transition: color 0.4s;
}

body.negative { color: #fff; }
Tim S.
  • 12,449
  • 7
  • 41
  • 68