From modern-selectors
Modern CSS Selectors Quick Reference - :has(), :is(), :where(), :not(), and advanced selector patterns
How this skill is triggered — by the user, by Claude, or both
Slash command
/modern-selectors:modern-selectors-referenceThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Comprehensive reference for modern CSS selectors including :has(), :is(), :where(), :not(), :nth-child(), :focus-visible, attribute selectors, and combinators.
Comprehensive reference for modern CSS selectors including :has(), :is(), :where(), :not(), :nth-child(), :focus-visible, attribute selectors, and combinators.
Select parent elements based on their descendants.
parent:has(selector) { }
/* Card with image */
.card:has(img) {
display: grid;
grid-template-columns: 200px 1fr;
}
/* Card without image */
.card:not(:has(img)) {
display: block;
max-width: 600px;
}
.form-group:has(input:invalid) {
border-left: 3px solid #ef4444;
background-color: #fef2f2;
}
.form-group:has(input:valid) {
border-left: 3px solid #10b981;
background-color: #f0fdf4;
}
.form-group:has(input:focus) {
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
}
.list-item:has(button:hover) {
background-color: #f3f4f6;
transform: translateX(4px);
}
.card:has(a:hover) {
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
transform: translateY(-4px);
}
.gallery:not(:has(img)) {
min-height: 400px;
display: flex;
align-items: center;
justify-content: center;
background-color: #f9fafb;
border: 2px dashed #d1d5db;
}
.gallery:not(:has(img))::after {
content: "No images to display";
color: #6b7280;
}
.accordion-item:has(input[type="checkbox"]:checked) .accordion-content {
max-height: 500px;
opacity: 1;
padding: 1rem;
}
.tabs:has(#tab1:checked) #panel1,
.tabs:has(#tab2:checked) #panel2 {
display: block;
}
.grid:has(> .item:nth-child(n+7)) {
/* 7+ items - use 4 columns */
grid-template-columns: repeat(4, 1fr);
}
.grid:has(> .item:nth-child(n+4):nth-child(-n+6)) {
/* 4-6 items - use 3 columns */
grid-template-columns: repeat(3, 1fr);
}
Group selectors with maintained specificity.
:is(selector1, selector2, selector3) { }
:is(h1, h2, h3, h4, h5, h6) {
font-family: 'Inter', sans-serif;
font-weight: 700;
line-height: 1.2;
}
:is(h1, h2, h3) {
color: #1f2937;
}
button:is(:hover, :focus-visible, :active) {
outline: 2px solid #3b82f6;
outline-offset: 2px;
}
input:is(:hover, :focus) {
border-color: #3b82f6;
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
}
:is(input, select, textarea):is(:focus, :focus-visible) {
outline: 2px solid #3b82f6;
border-color: #3b82f6;
}
:is(input, select, textarea):disabled {
opacity: 0.6;
cursor: not-allowed;
background-color: #f3f4f6;
}
/* Before: */
article h2,
aside h2,
section h2 {
font-size: 1.5rem;
}
/* After: */
:is(article, aside, section) h2 {
font-size: 1.5rem;
}
:is([data-state="loading"], [data-state="pending"], [data-state="processing"]) {
pointer-events: none;
opacity: 0.6;
}
:is([data-theme="dark"], [data-mode="night"]) {
--bg-color: #1f2937;
--text-color: #f9fafb;
}
Same as :is() but with zero specificity (easy to override).
:where(selector1, selector2) { }
:where(button, .btn) {
/* Specificity: 0,0,0 - easily overridden */
padding: 0.5rem 1rem;
border: none;
border-radius: 0.375rem;
}
/* Simple class overrides */
.btn-large {
/* Specificity: 0,1,0 - wins */
padding: 1rem 2rem;
}
:where(ul, ol)[role="list"] {
list-style: none;
padding: 0;
margin: 0;
}
:where(h1, h2, h3, h4, h5, h6) {
margin: 0;
font-weight: inherit;
font-size: inherit;
}
:where(a) {
color: inherit;
text-decoration: none;
}
/* Easy to override */
.nav-link {
color: #3b82f6;
}
:where(input, select, textarea) {
font-family: inherit;
font-size: 100%;
line-height: 1.5;
margin: 0;
}
:where([data-theme="dark"]) :where(h1, h2, h3, p) {
color: #f9fafb;
}
:where([data-theme="dark"]) :where(input, textarea) {
background-color: #374151;
color: #f9fafb;
}
Exclude elements from selection.
:not(selector) { }
:not(selector1, selector2) { } /* Multiple */
button:not(.btn-danger) {
background-color: #3b82f6;
}
button:not(.btn-danger):not(.btn-ghost):not(:disabled) {
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
.list-item:not(:first-child) {
margin-top: 1rem;
}
.list-item:not(:last-child) {
border-bottom: 1px solid #e5e7eb;
padding-bottom: 1rem;
}
input:not(:invalid):not(.error):focus {
border-color: #10b981;
box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.1);
}
input:not(:placeholder-shown):invalid {
border-color: #ef4444;
}
img:not([alt]) {
/* Highlight images missing alt text */
outline: 3px solid #ef4444;
}
a:not([href]) {
color: inherit;
cursor: default;
}
input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]) {
width: 100%;
padding: 0.5rem;
border: 1px solid #d1d5db;
}
.card:not(:has(img)) {
padding: 2rem;
}
.form:not(:has(input:invalid)) .submit-btn {
opacity: 1;
cursor: pointer;
}
Select elements based on their position.
:nth-child(n) /* Number */
:nth-child(odd) /* Keyword */
:nth-child(even) /* Keyword */
:nth-child(2n+1) /* Formula */
:nth-child(n+3) /* Starting from */
:nth-child(-n+5) /* First n */
tr:nth-child(odd) {
background-color: #f9fafb;
}
tr:nth-child(even) {
background-color: #ffffff;
}
.grid-item:nth-child(3n) {
/* Every 3rd item */
grid-column: span 2;
}
.grid-item:nth-child(5n) {
/* Every 5th item */
background-color: #fef3c7;
}
.list-item:nth-child(-n+3) {
/* First 3 items */
font-weight: 600;
background-color: #eff6ff;
}
.list-item:nth-last-child(-n+3) {
/* Last 3 items */
opacity: 0.6;
}
.item:nth-child(n+4):nth-child(-n+8) {
/* Items 4-8 */
border-left: 3px solid #3b82f6;
}
.tag:nth-child(5n+1) { background-color: #ef4444; }
.tag:nth-child(5n+2) { background-color: #3b82f6; }
.tag:nth-child(5n+3) { background-color: #10b981; }
.tag:nth-child(5n+4) { background-color: #f59e0b; }
.tag:nth-child(5n) { background-color: #8b5cf6; }
.fade-in:nth-child(1) { animation-delay: 0s; }
.fade-in:nth-child(2) { animation-delay: 0.1s; }
.fade-in:nth-child(3) { animation-delay: 0.2s; }
/* Or formula */
.fade-in:nth-child(n) {
animation-delay: calc(0.1s * (var(--index)));
}
/* Exactly 4 items */
li:first-child:nth-last-child(4),
li:first-child:nth-last-child(4) ~ li {
width: 25%;
}
/* 5+ items */
li:first-child:nth-last-child(n+5),
li:first-child:nth-last-child(n+5) ~ li {
width: 20%;
}
Show focus only for keyboard navigation.
:focus-visible { } /* Keyboard navigation only */
:focus-within { } /* Parent when child focused */
button:focus-visible {
outline: 2px solid #3b82f6;
outline-offset: 2px;
}
button:focus:not(:focus-visible) {
/* Mouse click - no outline */
outline: none;
}
a:focus-visible {
outline: 2px dashed #3b82f6;
outline-offset: 4px;
background-color: #eff6ff;
border-radius: 0.25rem;
}
.form-group:focus-within {
background-color: #eff6ff;
border-left: 3px solid #3b82f6;
}
.form-group:focus-within label {
color: #1e40af;
font-weight: 600;
}
.search-container:focus-within {
width: 400px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.search-container:focus-within .search-suggestions {
display: block;
opacity: 1;
}
.card:focus-within {
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
transform: translateY(-2px);
border-color: #3b82f6;
}
.skip-link {
position: absolute;
top: -100px;
}
.skip-link:focus-visible {
top: 0;
z-index: 9999;
padding: 1rem 2rem;
background-color: #1f2937;
color: white;
}
Powerful attribute-based element selection.
[attr] /* Has attribute */
[attr="value"] /* Exact match */
[attr~="value"] /* Word in list */
[attr|="value"] /* Exact or prefix */
[attr^="value"] /* Starts with */
[attr$="value"] /* Ends with */
[attr*="value"] /* Contains */
[attr operator value i] /* Case-insensitive */
input[required] {
border-left: 3px solid #ef4444;
}
input[required]:valid {
border-left-color: #10b981;
}
input[type="email"] {
background-image: url('icons/email.svg');
background-position: right 0.5rem center;
background-repeat: no-repeat;
}
input[type="password"] {
font-family: 'monospace';
letter-spacing: 0.1em;
}
a[href^="http://"],
a[href^="https://"] {
padding-right: 1.25rem;
background-image: url('icons/external-link.svg');
background-position: right center;
}
a[href^="mailto:"] {
color: #3b82f6;
text-decoration: underline;
}
a[href$=".pdf"]::after {
content: " (PDF)";
font-size: 0.75rem;
color: #ef4444;
}
a[href$=".doc"]::after,
a[href$=".docx"]::after {
content: " (Word)";
color: #2563eb;
}
[data-state="loading"] {
pointer-events: none;
opacity: 0.6;
}
[data-state="error"] {
background-color: #fef2f2;
border-color: #ef4444;
}
[data-state="success"] {
background-color: #f0fdf4;
border-color: #10b981;
}
[aria-expanded="true"] .icon-chevron {
transform: rotate(180deg);
}
[aria-disabled="true"] {
opacity: 0.5;
cursor: not-allowed;
}
[aria-current="page"] {
font-weight: 700;
border-left: 3px solid #3b82f6;
}
a[href$=".PDF" i]::after,
a[href$=".pdf" i]::after {
content: " (PDF)";
}
Select elements based on relationships.
parent descendant /* Descendant (any depth) */
parent > child /* Direct child only */
element + adjacent /* Immediately following */
element ~ sibling /* All following siblings */
article p {
line-height: 1.6;
margin-bottom: 1rem;
}
.card a {
color: #3b82f6;
text-decoration: none;
}
nav > ul {
display: flex;
gap: 1rem;
list-style: none;
}
.container > * {
margin-bottom: 1rem;
}
h2 + p {
/* Paragraph immediately after h2 */
font-size: 1.125rem;
font-weight: 500;
}
label + input {
margin-top: 0.25rem;
}
h2 ~ p {
/* All paragraphs after h2 */
text-align: left;
}
input:checked ~ label {
font-weight: 600;
color: #1f2937;
}
.form-field + .form-field {
margin-top: 1.5rem;
}
.breadcrumb > li + li::before {
content: "/";
margin: 0 0.5rem;
color: #9ca3af;
}
input[type="checkbox"]:checked + label {
color: #10b981;
font-weight: 600;
}
input[type="radio"]:checked ~ .radio-content {
display: block;
padding: 1rem;
background-color: #f0fdf4;
}
Understanding and managing CSS specificity.
1,0,0,00,1,0,00,0,1,00,0,0,1:where() always: 0,0,0,0:is()/:not()/:has(): specificity of most specific argument/* Specificity: 0,0,0,0 */
:where(.btn) {
padding: 0.5rem 1rem;
}
/* Specificity: 0,0,1,0 - easily wins */
.btn-primary {
background-color: #3b82f6;
}
/* Specificity: 0,0,1,0 (from .active) */
:is(.active, p) {
font-weight: 600;
}
/* Layer 1: Resets - 0 specificity */
:where(*, *::before, *::after) {
box-sizing: border-box;
}
/* Layer 2: Elements - 0,0,0,1 */
button {
font-family: inherit;
}
/* Layer 3: Utilities - 0,0,1,0 */
.text-center { text-align: center; }
/* Layer 4: Components - 0,0,1,0 to 0,0,2,0 */
.btn { padding: 0.5rem 1rem; }
.btn.btn-large { padding: 1rem 2rem; }
/* Layer 5: States - 0,0,2,0 */
.btn:hover { transform: translateY(-2px); }
details {
border: 1px solid #e5e7eb;
border-radius: 0.5rem;
padding: 1rem;
}
details summary {
cursor: pointer;
font-weight: 600;
list-style: none;
}
details summary::before {
content: "▶";
margin-right: 0.5rem;
transition: transform 0.3s;
}
details[open] summary::before {
transform: rotate(90deg);
}
details:has(summary:hover) {
border-color: #3b82f6;
background-color: #eff6ff;
}
.form-field:has(input:not(:placeholder-shown):invalid) {
border-left: 3px solid #ef4444;
background-color: #fef2f2;
}
.form-field:has(input:not(:placeholder-shown):valid) {
border-left: 3px solid #10b981;
background-color: #f0fdf4;
}
.error-message {
display: none;
color: #ef4444;
}
.form-field:has(input:invalid:not(:placeholder-shown)) .error-message {
display: block;
}
.card {
border: 1px solid #e5e7eb;
transition: all 0.3s;
}
.card:has(a:hover),
.card:has(button:hover) {
border-color: #3b82f6;
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
transform: translateY(-4px);
}
/* Exactly 4 items */
li:first-child:nth-last-child(4),
li:first-child:nth-last-child(4) ~ li {
width: 25%;
}
/* 5-8 items */
li:first-child:nth-last-child(n+5):nth-last-child(-n+8),
li:first-child:nth-last-child(n+5):nth-last-child(-n+8) ~ li {
width: calc(100% / 4);
}
/* 9+ items - switch to grid */
ul:has(> li:nth-child(9)) {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
}
Fallback:
@supports selector(:has(*)) {
.card:has(img) {
display: grid;
}
}
Scope :has() queries
/* SLOW */
body:has(.modal-open) { }
/* BETTER */
.modal-wrapper:has(.modal.is-open) { }
Use specific selectors
/* SLOW */
div div div p { }
/* FAST */
.article-content p { }
Avoid universal selectors in :has()
/* SLOW */
:has(*) { }
/* BETTER */
.container:has(.specific-class) { }
This reference covers the most common modern CSS selector patterns. Use these to reduce JavaScript dependencies, create more maintainable stylesheets, and build accessible interfaces.
Guides creation, editing, and verification of skills for AI coding agents using test-driven development with subagent scenarios. Use when authoring or debugging skills.
npx claudepluginhub ehssanatassi/ui-marketplace --plugin modern-selectors