{"id":393,"date":"2024-05-02T10:00:00","date_gmt":"2024-05-02T10:00:00","guid":{"rendered":"https:\/\/kerrprogroup.com\/?p=393"},"modified":"2025-03-19T12:20:50","modified_gmt":"2025-03-19T12:20:50","slug":"combining-css-has-and-html-select-for-greater-conditional-styling","status":"publish","type":"post","link":"https:\/\/kerrprogroup.com\/index.php\/2024\/05\/02\/combining-css-has-and-html-select-for-greater-conditional-styling\/","title":{"rendered":"Combining CSS\u00a0:has()\u00a0And HTML\u00a0<select>\u00a0For Greater Conditional Styling"},"content":{"rendered":"

Combining CSS\u00a0:has()\u00a0And HTML\u00a0<select>\u00a0For Greater Conditional Styling<\/title><\/p>\n<article>\n<header>\n<h1>Combining CSS\u00a0:has()\u00a0And HTML\u00a0<select>\u00a0For Greater Conditional Styling<\/h1>\n<address>Amit Sheen<\/address>\n<p> 2024-05-02T10:00:00+00:00<br \/>\n 2025-03-19T12:04:52+00:00<br \/>\n <\/header>\n<p>Even though the CSS <code>:has()<\/code> pseudo-class is relatively new, we already know a lot about it, thanks to many, many articles and tutorials demonstrating its powerful ability to conditionally select elements based on their contents. We\u2019ve all seen the card component and header examples, but the conditional nature of <code>:has()<\/code> actually makes it adept at working with form controls, which are pretty conditional in nature as well.<\/p>\n<p>Let\u2019s look specifically at the <code><\/code> element. With it, we can make a choice from a series of <code><\/code>s. Combined with <code>:has()<\/code>, we are capable of manipulating styles based on the selected <code><\/code>.<\/p>\n<pre><code class=\"language-html\">\n Option 1\n Option 2\n Option 3\n Option 4\n Option 5\n\n<\/code><\/pre>\n<p>This is your standard <code><\/code> usage, producing a dropdown menu that contains options for user selection. And while it\u2019s not mandatory, I\u2019ve added the <code>selected<\/code> attribute to the first <code><\/code> to set it as the initial selected option.<\/p>\n<p>Applying styles based on a user\u2019s selection is not a new thing. We\u2019ve had the <a href=\"https:\/\/css-tricks.com\/the-checkbox-hack\/\">Checkbox Hack<\/a> in our pockets for years, using the <code>:checked<\/code> CSS pseudo-class to style the element based on the selected option. In this next example, I\u2019m changing the element\u2019s <code>color<\/code> and the <code>background-color<\/code> properties based on the selected <code><\/code>.<\/p>\n<figure class=\"break-out\">\n<p data-height=\"480\" data-theme-id=\"light\" data-slug-hash=\"oNOwded\" data-user=\"amit_sheen\" data-default-tab=\"result\" class=\"codepen\">See the Pen [demo 01 – Using the :has selector on a dropdown menu](https:\/\/codepen.io\/smashingmag\/pen\/oNOwded) by <a href=\"https:\/\/codepen.io\/amit_sheen\">Amit Sheen<\/a>.<\/p><figcaption>See the Pen <a href=\"https:\/\/codepen.io\/smashingmag\/pen\/oNOwded\">demo 01 – Using the :has selector on a dropdown menu<\/a> by <a href=\"https:\/\/codepen.io\/amit_sheen\">Amit Sheen<\/a>.<\/figcaption><\/figure>\n<div data-audience=\"non-subscriber\" data-remove=\"true\" class=\"feature-panel-container\">\n<aside class=\"feature-panel\">\n<div class=\"feature-panel-left-col\">\n<div class=\"feature-panel-description\">\n<p>Meet <strong><a data-instant href=\"https:\/\/www.smashingconf.com\/online-workshops\/\">Smashing Workshops<\/a><\/strong> on <strong>front-end, design & UX<\/strong>, with practical takeaways, live sessions, <strong>video recordings<\/strong> and a friendly Q&A. With Brad Frost, St\u00e9ph Walter and <a href=\"https:\/\/smashingconf.com\/online-workshops\/workshops\">so many others<\/a>.<\/p>\n<p><a data-instant href=\"smashing-workshops\" class=\"btn btn--green btn--large\">Jump to the workshops\u00a0\u21ac<\/a><\/div>\n<\/div>\n<div class=\"feature-panel-right-col\"><a data-instant href=\"smashing-workshops\" class=\"feature-panel-image-link\"><\/p>\n<div class=\"feature-panel-image\">\n<img decoding=\"async\" loading=\"lazy\" class=\"feature-panel-image-img lazyload\" src=\"data:image\/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" alt=\"Feature Panel\" width=\"257\" height=\"355\" data-src=\"\/images\/smashing-cat\/cat-scubadiving-panel.svg\"><\/p>\n<\/div>\n<p><\/a>\n<\/div>\n<\/aside>\n<\/div>\n<p>But that\u2019s limited to styling the current element, right? If a particular <code><\/code> is <code>:checked<\/code>, then we style its style. We can write a more complex selector and style child elements based on whether an <code><\/code> is selected up the chain, but that\u2019s a one-way road in that we are unable to style up parent elements even further up the chain.<\/p>\n<p>That\u2019s where <code>:has()<\/code> comes in because styling up the chain is exactly what it is designed to do; in fact, it\u2019s often called <a href=\"https:\/\/www.smashingmagazine.com\/2021\/06\/has-native-css-parent-selector\/\">the \u201cparent selector\u201d<\/a> for this reason (although <a href=\"https:\/\/developer.chrome.com\/blog\/has-m105\/\">\u201cfamily selector\u201d<\/a> may be a better descriptor).<\/p>\n<p>For example, if we want to change the <code>background-color<\/code> of the <code><\/code> element according to the value of the selected <code><\/code>, <strong>we select the element if it has a specific <code>[value]<\/code> that is <code>:checked<\/code>.<\/strong><\/p>\n<figure class=\"break-out\">\n<p data-height=\"480\" data-theme-id=\"light\" data-slug-hash=\"eYoRopZ\" data-user=\"amit_sheen\" data-default-tab=\"result\" class=\"codepen\">See the Pen [demo 02 – Using the :has selector on a dropdown menu](https:\/\/codepen.io\/smashingmag\/pen\/eYoRopZ) by <a href=\"https:\/\/codepen.io\/amit_sheen\">Amit Sheen<\/a>.<\/p><figcaption>See the Pen <a href=\"https:\/\/codepen.io\/smashingmag\/pen\/eYoRopZ\">demo 02 – Using the :has selector on a dropdown menu<\/a> by <a href=\"https:\/\/codepen.io\/amit_sheen\">Amit Sheen<\/a>.<\/figcaption><\/figure>\n<p>Just how practical is this? One way I\u2019m using it is to style mandatory <code><\/code> elements without a valid selected <code><\/code>. So, instead of applying styles if the element <code>:has()<\/code> a <code>:checked<\/code> state, I am applying styles if the <code>required<\/code> element does <code>:not(:has(:checked))<\/code>.<\/p>\n<figure class=\"break-out\">\n<p data-height=\"480\" data-theme-id=\"light\" data-slug-hash=\"jORLoVM\" data-user=\"amit_sheen\" data-default-tab=\"result\" class=\"codepen\">See the Pen [demo 02.1 – Using the :has selector on a dropdown menu](https:\/\/codepen.io\/smashingmag\/pen\/jORLoVM) by <a href=\"https:\/\/codepen.io\/amit_sheen\">Amit Sheen<\/a>.<\/p><figcaption>See the Pen <a href=\"https:\/\/codepen.io\/smashingmag\/pen\/jORLoVM\">demo 02.1 – Using the :has selector on a dropdown menu<\/a> by <a href=\"https:\/\/codepen.io\/amit_sheen\">Amit Sheen<\/a>.<\/figcaption><\/figure>\n<p>But why stop there? If we can use <code>:has()<\/code> to style the <code><\/code> element as the parent of an <code><\/code>, then we can also use it to style the parent of the <code><\/code>, as well as its parent, in addition to its parent, and even its parent\u2026 all the way up the chain to the <code>:root<\/code> element. We could even bring <code>:has()<\/code> all the way up the chain and sniff out whether any <code><\/code> child of the document <code>:root<\/code> <code>:has()<\/code> a particular <code><\/code> that is <code>:checked<\/code>:<\/p>\n<pre><code class=\"language-css\">:root:has(select [value=\"foo\"]:checked) {\n \/\/ Styles applied if is -ed\n}\n<\/code><\/pre>\n<p>This is useful for <strong>setting a custom property value dynamically<\/strong> or <strong>applying a set of styles for the whole page<\/strong>. Let\u2019s make a little style picker that illustrates the idea of setting styles on an entire page.<\/p>\n<figure class=\"break-out\">\n<p data-height=\"480\" data-theme-id=\"light\" data-slug-hash=\"yLrXroO\" data-user=\"amit_sheen\" data-default-tab=\"result\" class=\"codepen\">See the Pen [demo 03 – Using the :has selector on a dropdown menu](https:\/\/codepen.io\/smashingmag\/pen\/yLrXroO) by <a href=\"https:\/\/codepen.io\/amit_sheen\">Amit Sheen<\/a>.<\/p><figcaption>See the Pen <a href=\"https:\/\/codepen.io\/smashingmag\/pen\/yLrXroO\">demo 03 – Using the :has selector on a dropdown menu<\/a> by <a href=\"https:\/\/codepen.io\/amit_sheen\">Amit Sheen<\/a>.<\/figcaption><\/figure>\n<p>Or perhaps a theme picker:<\/p>\n<figure class=\"break-out\">\n<p data-height=\"480\" data-theme-id=\"light\" data-slug-hash=\"OJGgjaJ\" data-user=\"amit_sheen\" data-default-tab=\"result\" class=\"codepen\">See the Pen [demo 04 – Using the :has selector on a dropdown menu](https:\/\/codepen.io\/smashingmag\/pen\/OJGgjaJ) by <a href=\"https:\/\/codepen.io\/amit_sheen\">Amit Sheen<\/a>.<\/p><figcaption>See the Pen <a href=\"https:\/\/codepen.io\/smashingmag\/pen\/OJGgjaJ\">demo 04 – Using the :has selector on a dropdown menu<\/a> by <a href=\"https:\/\/codepen.io\/amit_sheen\">Amit Sheen<\/a>.<\/figcaption><\/figure>\n<p>How that last example works is that I added a class to each <code><\/code> element and referenced that class inside the <code>:has()<\/code> selector in order to prevent unwanted selections in the event that there are multiple <code><\/code> elements on the page.<\/p>\n<p>And, of course, we don\u2019t have to go all the way up to the <code>:root<\/code> element. If we\u2019re working with a specific component, we can scope <code>:has()<\/code> to that component like in the following demo of a star rating component.<\/p>\n<figure class=\"break-out\">\n<p data-height=\"480\" data-theme-id=\"light\" data-slug-hash=\"rNbwvqz\" data-user=\"amit_sheen\" data-default-tab=\"result\" class=\"codepen\">See the Pen [demo 05 – Using the :has selector on a dropdown menu](https:\/\/codepen.io\/smashingmag\/pen\/rNbwvqz) by <a href=\"https:\/\/codepen.io\/amit_sheen\">Amit Sheen<\/a>.<\/p><figcaption>See the Pen <a href=\"https:\/\/codepen.io\/smashingmag\/pen\/rNbwvqz\">demo 05 – Using the :has selector on a dropdown menu<\/a> by <a href=\"https:\/\/codepen.io\/amit_sheen\">Amit Sheen<\/a>.<\/figcaption><\/figure>\n<blockquote><p>Watch a short video tutorial I made on using <a href=\"https:\/\/youtu.be\/33Q3CnBm0UU\">CSS to create 3D animated stars<\/a>.<\/p><\/blockquote>\n<div class=\"partners__lead-place\"><\/div>\n<h2 id=\"conclusion\">Conclusion<\/h2>\n<p>We\u2019d be doing <code>:has()<\/code> a great disservice if we only saw it as a \u201cparent selector\u201d rather than <strong>the great conditional operator<\/strong> it is for applying styles all the way up the chain. Seen this way, it\u2019s more of a modern upgrade to the Checkbox Hack in that it sends styles up like we were never able to do before.<\/p>\n<p>There are endless examples of using <code>:has()<\/code> to create style variations of a component according to its contents. We\u2019ve even seen it used to accomplish the once-complicated <a href=\"https:\/\/css-tricks.com\/creating-animated-clickable-cards-with-the-has-relational-pseudo-class\/\">linked card pattern<\/a>. But now you have an example for using it to create dropdown menus that conditionally apply styles (or don\u2019t) to a page or component based the currently selected option \u2014 depending on how far up the chain we scope it.<\/p>\n<p>I\u2019ve used this technique a few different ways \u2014 e.g., as form validation, a style picker, and star ratings \u2014 but I\u2019m sure there are plenty of other ways you can imagine how to use it in your own work. And if you are using <code>:has()<\/code> on a <code><\/code> element for something different or interesting, let me know because I\u2019d love to see it!<\/p>\n<h4 id=\"further-reading-on-smashingmag\">Further Reading On SmashingMag<\/h4>\n<ul>\n<li>\u201c<a href=\"https:\/\/www.smashingmagazine.com\/2023\/01\/level-up-css-skills-has-selector\/\">Level Up Your CSS Skills With The :has() Selector<\/a>,\u201d Stephanie Eckles<\/li>\n<li>\u201c<a href=\"https:\/\/www.smashingmagazine.com\/2021\/06\/has-native-css-parent-selector\/\">Meet :has, A Native CSS Parent Selector (And More)<\/a>,\u201d Adrian Bece<\/li>\n<li>\u201c<a href=\"https:\/\/www.smashingmagazine.com\/2024\/03\/setting-persisting-color-scheme-preferences-css-javascript\/\">Setting And Persisting Color Scheme Preferences With CSS And A \u201cTouch\u201d Of JavaScript<\/a>,\u201d Henry Bley-Vroman<\/li>\n<li>\u201c<a href=\"https:\/\/www.smashingmagazine.com\/2024\/01\/css-border-image-property\/\">The Complex But Awesome CSS border-image Property<\/a>,\u201d Temani Afif<\/li>\n<\/ul>\n<div class=\"signature\">\n <img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" alt=\"Smashing Editorial\" width=\"35\" height=\"46\" loading=\"lazy\" class=\"lazyload\" data-src=\"https:\/\/www.smashingmagazine.com\/images\/logo\/logo--red.png\"><br \/>\n <span>(gg, yk)<\/span>\n<\/div>\n<\/article>\n","protected":false},"excerpt":{"rendered":"<p>Combining CSS\u00a0:has()\u00a0And HTML\u00a0<select>\u00a0For Greater Conditional Styling Combining CSS\u00a0:has()\u00a0And HTML\u00a0<select>\u00a0For Greater Conditional Styling Amit Sheen 2024-05-02T10:00:00+00:00 2025-03-19T12:04:52+00:00 Even though the CSS :has() pseudo-class is relatively new, we already know a lot about it, thanks to many, many articles and tutorials demonstrating its powerful ability to conditionally select elements based on their contents. We\u2019ve all seen the card component and header examples, but the conditional nature of :has() actually makes it adept…<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[11],"tags":[],"_links":{"self":[{"href":"https:\/\/kerrprogroup.com\/index.php\/wp-json\/wp\/v2\/posts\/393"}],"collection":[{"href":"https:\/\/kerrprogroup.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/kerrprogroup.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/kerrprogroup.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/kerrprogroup.com\/index.php\/wp-json\/wp\/v2\/comments?post=393"}],"version-history":[{"count":1,"href":"https:\/\/kerrprogroup.com\/index.php\/wp-json\/wp\/v2\/posts\/393\/revisions"}],"predecessor-version":[{"id":394,"href":"https:\/\/kerrprogroup.com\/index.php\/wp-json\/wp\/v2\/posts\/393\/revisions\/394"}],"wp:attachment":[{"href":"https:\/\/kerrprogroup.com\/index.php\/wp-json\/wp\/v2\/media?parent=393"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/kerrprogroup.com\/index.php\/wp-json\/wp\/v2\/categories?post=393"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/kerrprogroup.com\/index.php\/wp-json\/wp\/v2\/tags?post=393"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}