CodePen<\/a>.<\/p>\nWhat the heck is going on here? The text inside the demo Pen above has a bit more information on each step, but just as a quick overview, here are the stages:<\/p>\n
Step 1: Element Selector<\/h3>\n
0, 0, 0, 1<\/p>\n
div {\r\n background: black;\r\n}<\/code><\/pre>\nStep 2: Two Element Selectors<\/h3>\n
0, 0, 0, 2<\/p>\n
body div {\r\n background: white;\r\n}<\/code><\/pre>\nStep 3: Three Element Selectors<\/h3>\n
0, 0, 0, 3<\/p>\n
html body div {\r\n background: black;\r\n}<\/code><\/pre>\nStep 4: Class Selector<\/h3>\n
0, 0, 1, 0<\/p>\n
.spy {\r\n background: white;\r\n}<\/code><\/pre>\nStep 5: Class + Element Selector<\/h3>\n
0, 0, 1, 1<\/p>\n
div.spy {\r\n background: black;\r\n}<\/code><\/pre>\nStep 6: Element + Class + Pseudo-Class Selector<\/h3>\n
0, 0, 2, 1<\/p>\n
div.spy:only-of-type {\r\n background: white;\r\n}<\/code><\/pre>\nStep 7: Stacked Classes<\/h3>\n
0, 0, \u221e, 0<\/p>\n
.spy.spy.spy.spy.spy.spy.spy.spy.spy {\r\n background: black;\r\n}<\/code><\/pre>\nStep 8: ID Selector<\/h3>\n
0, 1, 0, 0<\/p>\n
#spy {\r\n background: white;\r\n}<\/code><\/pre>\nStep 9: ID + Attribute Selector<\/h3>\n
0, 1, 1, 0<\/p>\n
#spy[class^=\"s\"] {\r\n background: black;\r\n}<\/code><\/pre>\nStep 10: Combining Many Above…<\/h3>\n
0, 1, 3, 3<\/p>\n
html body div#spy[class=\"spy\"]:first-of-type.spy {\r\n background: white;\r\n}<\/code><\/pre>\nStep 11: Inline Style<\/h3>\n
1, 0, 0, 0<\/p>\n
<div class=\"spy\" id=\"spy\" style=\"background: black;\"><\/div><\/code><\/pre>\nStep 12: !important<\/h3>\n
Kind of like [1, 0, 0, 0] on a per-property basis (can override an inline style).<\/p>\n
div {\r\n background: white !important;\r\n}<\/code><\/pre>\nStep 13: !important on inline style<\/h3>\n
Kind of like [\u221e, 0, 0, 0] on a per property basis, which no CSS can override.<\/p>\n
<div class=\"spy\" id=\"spy\" style=\"background: black !important;\"><\/div><\/code><\/pre>\nStep 14: box-shadow trickery<\/h3>\n
Some properties paint on top of others. box-shadow<\/code> paints on top of background.<\/p>\ndiv {\r\n box-shadow: inset 0 9001rem 0 white;\r\n}<\/code><\/pre>\nStep 15: Invert Filter<\/h3>\ndiv {\r\n -webkit-filter: invert(1);\r\n filter: invert(1);\r\n}<\/code><\/pre>\nStep 16: Pseudo Element Overlay<\/h3>\ndiv::after {\r\n content: \"\";\r\n height: 9001px;\r\n width: 9001px;\r\n background: black;\r\n top: 0;\r\n left: 0;\r\n position: absolute;\r\n}<\/code><\/pre>\nStep 17: !important again<\/h3>\n
All the specificity battles could be fought again, including the per-property battle using !important;<\/code>, so let’s end that here.<\/p>\ndiv:after {\r\n background: white !important;\r\n}<\/code><\/pre>\nStep 18: @keyframes trickery<\/h3>\n
!important<\/code> isn’t animateable, so the animation can override it.<\/p>\n@keyframes white {\r\n to {\r\n background: black;\r\n }\r\n}\r\n\r\ndiv:after {\r\n animation: white 1s linear;\r\n animation-play-state: paused;\r\n animation-delay: -1s;\r\n animation-fill-mode: forwards;\r\n}<\/code><\/pre>\nStep 19: Coloring the Content<\/h3>\n
Putting a huge block character over everything flips the color again!<\/p>\n
div:after {\r\n content: \"\u2588\";\r\n line-height: 0;\r\n color: white;\r\n font-size: 9001px;\r\n}<\/code><\/pre>\n
\nA gif of the demo in large-screen-Chrome:<\/p>\n