{"id":9507,"date":"2022-08-16T08:27:07","date_gmt":"2022-08-16T15:27:07","guid":{"rendered":"https:\/\/coderpad.io\/?p=9507"},"modified":"2023-06-05T14:16:52","modified_gmt":"2023-06-05T21:16:52","slug":"css-pseudo-classes","status":"publish","type":"post","link":"https:\/\/coderpad.io\/blog\/development\/css-pseudo-classes\/","title":{"rendered":"CSS Pseudo-Classes: The Must-Have, the Unusual, and the Experimental"},"content":{"rendered":"\n<p>Pseudo-classes are CSS features that allow us to do pretty amazing things when it comes to stylizing our content.<\/p>\n\n\n\n<p>Some common uses are applying styles to:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Mouse\/keyboard interactions (ex: <code>:hover<\/code>, <code>:active<\/code>, <code>:focus<\/code>),&nbsp;<\/li><li>Fields based on their content (ex: <code>:blank<\/code>, <code>:valid<\/code>, <code>:checked<\/code>) or&nbsp;<\/li><li>Elements based on their position in the DOM (ex: <code>:first-child<\/code>, <code>:nth-child()<\/code>, <code>:root<\/code>).<\/li><\/ul>\n\n\n\n<p>Pseudo-classes themselves are <em>keywords<\/em> that we add after our selector.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote\"><p>\ud83d\uddd2\ufe0f That syntax might remind you of <em>pseudo-elements<\/em> like <code>::before<\/code> and <code>::selection<\/code>. <em>Pseudo-classes and pseudo-elements are different things.<\/em> Pseudo-classes target states of an element like hover, disabled, or visited. Pseudo-elements affect elements that aren\u2019t explicitly written to the DOM, like a before element, a backdrop, or the selection. <strong>This post will focus on pseudo-classes only.<\/strong><\/p><\/blockquote>\n\n\n\n<p>In this post, we\u2019ll deep dive into pseudo-classes: the must-have, the unusual, and even the brand-new experimental ones!<\/p>\n\n\n<aside class=\"\n    cta-banner\n     cta-banner--bg-blue      cta-banner--has-media \"\ndata-block-name=\"cta-banner\">\n    <div class=\"inner\">\n        <div class=\"content\">\n                            <h2 class=\"headline\">Learn how to run front-end developer interviews that don&#8217;t suck<\/h2>\n            \n                            <div class=\"cta-buttons\">\n                                    <a href=\"https:\/\/coderpad.io\/blog\/interviewing\/5-tips-for-interviewing-frontend\/\" class=\"button  js-cta--read-our-guide\"  data-ga-category=\"CTA\" data-ga-label=\"Learn how to run front-end developer interviews that don&#039;t suck|Read our guide\">Read our guide<\/a>\n                                <\/div>\n                    <\/div>\n                    <div class=\"media\">\n                <img loading=\"lazy\" decoding=\"async\" width=\"432\" height=\"342\" src=\"https:\/\/coderpad.io\/wp-content\/uploads\/2022\/08\/Illustration-of-man-with-beard-popping-out-of-computer-chat.png\" class=\"attachment-large size-large\" alt=\"\" srcset=\"https:\/\/coderpad.io\/wp-content\/uploads\/2022\/08\/Illustration-of-man-with-beard-popping-out-of-computer-chat.png 432w, https:\/\/coderpad.io\/wp-content\/uploads\/2022\/08\/Illustration-of-man-with-beard-popping-out-of-computer-chat-300x238.png 300w\" sizes=\"auto, (max-width: 432px) 100vw, 432px\" \/>\n            <\/div>\n            <\/div>\n<\/aside>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Relative Selectors<\/strong><\/h2>\n\n\n\n<p><em>Relative selectors<\/em> are any pseudo-class used to select an element based on its position on the DOM.<\/p>\n\n\n\n<p>First, we have&nbsp; <code>:first-child<\/code> and <code>:last-child<\/code>. As their name suggests, they are used to select an element&#8217;s first or last child.<\/p>\n\n\n\n<p>On top of that, you can use <code>:nth-child<\/code> whenever you need to select the n<sup>th <\/sup>element.<\/p>\n\n\n\n<p>Here is an example:<\/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 shcb-wrap-lines\"><span class=\"hljs-comment\">\/* Make the first li red *\/<\/span>\n<span class=\"hljs-selector-tag\">li<\/span><span class=\"hljs-selector-pseudo\">:first-child<\/span>{\n\u00a0 <span class=\"hljs-attribute\">color<\/span>:red;\n}\n\n<span class=\"hljs-comment\">\/* Make the 3rd li blue *\/<\/span>\n<span class=\"hljs-selector-tag\">li<\/span><span class=\"hljs-selector-pseudo\">:nth-child(3)<\/span>{\n\u00a0 <span class=\"hljs-attribute\">color <\/span>: blue\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>Another example of a relative selector I use all the time for styling tables is the <code>:nth-child(even)<\/code> selector that selects even elements.<\/p>\n\n\n\n<p>There is also the standard trick of setting a margin-bottom to some elements and making it <code>0px<\/code> on the <code>:last-child<\/code>.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote\"><p>\ud83d\udca1 For more information, read the<a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/CSS\/Pseudo-classes#tree-structural_pseudo-classes\" target=\"_blank\" rel=\"noreferrer noopener\"> MDN documentation for relative selectors<\/a>, referred to as <em>Tree structural pseudo-classes<\/em>.<\/p><\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>User Interaction Selector<\/strong><\/h2>\n\n\n\n<p>A <em>user interaction selector<\/em> is any selector responding to user input like a mouse click, a hover, or an element focused on with the keyboard.<\/p>\n\n\n\n<p>In CSS development, we use these a <em>lot<\/em>, so let\u2019s dive into them!<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Link status pseudo-classes<\/strong><\/h3>\n\n\n\n<p>First, let\u2019s talk about the links. You can use the <code>:visited<\/code> pseudo-class to target any link that a user visited:<\/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 shcb-wrap-lines\"><span class=\"hljs-selector-tag\">a<\/span><span class=\"hljs-selector-pseudo\">:visited<\/span>{\n\u00a0 <span class=\"hljs-attribute\">color<\/span>: <span class=\"hljs-number\">#c58af9<\/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>That is the purple color you see on the Google results you\u2019ve already visited:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter is-resized\"><a href=\"https:\/\/d2h1bfu6zrdxog.cloudfront.net\/wp-content\/uploads\/2022\/08\/img_62f154c58605c.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/d2h1bfu6zrdxog.cloudfront.net\/wp-content\/uploads\/2022\/08\/img_62f154c58605c.png\" alt=\"\" width=\"685\" height=\"467\"\/><\/a><figcaption> Results from Google. The link you already visited appears in purple instead of blue, stylized using the<code> :visited<\/code> pseudo-class.<\/figcaption><\/figure>\n<\/div>\n\n\n<p>You can also target non-visited links by using the <code>:link<\/code> pseudo-class.<\/p>\n\n\n\n<p>In great news for CSS developers, another fascinating pseudo-class has recently been released &#8212; <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/CSS\/:any-link\" target=\"_blank\" rel=\"noreferrer noopener\"><code>:any-link<\/code><\/a>. It combines <code>:visited<\/code> and <code>:link<\/code>, and it targets all links (and <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/HTML\/Element\/area\" target=\"_blank\" rel=\"noreferrer noopener\"><code>area<\/code><\/a>) with a valid <code>href<\/code> attribute.<\/p>\n\n\n\n<p>There\u2019s also <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/CSS\/:local-link\" target=\"_blank\" rel=\"noreferrer noopener\"><code>:local-link<\/code><\/a>, the recently developed but not-yet-supported pseudo-class that targets links of the same domain you&#8217;re currently on.<\/p>\n\n\n\n<p>With these pseudo-classes, you can have a different style for a link pointing to an external domain than for the link pointing to the current website. If the <code>href<\/code> target is the same as the document URL, it will match.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Hover, Focus, and Active<\/strong><\/h3>\n\n\n\n<p>To target an element hovered over by the mouse, use the <code>:hover<\/code> pseudo-class. We use this for links, buttons, and other elements that will be clickable.<\/p>\n\n\n\n<p>Here is how you make a link go red on hover:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css shcb-wrap-lines\"><span class=\"hljs-selector-tag\">a<\/span><span class=\"hljs-selector-pseudo\">:hover<\/span>{\n\u00a0 <span class=\"hljs-attribute\">color<\/span>: red;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><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<blockquote class=\"wp-block-quote\"><p>\u26a0\ufe0f In reality, you can use <code>:hover<\/code> on any element you want, but be careful. If not done sparingly, it will confuse your users and create a bad experience for them.<\/p><\/blockquote>\n\n\n\n<p><code>:focus<\/code> is often used to target a field the user clicked or tabbed into. It\u2019s super useful for form fields and buttons.<\/p>\n\n\n\n<p>By default, the browser uses an <code>outline<\/code> on <code>:focus<\/code>, and of course you can overwrite this. That is how you edit the default outline:&nbsp;&nbsp;<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css shcb-wrap-lines\"><span class=\"hljs-selector-tag\">a<\/span><span class=\"hljs-selector-pseudo\">:focus<\/span>{\n\u00a0 <span class=\"hljs-attribute\">outline<\/span>: <span class=\"hljs-number\">2px<\/span> dashed blue;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><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<blockquote class=\"wp-block-quote\"><p>\u26a0\ufe0f Before you remove an outline on focus, remember that the browser uses an outline for accessibility concerns: <em>keyboard users should be able to clearly identify what\u2019s being focused on<\/em> (<em>aka<\/em> what will be triggered when pressing <code>Enter<\/code>). More information on this matter can be found in the focus indicator section of <a href=\"https:\/\/coderpad.io\/blog\/development\/introduction-to-web-accessibility-a11y\/#focus-indicators\" target=\"_blank\" rel=\"noreferrer noopener\">Introduction to Web Accessibility<\/a> by <a href=\"https:\/\/twitter.com\/crutchcorn\" target=\"_blank\" rel=\"noreferrer noopener\">Corbin Crutchley<\/a>.<\/p><\/blockquote>\n\n\n\n<p><code>:active<\/code> is used when a click is being made or held. I always use this to make the button \u201cpop\u201d on a click. It provides excellent visual feedback to the user, so they know the website acknowledged their click.<\/p>\n\n\n\n<p>I usually make a small <code>transform: translateY(2px);<\/code> when <code>:active<\/code> for my buttons \u2014 but you can get more creative, like the way<a href=\"https:\/\/mui.com\/material-ui\/react-button\/\" target=\"_blank\" rel=\"noreferrer noopener\"> Material UI Buttons<\/a> react on clicks:<\/p>\n\n\n\n<figure class=\"wp-block-video aligncenter\"><video height=\"168\" style=\"aspect-ratio: 660 \/ 168;\" width=\"660\" autoplay controls loop muted src=\"https:\/\/d2h1bfu6zrdxog.cloudfront.net\/wp-content\/uploads\/2022\/08\/csspseudoclass.mp4\"><\/video><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Focus-visible and Focus-within<\/strong><\/h3>\n\n\n\n<p>By default, when the user clicks on something with their mouse, it activates the <code>:focus<\/code> styling, even if you want to show that styling only for the keyboard. We may not want that behavior when focusing with the mouse simply because it <em>does not look good<\/em>, but we need it when using the keyboard for accessibility reasons.<\/p>\n\n\n\n<p>With the help of <code>:focus-visible<\/code>, you can style an element only when the user is focused with their keyboard. It will target elements that need to show focus, so it will target our element only if <code>:focus<\/code> is using <code>tab<\/code>.<\/p>\n\n\n\n<p>So when focusing on an element, the browser would determine if it matched <code>:focus-visible<\/code>, based on the input method used.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote\"><p>\ud83d\udca1 Check out the example below and<a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/CSS\/:focus-visible\" target=\"_blank\" rel=\"noreferrer noopener\"> the MDN documentation<\/a> for more information on <code>:focus-visible<\/code>.<\/p><\/blockquote>\n\n\n\n<p>Now let\u2019s talk about <code>:focus-within<\/code>. This powerful selector allows us to select an element based on its children&#8217;s focus state. Focus-within enables you to target a form that has a focus element <em>within<\/em>.<\/p>\n\n\n\n<p>Let\u2019s say you want the focus of an input to make the field container look focused instead of the input itself. You can disable the focus on the field and use <code>:focus-within<\/code> on the field container to make it look how you want it to.<\/p>\n\n\n\n<p>Take a look at the example below that demonstrates both <em>Focus-visible<\/em> and <em>Focus-within<\/em>. If you focus on the email field, you\u2019ll notice that the error message appears. Also, the focus is on the whole field, not just the input.<\/p>\n\n\n\n<p>Try clicking the different buttons. You\u2019ll see that the ones using focus-visible don\u2019t show any outline:<\/p>\n\n\n\n<script async=\"\" src=\"\/\/jsfiddle.net\/CoderPadKen\/m5dfohz0\/2\/embed\/html,css,result\/\"><\/script>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>The <code>:target<\/code> selector<\/strong><\/h3>\n\n\n\n<p>Did you know that instead of carrying you to another page, a link can target an element of the current page instead?<\/p>\n\n\n\n<p>If you use the <code>#<\/code> symbol and the element ID as an <code>href<\/code> attribute for your link, clicking it will make the user \u201cjump\u201d to the new element. In HTML, we call that an anchor.&nbsp;<\/p>\n\n\n\n<p>Anchors were always powerful and became even more so since the introduction of smooth-scrolling and <code>scroll-padding-top<\/code>. You can now make with native CSS what would have been quite a pain to do in JavaScript a few years ago.<\/p>\n\n\n\n<p>The <code>:target<\/code> pseudo-class expands what you can do with anchors by letting us stylize the targeted element.<\/p>\n\n\n\n<p>For our example below, you have a few paragraphs and a summary. By using <code>:target<\/code>, you can add an outline to the current paragraph:<\/p>\n\n\n\n<script async=\"\" src=\"\/\/jsfiddle.net\/CoderPadKen\/fmLvcp5z\/2\/embed\/html,css,result\/\"><\/script>\n\n\n\n<blockquote class=\"wp-block-quote\"><p>\ud83d\udca1 If you wonder how deep you can go with anchor links and the target pseudo-class, look at <a href=\"https:\/\/www.youtube.com\/watch?v=b--q6Fsf_cA\" target=\"_blank\" rel=\"noreferrer noopener\">Kevin Powell recreating the Netflix carousel with only CSS<\/a>.<\/p><\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Styling Form Fields<\/strong><\/h2>\n\n\n\n<p>Many pseudo-classes are available for us to make our form fields look significantly better.<\/p>\n\n\n\n<p>In this section, you\u2019ll look at disabled, required, optional, valid, and invalid pseudo-classes.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Disabled<\/strong><\/h3>\n\n\n\n<p>A disabled element cannot be interacted with \u2014 usually, this will be an input, a select, or a button. To disable an element, use the disabled attribute on our element in HTML.<\/p>\n\n\n\n<p>Visually, we show it by graying it out, making it evident that the element cannot be interacted with.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Required &amp; Optional<\/strong><\/h3>\n\n\n\n<p>In HTML, use the <code>required<\/code> attribute on an input to indicate its need to be filled before submitting the form. You can then use the <code>:required<\/code> pseudo-class to target those elements and put an emphasis on them.<\/p>\n\n\n\n<p>CSS also provides the <code>:optional<\/code> pseudo-class to target the inputs that are not required.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Valid &amp; Invalid<\/strong><\/h3>\n\n\n\n<p>When dealing with fields in HTML, you can specify what types of data are acceptable and what types are not. Using a <a href=\"https:\/\/coderpad.io\/blog\/development\/the-complete-guide-to-regular-expressions-regex\/\" target=\"_blank\" rel=\"noreferrer noopener\">REGEX expression<\/a>, you can ask for numbers, an email address, or even a custom pattern.<\/p>\n\n\n\n<p>In CSS, inputs have a <code>valid<\/code> or <code>invalid<\/code> state that you can stylize using the <code>:valid<\/code> and <code>:invalid<\/code> selectors.<\/p>\n\n\n\n<p>Usually, we display a red outline on <code>invalid<\/code> fields to clearly show the user which fields are blocking their form submission.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Example<\/strong><\/h3>\n\n\n\n<p>The example below is a form using all the form-related pseudo-classes we just mentioned.<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>The name field is <code>required<\/code> and is currently empty, so it\u2019s <code>invalid<\/code> and has a red outline.<\/li><li>The address is not required, so it is <code>valid<\/code> and has a green border even though it\u2019s empty.<\/li><li>The company is <code>disabled<\/code>, so its opacity is lower, and the cursor is set to <code>not-allowed<\/code>.<\/li><li>The email field is invalid as the value contains two <code>@<\/code> symbols. It is <code>invalid<\/code> and is stylized with a red border.<\/li><\/ul>\n\n\n\n<p>And as you can see, the form itself can be stylized with <code>:valid<\/code> and <code>:invalid<\/code> too. A form needs all its fields to be <code>valid<\/code> to be <code>valid<\/code> itself:<\/p>\n\n\n\n<script async=\"\" src=\"\/\/jsfiddle.net\/CoderPadKen\/an6c47t1\/embed\/html,css,result\/\"><\/script>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>New Pseudo-Classes<\/strong><\/h2>\n\n\n\n<p>All the pseudo-classes mentioned in this post, except for <code>:focus-within<\/code> and <code>:focus-visible<\/code>, were available in the ecosystem for quite some time.<\/p>\n\n\n\n<p>But in this section, we\u2019ll talk about new and exciting stuff.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>The <code>:not<\/code> selector<\/strong><\/h3>\n\n\n\n<p>The <code>:not<\/code> pseudo-class is pretty much self-explanatory. It allows us to declare what we do NOT want in our selector. It makes life much easier sometimes to exclude elements from our selector instead of including all the ones we want.<\/p>\n\n\n\n<p>The <code>:not<\/code> pseudo-class allows us to write a cleaner and more descriptive selector.<\/p>\n\n\n\n<p>Let\u2019s say you want to target every link that is not a button. You can now write it in a <em>much simpler<\/em> way:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css shcb-wrap-lines\"><span class=\"hljs-comment\">\/* without using :not *\/<\/span>\n<span class=\"hljs-selector-tag\">a<\/span> {\n\u00a0 <span class=\"hljs-attribute\">color<\/span>: brown;\n}\n<span class=\"hljs-selector-class\">.button<\/span> {\n\u00a0 <span class=\"hljs-attribute\">color<\/span>: white;\n}\n\n<span class=\"hljs-comment\">\/* using :not *\/<\/span>\n<span class=\"hljs-selector-tag\">a<\/span><span class=\"hljs-selector-pseudo\">:not(.button)<\/span> {\n\u00a0 <span class=\"hljs-attribute\">color<\/span>: brown;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><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>It doesn\u2019t look like a lot, but when using the <code>:not<\/code> selector, <em>you don\u2019t even need to know the button\u2019s color<\/em>.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote\"><p>\ud83d\udca1 Modern browsers have supported <code>:not<\/code> since 2020, look at the <a href=\"https:\/\/caniuse.com\/css-not-sel-list\" target=\"_blank\" rel=\"noreferrer noopener\">caniuse page<\/a> for more information.<\/p><\/blockquote>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>The <code>:where<\/code> &amp; <code>:is<\/code> pseudo-classes<\/strong><\/h3>\n\n\n\n<p>The <code>:is<\/code> selector allows us to write <a href=\"https:\/\/blog.boot.dev\/clean-code\/dry-code\/#:~:text=What%20is%20DRY%20Code%3F,data%20normalization%20to%20avoid%20redundancy.\" target=\"_blank\" rel=\"noreferrer noopener\">DRYer<\/a> code by consolidating multiple selectors. Let\u2019s say you need to target buttons from <code>.header<\/code>, <code>.footer<\/code> and <code>.sidebar<\/code>.<\/p>\n\n\n\n<p>Without the <code>:is<\/code> selector, you might write something like this:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css shcb-wrap-lines\"><span class=\"hljs-selector-class\">.header<\/span> <span class=\"hljs-selector-class\">.button<\/span>,\n<span class=\"hljs-selector-class\">.footer<\/span><span class=\"hljs-selector-class\">.button<\/span>,\n<span class=\"hljs-selector-class\">.sidebar<\/span> <span class=\"hljs-selector-class\">.button<\/span> {\n\u00a0 <span class=\"hljs-attribute\">background<\/span>: teal;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><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>This feels like unnecessary repetition, doesn\u2019t it?<\/p>\n\n\n\n<p>Using <code>:is<\/code> you can write:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css shcb-wrap-lines\"><span class=\"hljs-selector-pseudo\">:is(.header<\/span>, <span class=\"hljs-selector-class\">.foooter<\/span>, <span class=\"hljs-selector-class\">.sidebar<\/span>) <span class=\"hljs-selector-class\">.button<\/span> {\n\u00a0 <span class=\"hljs-attribute\">background<\/span>: teal;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><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>This code is shorter, easier to read, and&nbsp;<a href=\"https:\/\/caniuse.com\/css-matches-pseudo\" target=\"_blank\" rel=\"noreferrer noopener\">supported in major web browsers<\/a>.<\/p>\n\n\n\n<p>To understand <code>:where<\/code>, we need to talk about selector specificity.<\/p>\n\n\n\n<p>First, if you are unfamiliar with specificity, read this great<a href=\"https:\/\/www.smashingmagazine.com\/2007\/07\/css-specificity-things-you-should-know\/\" target=\"_blank\" rel=\"noreferrer noopener\"> deep dive from Smashing Magazine<\/a>.<\/p>\n\n\n\n<p>Also, to try your selector specificity, I recommend<a href=\"https:\/\/polypane.app\/css-specificity-calculator\/\" target=\"_blank\" rel=\"noreferrer noopener\"> this great tool<\/a> from Polypane.<\/p>\n\n\n\n<p>When working with large CSS codebases, specificity is always a struggle. When defining defaults, we need the specificity to be as low as possible.<\/p>\n\n\n\n<p>The <code>:where<\/code> pseudo-class acts like <code>:is<\/code>, but it <em>always has a 0 specificity<\/em>, when <code>:is<\/code> specificity will be the most specific in its selector list.<\/p>\n\n\n\n<p>It makes the <code>:where<\/code> super helpful in writing base styles that can easily be overwritten.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote\"><p> \ud83d\udca1 I recommend<a href=\"https:\/\/css-tricks.com\/using-the-specificity-of-where-as-a-css-reset\/\" target=\"_blank\" rel=\"noreferrer noopener\"> this post<\/a> by<a href=\"https:\/\/twitter.com\/mojtabaseyedi\" target=\"_blank\" rel=\"noreferrer noopener\"> Mojtaba Seyedi<\/a> going through an actual use case of the <code>where<\/code> pseudo-class in the context of a CSS reset.<\/p><\/blockquote>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>All about <code>:has<\/code>, a promising but experimental selector<\/strong><\/h3>\n\n\n\n<p>The <code>:has<\/code> selector allows you to select an element based on its children. You can, for example, use it for selecting any field container with an <code>:invalid<\/code> input inside.<\/p>\n\n\n\n<p>Unfortunately, as of this writing, the <code>:has<\/code> pseudo-class is not yet supported in major browsers.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><a href=\"https:\/\/d2h1bfu6zrdxog.cloudfront.net\/wp-content\/uploads\/2022\/08\/img_62f154c71127d.png\" target=\"_blank\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/d2h1bfu6zrdxog.cloudfront.net\/wp-content\/uploads\/2022\/08\/img_62f154c71127d.png\" alt=\"\"\/><\/a><figcaption><a href=\"https:\/\/caniuse.com\/css-has\" target=\"_blank\" rel=\"noreferrer noopener\">The `:has` pseudo-class on caniuse<\/a>. Currently only supported on Safari and the latest version of Chrome.<\/figcaption><\/figure>\n<\/div>\n\n\n<p>Still, we are getting there, and this is <em>exciting progress for CSS developers<\/em>.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote\"><p>\ud83d\udca1 If you want to read more about <code>:has<\/code>, I recommend<a href=\"https:\/\/twitter.com\/ibaslogic\/\" target=\"_blank\" rel=\"noreferrer noopener\"> Ibadehin Mojeed<\/a>\u2019s article on it, <a href=\"https:\/\/blog.logrocket.com\/how-when-use-css-has-selector\/\" target=\"_blank\" rel=\"noreferrer noopener\">How and when to use the CSS <code>:has<\/code> selector<\/a>. Also, check the<a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/CSS\/:has\" target=\"_blank\" rel=\"noreferrer noopener\"> MDN documentation<\/a> for it.<\/p><\/blockquote>\n\n\n\n<p><strong><em>I&#8217;m Tom Quinonero, I write about design systems and CSS.<\/em><\/strong><a href=\"https:\/\/twitter.com\/tomquinonero\" target=\"_blank\" rel=\"noreferrer noopener\"><strong><em> Follow me on Twitter<\/em><\/strong><\/a><strong><em> for more tips and resources \ud83e\udd19<\/em><\/strong><\/p>\n\n\n\n<p>Sources and Links:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/www.notion.so\/Pseudo-Classes-in-CSS-206043e785db437493aa9204bf5cab5f\" target=\"_blank\" rel=\"noreferrer noopener\">The CSS Specificity Calculator<\/a><\/li><li><a href=\"https:\/\/www.smashingmagazine.com\/2007\/07\/css-specificity-things-you-should-know\/\" target=\"_blank\" rel=\"noreferrer noopener\">CSS Specificity: Things You Should Know<\/a> by<a href=\"https:\/\/twitter.com\/vitalyf\" target=\"_blank\" rel=\"noreferrer noopener\"> Vitaly Friedman<\/a><\/li><li><a href=\"https:\/\/css-tricks.com\/using-the-specificity-of-where-as-a-css-reset\/\" target=\"_blank\" rel=\"noreferrer noopener\">Using the Specificity of :where() as a CSS Reset<\/a> by<a href=\"https:\/\/www.notion.so\/Pseudo-Classes-in-CSS-206043e785db437493aa9204bf5cab5f\" target=\"_blank\" rel=\"noreferrer noopener\"> Mojtaba Seyedi<\/a><\/li><li><a href=\"https:\/\/www.smashingmagazine.com\/2021\/04\/guide-supported-modern-css-pseudo-class-selectors\/\" target=\"_blank\" rel=\"noreferrer noopener\">A Guide To Newly Supported, Modern CSS Pseudo-Class Selectors<\/a> by<a href=\"https:\/\/twitter.com\/5t3ph\/\" target=\"_blank\" rel=\"noreferrer noopener\"> Stephanie Eckels<\/a><\/li><li><a href=\"https:\/\/blog.logrocket.com\/how-when-use-css-has-selector\/\" target=\"_blank\" rel=\"noreferrer noopener\">How and when to use the CSS :has selector<\/a> by<a href=\"https:\/\/twitter.com\/ibaslogic\/\" target=\"_blank\" rel=\"noreferrer noopener\"> Ibadehin Mojeed<\/a><\/li><\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Pseudo-classes are CSS features that allow us to do pretty amazing things when it comes to stylizing our content. Pseudo-classes come in handy, and not many developers know about them. This article teaches the must-have, the unusual, and the experimental pseudo-classes.<\/p>\n","protected":false},"author":12,"featured_media":15415,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[9],"tags":[],"persona":[29],"blog-programming-language":[62],"keyword-cluster":[],"class_list":["post-9507","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-development"],"acf":[],"_links":{"self":[{"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/posts\/9507","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/users\/12"}],"replies":[{"embeddable":true,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/comments?post=9507"}],"version-history":[{"count":169,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/posts\/9507\/revisions"}],"predecessor-version":[{"id":21586,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/posts\/9507\/revisions\/21586"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/media\/15415"}],"wp:attachment":[{"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/media?parent=9507"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/categories?post=9507"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/tags?post=9507"},{"taxonomy":"persona","embeddable":true,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/persona?post=9507"},{"taxonomy":"blog-programming-language","embeddable":true,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/blog-programming-language?post=9507"},{"taxonomy":"keyword-cluster","embeddable":true,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/keyword-cluster?post=9507"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}