Take the 2-minute tour ×
Graphic Design Stack Exchange is a question and answer site for professional graphic designers and non-designers trying to do their own graphic design. It's 100% free, no registration required.

I have two blocks (div elements) with one black on the top background-color: black and one white on the bottom.

Is it possible to have a piece of text that straddles the two zones with inverted colors? (Example: the top part of the text "FOO" will be white on black and the bottom part black over a white region).

share|improve this question
1  
Hi Joe, welcome to GD SE, it's a good question, and user568458 has provided a solution that probably can't be improved upon. Could you mark an answer as accepted (click on tick beneath vote numbers) or comment on an answer to tell us about any problems your having with the current solutions? –  Dominic Oct 14 '13 at 14:34
add comment

3 Answers

up vote 8 down vote accepted

If you mean something like this:

enter image description here


Edit: here's a better way, which only requires one HTML element and so won't be weird when read by non-CSS-styling clients like search engines, screen readers, RSS, 'no style' apps etc (thanks to Dominic for suggesting trying :before and :after).

http://jsbin.com/UtUlIFO/2/edit

The important code (add colours to this):

HTML: <div class="someclass" data-text="Some text">Some text</div>

CSS:

.someclass {
  position: relative;
  display: inline-block;
}

.someclass:after {
  content: attr(data-text);
  display: block;
  position: absolute;
  top: 0px;
  height: 50%;
  overflow: hidden;
}

The HTML attribute can be anything - I used data-text because it's descriptive and avoids undesirable side effects (e.g. you could use title but it would create mouseovers in some browsers).

If you want display:block; on the main (.top) element, add something like width: 100%; to the inner (.bottom) element so it fills it.

If you're using jQuery, you can apply this style to any element really easily, avoiding having to manually type out the data-text duplicated bit:

$('.someElement').each(function(){
  $(this).addClass('someclass').attr('data-text',$(this).text());
});

Demo of that plus some other stuff like multiple lines, padding


Original suggestion:

http://jsbin.com/UtUlIFO/1/edit

Unfortunately it requires duplicating the text.

That said, because one element is inside the other and all the sizes are relative, if you're good with javascript/jQuery you could make something that clones an element inside itself and applies the appropriate styles. That could then run on anything and apply this style to it.

If you're very good with JS you could make this only apply if the media display mode is screen so that javascript-enabled search bots and people using screen readers only read the content once and aren't confused by reading everything twice... but now we're getting a bit technical :-).

Key code: (.bottom is inside .top like <div class="top">Hi<div class="bottom">Hi</div></div>)

.top {
  position: relative;
  display: inline-block;

  background: #000000;
  color: #ffffff;
}

.bottom {
  position: absolute;
  top: 0px;
  height: 50%;
  overflow: hidden;  

  background: #ffffff;
  color: #000000;    
}
share|improve this answer
2  
I'm trying to figure out if there's a way to do it by creating the duplicate text with a pseudo-element (:after or :before) any ideas? –  Dominic Oct 10 '13 at 17:37
2  
Interesting idea: you can do this (duplicating the content hard-coded into the CSS) or this (duplicating the content in a HTML attribute, then reading that) but apparently it's not possible to simply read the HTML content text using CSS. The HTML attribute way seems the best since it doesn't mess up machine-reading of the HTML. I've added some things like this above. –  user568458 Oct 11 '13 at 9:35
    
Very nice, displays fine on WebKit to, my method shifts a bit on mobiles. Would +5 if I could. Also, fallback for pre CSS3/non-supporting browsers should just be plain text, no dooping. In the words of Tony the tiger: Its grrrreat. :) –  Dominic Oct 11 '13 at 11:30
add comment

Surprisingly, it is possible, though I'd only advise it if you're website is all about the visual impact and the semantics of the code don't matter, additionally it probably won't be very consistent across older browsers.

The result is:

Inverted Text

This is not a pretty solution, and I'd bet it's not the only one out there, but it does what you want.

It requires that you have two instances of the text, and using absolute positioning and some simple maths, you can create this effect.

So if we have a container div, and within that two more divs, and within each of those an instance of the text, you can use the following HTML structure and CSS properties to achieve this:

<div class="container">
    <div class="black">
       <div class="text">Invert</div>
    </div>
    <div class="white">
       <div class="text">Invert</div>
    </div>
</div>

.container{position:relative; width:200px; height:100px; display:block; margin:0px; padding:0px; }

.black, .white{position:absolute; left:0px; background:#000; width:200px; height:50px; margin:0px; padding:0px; overflow:hidden; }

.black{top:0px; }

.white{bottom:0px; background:#fff; }

.text{position:absolute; color:#fff; font-size:70px; padding:0px; }

.black .text{bottom:-40px; }

.white .text{top:-40px; color:#000; }

Here is a JSFiddle of the result. :)

share|improve this answer
    
Oooh posted while I was finishing typing! Nice answer but I think there's a couple of ways it can be simplified to be more something that can be dropped in anywhere. I think there's no way to do it without duplicating text. –  user568458 Oct 10 '13 at 17:05
1  
Haha! I was rushing to get it in before somebody else :P! It's surprising how easy it was. That said, you're answer has waaay less code. I'd go with your one if it was me choosing. –  Dominic Oct 10 '13 at 17:10
add comment

There is also a CSS3 property, only supported by webkit, that inverts colors:

image {
 -webkit-filter: invert(100%);  
}

And there's an HTML5 Canvas Invert, here's an example and the full code. It iterates over all of the pixels in an image and inverts red, green, and blue by subtracting each component from the max color value, 255.

Both solutions would still require 2 images and CSS positioning for them. Since compatibility is not very good, I'd definitely go for one of the other answers :)

share|improve this answer
    
That's awesome, if only it was a standard property! –  Dominic Oct 11 '13 at 8:28
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.