{"id":9469,"date":"2026-05-04T10:10:56","date_gmt":"2026-05-04T15:10:56","guid":{"rendered":"https:\/\/frontendmasters.com\/blog\/?p=9469"},"modified":"2026-05-04T10:10:57","modified_gmt":"2026-05-04T15:10:57","slug":"css-n-of-selectors-for-conditional-validation","status":"publish","type":"post","link":"https:\/\/frontendmasters.com\/blog\/css-n-of-selectors-for-conditional-validation\/","title":{"rendered":"CSS `n of` Selectors for Conditional Validation"},"content":{"rendered":"\n<p>Sometimes we do a cursory check on user input controls before they\u2019re all set for data validation and submission. For instance, a form might only unlock its submit button when the user has filled in a certain number of fields. Or a user needs to fill in a field in the right way to take the next step.<\/p>\n\n\n\n<p>This is a great way to <strong>cut down on submission mistakes and help users make sure everything is as right as possible for submission with less hassle<\/strong>. It\u2019s even more effective when designed to give real-time feedback.<\/p>\n\n\n\n<p>CSS lets you handle some of these simple checks right away, even before the browser\u2019s validation routine runs following a submission trigger. The <code>:valid<\/code> and <code>:invalid<\/code> pseudo-classes are good examples of that. They allow browsers style fields as you type, so you can see if the data you\u2019re entering is in the right format.<\/p>\n\n\n\n<p>Similarly, <strong>the<\/strong> <code>n of &lt;selector-list&gt;<\/code> <strong>syntax in the<\/strong> <code>:nth-child<\/code> <strong>selector can also be very useful for a preliminary validation<\/strong>. First, let\u2019s see what it does.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">About <code>n of<\/code> selectors<\/h2>\n\n\n\n<p>The <code>:nth-child()<\/code> selector picks elements from all siblings, counting from the first. The <code>n of selectors<\/code> syntax version does the same, but <strong>only from siblings matching the given selectors<\/strong>.<\/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-comment\">\/* selects second element *\/<\/span>\n<span class=\"hljs-selector-pseudo\">:nth-child(2)<\/span> { }\n\n<span class=\"hljs-comment\">\/* selects second of all elements with class marked *\/<\/span>\n<span class=\"hljs-selector-pseudo\">:nth-child(2<\/span> <span class=\"hljs-selector-tag\">of<\/span> <span class=\"hljs-selector-class\">.marked<\/span>) { }<\/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<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_EaNYZKN\" src=\"\/\/codepen.io\/anon\/embed\/EaNYZKN?height=450&amp;theme-id=1&amp;slug-hash=EaNYZKN&amp;default-tab=result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed EaNYZKN\" title=\"CodePen Embed EaNYZKN\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<p>Although not explicitly, in a rudimentary way, <code>n of<\/code> selectors can keep count of a selector\u2019s matching elements. The same also works for pseudo-classes which usually indicate the state of an element.&nbsp;<\/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-tag\">label<\/span><span class=\"hljs-selector-pseudo\">:nth-child(2<\/span> <span class=\"hljs-selector-tag\">of<\/span> <span class=\"hljs-selector-pseudo\">:has(<\/span><span class=\"hljs-selector-pseudo\">:checked))<\/span> {\n  <span class=\"hljs-attribute\">color<\/span>: red;\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>Say, in a todo list, we want to give the user a sense of accomplishment as they clear items, perhaps every three? <code>n of selectors<\/code> can help with that, because we will know when a third or sixth <code>:checked<\/code> box appears in the list.<\/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\"><span class=\"hljs-selector-class\">.list<\/span><span class=\"hljs-selector-pseudo\">:has(<\/span><span class=\"hljs-selector-pseudo\">:nth-child(3<\/span> <span class=\"hljs-selector-tag\">of<\/span> <span class=\"hljs-selector-pseudo\">:checked))<\/span> {\n   <span class=\"hljs-comment\">\/* A cheer for user on getting three things done in the list *\/<\/span>\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<p>The demo below the second of all labels with a <code>:checked<\/code> box as a decendent.<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_GgNKrpB\" src=\"\/\/codepen.io\/anon\/embed\/GgNKrpB?height=450&amp;theme-id=1&amp;slug-hash=GgNKrpB&amp;default-tab=result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed GgNKrpB\" title=\"CodePen Embed GgNKrpB\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<p class=\"learn-more\">Possible Webkit bug (April 2026): In some contexts, state-based styling with \u201cn of selector\u201d may not work as expected in Webkit browsers. Compare with Firefox results.&nbsp;<\/p>\n\n\n\n<p>We apply the same idea to our initial check of input controls. Imagine a form where the user needs to fill out at least three fields. We give them a heads-up about this requirement before they begin, and once they\u2019ve completed three fields, we let them know they\u2019ve met that requirement. I\u2019ll use simple validations in the demo to check if the fields are filled, but you can use any validation you prefer.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The Example<\/h2>\n\n\n\n<p>Here are the fields:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"field\"<\/span>&gt;<\/span>\n  <span class=\"hljs-comment\">&lt;!-- email label --&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">input<\/span> <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"email\"<\/span> <span class=\"hljs-attr\">placeholder<\/span>=<span class=\"hljs-string\">\"jane.doe@example.org\"<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"field\"<\/span>&gt;<\/span>\n  <span class=\"hljs-comment\">&lt;!-- social url label --&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">input<\/span> <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"url\"<\/span> <span class=\"hljs-attr\">placeholder<\/span>=<span class=\"hljs-string\">\"https:\/\/linkedin.com\/janedoe\"<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"field\"<\/span>&gt;<\/span>\n  <span class=\"hljs-comment\">&lt;!-- social handle label --&gt;<\/span>  \n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">input<\/span> <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"text\"<\/span> <span class=\"hljs-attr\">placeholder<\/span>=<span class=\"hljs-string\">\"@username\"<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"field\"<\/span>&gt;<\/span>\n  <span class=\"hljs-comment\">&lt;!-- gender label --&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">span<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">input<\/span> <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"radio\"<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"gender\"<\/span>&gt;<\/span> <span class=\"hljs-comment\">&lt;!-- male label --&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">input<\/span> <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"radio\"<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"gender\"<\/span>&gt;<\/span> <span class=\"hljs-comment\">&lt;!-- female label --&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">input<\/span> <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"radio\"<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"gender\"<\/span>&gt;<\/span> <span class=\"hljs-comment\">&lt;!-- other label --&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">span<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"field\"<\/span>&gt;<\/span>\n  <span class=\"hljs-comment\">&lt;!-- contact preference label --&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">select<\/span>  <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"contact-preference\"<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">option<\/span> <span class=\"hljs-attr\">value<\/span>=<span class=\"hljs-string\">\"\"<\/span> <span class=\"hljs-attr\">selected<\/span>&gt;<\/span><span class=\"hljs-comment\">&lt;!-- text --&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">option<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">option<\/span> <span class=\"hljs-attr\">value<\/span>=<span class=\"hljs-string\">\"email\"<\/span>&gt;<\/span><span class=\"hljs-comment\">&lt;!-- text --&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">option<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">option<\/span> <span class=\"hljs-attr\">value<\/span>=<span class=\"hljs-string\">\"phone\"<\/span>&gt;<\/span><span class=\"hljs-comment\">&lt;!-- text --&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">option<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">option<\/span> <span class=\"hljs-attr\">value<\/span>=<span class=\"hljs-string\">\"whatsapp\"<\/span>&gt;<\/span><span class=\"hljs-comment\">&lt;!-- text --&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">option<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">option<\/span> <span class=\"hljs-attr\">value<\/span>=<span class=\"hljs-string\">\"sms\"<\/span>&gt;<\/span><span class=\"hljs-comment\">&lt;!-- text --&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">option<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">select<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Selectors for Validating<\/h3>\n\n\n\n<p>For the text, URL, and email, I\u2019ll check <strong>if the<\/strong> <code>placeholder<\/code> <strong>is visible<\/strong>. If it isn\u2019t, I\u2019ll know the user has filled it in. For the radio group, I\u2019ll check <strong>if it\u2019s<\/strong> <code>:checked<\/code>. And for the select box, I\u2019ll look for the <strong>absence of the<\/strong> <code>:checked<\/code> <strong>state in the<\/strong> <code>option<\/code> <strong>with empty string value<\/strong>.<\/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\"><span class=\"hljs-selector-attr\">&#91;type=<span class=\"hljs-string\">\"email\"<\/span>]<\/span><span class=\"hljs-selector-pseudo\">:not(<\/span><span class=\"hljs-selector-pseudo\">:placeholder-shown)<\/span>,\n<span class=\"hljs-selector-attr\">&#91;type=<span class=\"hljs-string\">\"url\"<\/span>]<\/span><span class=\"hljs-selector-pseudo\">:not(<\/span><span class=\"hljs-selector-pseudo\">:placeholder-shown)<\/span>,\n<span class=\"hljs-selector-attr\">&#91;type=<span class=\"hljs-string\">\"text\"<\/span>]<\/span><span class=\"hljs-selector-pseudo\">:not(<\/span><span class=\"hljs-selector-pseudo\">:placeholder-shown)<\/span>,\n<span class=\"hljs-selector-attr\">&#91;type=<span class=\"hljs-string\">\"radio\"<\/span>]<\/span><span class=\"hljs-selector-pseudo\">:checked<\/span>,\n<span class=\"hljs-selector-tag\">option<\/span><span class=\"hljs-selector-attr\">&#91;value=<span class=\"hljs-string\">\"\"<\/span>]<\/span><span class=\"hljs-selector-pseudo\">:not(<\/span><span class=\"hljs-selector-pseudo\">:checked)<\/span> {}<\/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><strong>If any of the selectors above match, I\u2019ll assume the user has filled a field<\/strong>. If the user has filled three or more fields, <code>3 of selectors-for-filled-fields<\/code> syntax will match the third of all the filled fields. First, let me combine the selectors that use <code>placeholder<\/code> to shorten the code.<\/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\"><span class=\"hljs-selector-pseudo\">:where(<\/span><span class=\"hljs-selector-attr\">&#91;type=<span class=\"hljs-string\">\"email\"<\/span>]<\/span>,\n<span class=\"hljs-selector-attr\">&#91;type=<span class=\"hljs-string\">\"url\"<\/span>]<\/span>,\n<span class=\"hljs-selector-attr\">&#91;type=<span class=\"hljs-string\">\"text\"<\/span>]<\/span>)<span class=\"hljs-selector-pseudo\">:not(<\/span><span class=\"hljs-selector-pseudo\">:placeholder-shown)<\/span> {}<\/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<h3 class=\"wp-block-heading\">Validation<\/h3>\n\n\n\n<p>To select <code>.field<\/code>s that have these controls:<\/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\"><span class=\"hljs-selector-class\">.field<\/span><span class=\"hljs-selector-pseudo\">:has(<\/span>\n  <span class=\"hljs-selector-pseudo\">:where(<\/span><span class=\"hljs-selector-attr\">&#91;type=<span class=\"hljs-string\">\"email\"<\/span>]<\/span>,<span class=\"hljs-selector-attr\">&#91;type=<span class=\"hljs-string\">\"url\"<\/span>]<\/span>,<span class=\"hljs-selector-attr\">&#91;type=<span class=\"hljs-string\">\"text\"<\/span>]<\/span>)<span class=\"hljs-selector-pseudo\">:not(<\/span><span class=\"hljs-selector-pseudo\">:placeholder-shown)<\/span>,\n  <span class=\"hljs-selector-attr\">&#91;type=<span class=\"hljs-string\">\"radio\"<\/span>]<\/span><span class=\"hljs-selector-pseudo\">:checked<\/span>, \n  <span class=\"hljs-selector-tag\">option<\/span><span class=\"hljs-selector-attr\">&#91;value=<span class=\"hljs-string\">\"\"<\/span>]<\/span><span class=\"hljs-selector-pseudo\">:not(<\/span><span class=\"hljs-selector-pseudo\">:checked)<\/span>\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>And finally, to select the 3rd one of these <code>.field<\/code>s:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-pseudo\">:nth-child(3<\/span> <span class=\"hljs-selector-tag\">of<\/span> <span class=\"hljs-selector-class\">.field<\/span><span class=\"hljs-selector-pseudo\">:has(<\/span>\n  <span class=\"hljs-selector-pseudo\">:where(<\/span><span class=\"hljs-selector-attr\">&#91;type=<span class=\"hljs-string\">\"email\"<\/span>]<\/span>,<span class=\"hljs-selector-attr\">&#91;type=<span class=\"hljs-string\">\"url\"<\/span>]<\/span>,<span class=\"hljs-selector-attr\">&#91;type=<span class=\"hljs-string\">\"text\"<\/span>]<\/span>)<span class=\"hljs-selector-pseudo\">:not(<\/span><span class=\"hljs-selector-pseudo\">:placeholder-shown)<\/span>, \n  <span class=\"hljs-selector-attr\">&#91;type=<span class=\"hljs-string\">\"radio\"<\/span>]<\/span><span class=\"hljs-selector-pseudo\">:checked<\/span>, \n  <span class=\"hljs-selector-tag\">option<\/span><span class=\"hljs-selector-attr\">&#91;value=<span class=\"hljs-string\">\"\"<\/span>]<\/span><span class=\"hljs-selector-pseudo\">:not(<\/span><span class=\"hljs-selector-pseudo\">:checked)))<\/span> {\n  <span class=\"hljs-comment\">\/* Let user know they've filled three fields *\/<\/span>\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><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<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_QwKJxQm\" src=\"\/\/codepen.io\/anon\/embed\/QwKJxQm?height=550&amp;theme-id=1&amp;slug-hash=QwKJxQm&amp;default-tab=result\" height=\"550\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed QwKJxQm\" title=\"CodePen Embed QwKJxQm\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">More Examples<\/h2>\n\n\n\n<p>Here&#8217;s a simplified version where the form becomes submit-able when two of the four (text-only) fields are filled out.<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_gbwyGgE\" src=\"\/\/codepen.io\/anon\/embed\/gbwyGgE?height=550&amp;theme-id=1&amp;slug-hash=gbwyGgE&amp;default-tab=result\" height=\"550\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed gbwyGgE\" title=\"CodePen Embed gbwyGgE\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<p>And here&#8217;s another example where a special message is shown after the form when three of the fields are filled out.<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_EagJwWv\" src=\"\/\/codepen.io\/anon\/embed\/EagJwWv?height=650&amp;theme-id=1&amp;slug-hash=EagJwWv&amp;default-tab=result\" height=\"650\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed EagJwWv\" title=\"CodePen Embed EagJwWv\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<p>Like I mentioned before, you can use any validations you like. For example, you could use <code>select:valid<\/code> for a <code>required<\/code> select box that\u2019s been selected, or <code>:in-range<\/code> for a user input that\u2019s within a <code>min<\/code>&#8211;<code>max<\/code> range. No matter what types of fields you\u2019re using or how you\u2019re validating them, you can use their validating state selectors to see <strong>if a certain number of them have been found<\/strong>. <\/p>\n\n\n\n<p>I suggest letting users know what\u2019s expected of them when filling out the form and letting them know when the preliminary checks have been cleared.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>:nth-child supports the keyword `of` in the argument which can be super useful on it&#8217;s own. Combo that with a :has() selector to do some pretty wild stuff!<\/p>\n","protected":false},"author":20,"featured_media":9546,"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":[478,7,82],"class_list":["post-9469","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog-post","tag-nth-child-2","tag-css","tag-form-validation"],"acf":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2026\/05\/nth-of.jpg?fit=2000%2C1200&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/9469","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\/20"}],"replies":[{"embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/comments?post=9469"}],"version-history":[{"count":7,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/9469\/revisions"}],"predecessor-version":[{"id":9549,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/9469\/revisions\/9549"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/media\/9546"}],"wp:attachment":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/media?parent=9469"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/categories?post=9469"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/tags?post=9469"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}