{"id":236005,"date":"2016-01-11T08:10:53","date_gmt":"2016-01-11T15:10:53","guid":{"rendered":"http:\/\/css-tricks.com\/?p=236005"},"modified":"2017-04-10T18:33:41","modified_gmt":"2017-04-11T01:33:41","slug":"a-specificity-battle","status":"publish","type":"post","link":"https:\/\/css-tricks.com\/a-specificity-battle\/","title":{"rendered":"A Specificity Battle! (and other trickery)"},"content":{"rendered":"

The following is a guest adventure by Francisco Dias from HubSpot<\/a>. I saw Francisco and Cris Necochea give this as a quick, fun presentation at the Show & Tell<\/a> at CSS Dev Conf this year. He graciously agreed to prepare it for a blog post!<\/em><\/p>\n

<\/p>\n

19 ways to override a background color<\/h3>\n

Starting with pretty much the lowest specificity selector:<\/p>\n

div {\r\n  background: black;\r\n}<\/code><\/pre>\n

There are an awful lot of ways to one-up the existing specificity without repeating the same trick.<\/p>\n

Click through each step to see the spies force their color (black or white) on top of the previous color. When the specificity one-upping stops, there are still more tricks up their sleeve!<\/p>\n

(The Spy shape is created from a clip-path<\/code> on the div<\/code> in the demo to make it more fun and Spy-vs-Spy like. If the browser you’re currently in doesn’t support clip-path, you’ll just see white or black boxes.)<\/em><\/p>\n

See the Pen Spy Vs Spy<\/a> by Francisco Dias (@FranDias<\/a>) on CodePen<\/a>.<\/p>\n

What 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>\n

Step 2: Two Element Selectors<\/h3>\n

0, 0, 0, 2<\/p>\n

body div {\r\n  background: white;\r\n}<\/code><\/pre>\n

Step 3: Three Element Selectors<\/h3>\n

0, 0, 0, 3<\/p>\n

html body div {\r\n  background: black;\r\n}<\/code><\/pre>\n

Step 4: Class Selector<\/h3>\n

0, 0, 1, 0<\/p>\n

.spy {\r\n  background: white;\r\n}<\/code><\/pre>\n

Step 5: Class + Element Selector<\/h3>\n

0, 0, 1, 1<\/p>\n

div.spy {\r\n  background: black;\r\n}<\/code><\/pre>\n

Step 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>\n

Step 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>\n

Step 8: ID Selector<\/h3>\n

0, 1, 0, 0<\/p>\n

#spy {\r\n  background: white;\r\n}<\/code><\/pre>\n

Step 9: ID + Attribute Selector<\/h3>\n

0, 1, 1, 0<\/p>\n

#spy[class^=\"s\"] {\r\n  background: black;\r\n}<\/code><\/pre>\n

Step 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>\n

Step 11: Inline Style<\/h3>\n

1, 0, 0, 0<\/p>\n

<div class=\"spy\" id=\"spy\" style=\"background: black;\"><\/div><\/code><\/pre>\n

Step 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>\n

Step 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>\n

Step 14: box-shadow trickery<\/h3>\n

Some properties paint on top of others. box-shadow<\/code> paints on top of background.<\/p>\n

div {\r\n  box-shadow: inset 0 9001rem 0 white;\r\n}<\/code><\/pre>\n

Step 15: Invert Filter<\/h3>\n
div {\r\n  -webkit-filter: invert(1);\r\n          filter: invert(1);\r\n}<\/code><\/pre>\n

Step 16: Pseudo Element Overlay<\/h3>\n
div::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>\n

Step 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>\n

div:after {\r\n  background: white !important;\r\n}<\/code><\/pre>\n

Step 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>\n

Step 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
\n

A gif of the demo in large-screen-Chrome:<\/p>\n

<\/figure>\n","protected":false},"excerpt":{"rendered":"

The following is a guest adventure by Francisco Dias from HubSpot. I saw Francisco and Cris Necochea give this as a quick, fun presentation at the Show & Tell at CSS Dev Conf this year. He graciously agreed to prepare it for a blog post!<\/p>\n","protected":false},"author":248342,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_bbp_topic_count":0,"_bbp_reply_count":0,"_bbp_total_topic_count":0,"_bbp_total_reply_count":0,"_bbp_voice_count":0,"_bbp_anonymous_reply_count":0,"_bbp_topic_count_hidden":0,"_bbp_reply_count_hidden":0,"_bbp_forum_subforum_count":0,"sig_custom_text":"","sig_image_type":"featured-image","sig_custom_image":0,"sig_is_disabled":false,"inline_featured_image":false,"c2c_always_allow_admin_comments":false,"footnotes":"","jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":[]},"categories":[4],"tags":[],"jetpack_publicize_connections":[],"acf":[],"jetpack_featured_media_url":"","jetpack-related-posts":[{"id":364152,"url":"https:\/\/css-tricks.com\/manuel-matuzovics-css-specificity-demo\/","url_meta":{"origin":236005,"position":0},"title":"Manuel Matuzovic’s CSS Specificity Demo","date":"February 25, 2022","format":false,"excerpt":"If you're looking for a primer on CSS specificity, we've got that. And if you're trying to get ahead of the game, you should be aware of CSS Cascade Layers as well. One of the ways to help get a grasp of CSS specificity is thinking terms of \"what beats\u2026","rel":"","context":"In "Link"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2018\/12\/css-audit-specificity-graph.png?fit=1200%2C600&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":346355,"url":"https:\/\/css-tricks.com\/css-nesting-specificity-and-you\/","url_meta":{"origin":236005,"position":1},"title":"CSS Nesting, specificity, and you","date":"August 10, 2021","format":false,"excerpt":"Here\u2019s Kilian Valkhof on CSS nesting which isn't available in browsers yet, but will be soon. There are a few differences he notes between CSS nesting and nesting in Sass or Less though. Take, for example, the following code: div { background: #fff; & p { color: red; } border:\u2026","rel":"","context":"In "Link"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2021\/08\/css-nesting.jpg?fit=1200%2C600&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":264665,"url":"https:\/\/css-tricks.com\/latest-ways-deal-cascade-inheritance-specificity\/","url_meta":{"origin":236005,"position":2},"title":"The latest ways to deal with the cascade, inheritance and specificity","date":"January 10, 2018","format":false,"excerpt":"The cascade is such an intrinsic part of CSS that they put it right there in the name. If you\u2019ve ever needed to use !important to affect specificity in the cascade, you\u2019ll know that it can be a tricky thing to deal with. In the early days of CSS, it\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":372576,"url":"https:\/\/css-tricks.com\/using-css-cascade-layers-to-manage-custom-styles-in-a-tailwind-project\/","url_meta":{"origin":236005,"position":3},"title":"Using CSS Cascade Layers to Manage Custom Styles in a Tailwind Project","date":"August 24, 2022","format":false,"excerpt":"If a utility class only does one thing, chances are you don\u2019t want it to be overridden by any styles coming from elsewhere. One approach is to use !important to be 100% certain the style will be applied, regardless of specificity conflicts. The Tailwind config file has an !important option\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2022\/08\/tailwind-layers.png?fit=1200%2C600&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":375144,"url":"https:\/\/css-tricks.com\/taming-the-cascade-with-bem-and-modern-css-selectors\/","url_meta":{"origin":236005,"position":4},"title":"Taming the Cascade With BEM and Modern CSS Selectors","date":"November 21, 2022","format":false,"excerpt":"BEM. Like seemingly all techniques in the world of front-end development, writing CSS in a BEM format can be polarizing. But it is \u2013 at least in my Twitter bubble \u2013 one of the better-liked CSS methodologies. Personally, I think BEM is good, and I think you should use it.\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2022\/11\/is-where-funnels.jpg?fit=1200%2C600&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":336871,"url":"https:\/\/css-tricks.com\/where-has-a-cool-specificity-trick-too\/","url_meta":{"origin":236005,"position":5},"title":":where() has a cool specificity trick, too.","date":"March 29, 2021","format":false,"excerpt":"There is a lot of hype on the :is() pseudo-selector lately, probably because now that Safari 14 has it, it's supported across all the major browsers. You've got Miriam tweeting about it, Kevin Powell doing a video, \u0160ime getting it into the Web Platform News, and Robin mentioning it. Bramus\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2020\/06\/is-where-pseudo.jpg?fit=1200%2C600&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]}],"featured_media_src_url":null,"_links":{"self":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts\/236005"}],"collection":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/users\/248342"}],"replies":[{"embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/comments?post=236005"}],"version-history":[{"count":11,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts\/236005\/revisions"}],"predecessor-version":[{"id":236601,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts\/236005\/revisions\/236601"}],"wp:attachment":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/media?parent=236005"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/categories?post=236005"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/tags?post=236005"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}