{"id":5194,"date":"2025-02-14T11:44:54","date_gmt":"2025-02-14T16:44:54","guid":{"rendered":"https:\/\/frontendmasters.com\/blog\/?p=5194"},"modified":"2025-02-14T11:44:56","modified_gmt":"2025-02-14T16:44:56","slug":"rainbow-selection-in-css","status":"publish","type":"post","link":"https:\/\/frontendmasters.com\/blog\/rainbow-selection-in-css\/","title":{"rendered":"Rainbow Selection in CSS"},"content":{"rendered":"\n<p>There is a <code>::selection<\/code> pseudo class selector in CSS that allows you to style what content (mostly: text) looks like when it&#8217;s selected. <\/p>\n\n\n\n<p>Say your website has pretty strong orange-colored branding, you could use this to extend the feel of that branding. <\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"387\" src=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/02\/Screenshot-2025-02-14-at-7.30.26%E2%80%AFAM.png?resize=1024%2C387&#038;ssl=1\" alt=\"Geoff Grahams website with the first few words of a paragraph selected. The selected text has an orange background color, just like the border of the whole site.\" class=\"wp-image-5195\" style=\"width:631px;height:auto\" srcset=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/02\/Screenshot-2025-02-14-at-7.30.26%E2%80%AFAM.png?resize=1024%2C387&amp;ssl=1 1024w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/02\/Screenshot-2025-02-14-at-7.30.26%E2%80%AFAM.png?resize=300%2C113&amp;ssl=1 300w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/02\/Screenshot-2025-02-14-at-7.30.26%E2%80%AFAM.png?resize=768%2C290&amp;ssl=1 768w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/02\/Screenshot-2025-02-14-at-7.30.26%E2%80%AFAM.png?resize=1536%2C581&amp;ssl=1 1536w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/02\/Screenshot-2025-02-14-at-7.30.26%E2%80%AFAM.png?w=1888&amp;ssl=1 1888w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><\/figure>\n\n\n\n<p>Like:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">html<\/span> {\n  <span class=\"hljs-attribute\">--brandColor<\/span>: orange;\n}\n<span class=\"hljs-selector-pseudo\">::selection<\/span> {\n  <span class=\"hljs-attribute\">background-color<\/span>: <span class=\"hljs-built_in\">var<\/span>(--brandColor);\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>There is really only a couple of things you can set on <code>::selection<\/code> (see the <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/CSS\/::selection#allowable_properties\">allowable properties<\/a> bit on MDN), which makes sense. You wouldn&#8217;t want to be changing <code>font-size<\/code> on selection or anything like that as it would get messy quickly.<\/p>\n\n\n\n<p>I was on the <a href=\"https:\/\/lit.dev\/docs\/\">Lit documentation<\/a> site the other day and highlighted some text and saw this:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"895\" src=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/02\/lit.png?resize=1024%2C895&#038;ssl=1\" alt=\"Lit documentation site with 5 paragraphs of text selected, each with slightly different hues of greens and blues as backgrounds.\" class=\"wp-image-5197\" srcset=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/02\/lit.png?resize=1024%2C895&amp;ssl=1 1024w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/02\/lit.png?resize=300%2C262&amp;ssl=1 300w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/02\/lit.png?resize=768%2C671&amp;ssl=1 768w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/02\/lit.png?resize=1536%2C1342&amp;ssl=1 1536w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/02\/lit.png?resize=2048%2C1790&amp;ssl=1 2048w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><\/figure>\n\n\n\n<p>At first I wasn&#8217;t even sure if it was intentional, but I sure thought it was neat! I figured it was just <code>:nth-child()<\/code> trickery where you hang <code>::selection<\/code> off the end of it. Like:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-pseudo\">:nth-child(5n)<\/span><span class=\"hljs-selector-pseudo\">::selection<\/span> {\n  <span class=\"hljs-attribute\">background<\/span>: <span class=\"hljs-built_in\">oklch<\/span>(<span class=\"hljs-number\">70%<\/span> <span class=\"hljs-number\">0.111<\/span> <span class=\"hljs-number\">0<\/span> \/ <span class=\"hljs-number\">72.27%<\/span>)\n}\n<span class=\"hljs-selector-pseudo\">:nth-child(5n+1)<\/span><span class=\"hljs-selector-pseudo\">::selection<\/span> {\n  <span class=\"hljs-attribute\">background<\/span>: <span class=\"hljs-built_in\">oklch<\/span>(<span class=\"hljs-number\">70%<\/span> <span class=\"hljs-number\">0.111<\/span> <span class=\"hljs-number\">40<\/span> \/ <span class=\"hljs-number\">72.27%<\/span>)\n}\n<span class=\"hljs-selector-pseudo\">:nth-child(5n+2)<\/span><span class=\"hljs-selector-pseudo\">::selection<\/span> {\n  <span class=\"hljs-attribute\">background<\/span>: <span class=\"hljs-built_in\">oklch<\/span>(<span class=\"hljs-number\">70%<\/span> <span class=\"hljs-number\">0.111<\/span> <span class=\"hljs-number\">80<\/span> \/ <span class=\"hljs-number\">72.27%<\/span>)\n}\n<span class=\"hljs-selector-pseudo\">:nth-child(5n+3)<\/span><span class=\"hljs-selector-pseudo\">::selection<\/span> {\n  <span class=\"hljs-attribute\">background<\/span>: <span class=\"hljs-built_in\">oklch<\/span>(<span class=\"hljs-number\">70%<\/span> <span class=\"hljs-number\">0.111<\/span> <span class=\"hljs-number\">120<\/span> \/ <span class=\"hljs-number\">72.27%<\/span>)\n}\n<span class=\"hljs-selector-pseudo\">:nth-child(5n+4)<\/span><span class=\"hljs-selector-pseudo\">::selection<\/span> {\n  <span class=\"hljs-attribute\">background<\/span>: <span class=\"hljs-built_in\">oklch<\/span>(<span class=\"hljs-number\">70%<\/span> <span class=\"hljs-number\">0.111<\/span> <span class=\"hljs-number\">160<\/span> \/ <span class=\"hljs-number\">72.27%<\/span>)\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>So I made a demo of that and it works great:<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_qEWeWLP\" src=\"\/\/codepen.io\/anon\/embed\/qEWeWLP?height=450&amp;theme-id=47434&amp;slug-hash=qEWeWLP&amp;default-tab=result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed qEWeWLP\" title=\"CodePen Embed qEWeWLP\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<p><a href=\"https:\/\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/02\/Screenshot-2025-02-14-at-7.54.12\u202fAM.png\">No dice on iOS<\/a> but it seems to work everywhere else.<\/p>\n\n\n\n<p>I did ultimately poke at the Lit site with DevTools and saw their approach was basically what I thought it was going to be. Except a little more fancy as they are using <code>color-mix()<\/code> with their primary colors and setting both the <code>color<\/code> and <code>background<\/code>. <\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"1014\" src=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/02\/contrast.png?resize=1024%2C1014&#038;ssl=1\" alt=\"\" class=\"wp-image-5199\" srcset=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/02\/contrast.png?resize=1024%2C1014&amp;ssl=1 1024w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/02\/contrast.png?resize=300%2C297&amp;ssl=1 300w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/02\/contrast.png?resize=150%2C150&amp;ssl=1 150w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/02\/contrast.png?resize=768%2C760&amp;ssl=1 768w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/02\/contrast.png?resize=1536%2C1521&amp;ssl=1 1536w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/02\/contrast.png?w=1818&amp;ssl=1 1818w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><\/figure>\n\n\n\n<p>If you&#8217;re thinking <em>why not go <strong>full<\/strong> rainbow<\/em> like with a <code>linear-gradient()<\/code> like any sane thinking person is of course, unfortunately gradients are <code>background-image<\/code>s, which are ignored here, with only <code>background-color<\/code> being supported. \ud83d\ude2d\ud83c\udf08<\/p>\n","protected":false},"excerpt":{"rendered":"<p>::selection is cool, but scoping it to selectors like :nth-child(5n+2) is even more fun, especially on a love filled ay like Valentine&#8217;s Day.<\/p>\n","protected":false},"author":1,"featured_media":5201,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"sig_custom_text":"","sig_image_type":"featured-image","sig_custom_image":0,"sig_is_disabled":false,"inline_featured_image":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[1],"tags":[299,7],"class_list":["post-5194","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog-post","tag-selection","tag-css"],"acf":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/02\/rainbow.png?fit=790%2C454&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/5194","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/comments?post=5194"}],"version-history":[{"count":3,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/5194\/revisions"}],"predecessor-version":[{"id":5202,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/5194\/revisions\/5202"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/media\/5201"}],"wp:attachment":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/media?parent=5194"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/categories?post=5194"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/tags?post=5194"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}