CSS pseudo-classes and pseudo-elements for advanced styling

Alex Chang Feb 2026
2 tabs
/* Interactive pseudo-classes */
a:link { color: blue; }
a:visited { color: purple; }
a:hover { text-decoration: underline; }
a:active { color: red; }
a:focus { outline: 2px solid orange; }

button:hover {
  background-color: darkblue;
}

button:active {
  transform: scale(0.98);
}

button:focus {
  box-shadow: 0 0 0 3px rgba(66, 153, 225, 0.5);
}

button:focus:not(:focus-visible) {
  box-shadow: none; /* Remove for mouse clicks */
}

button:focus-visible {
  outline: 2px solid blue; /* Only for keyboard focus */
}

/* Structural pseudo-classes */
li:first-child {
  font-weight: bold;
}

li:last-child {
  border-bottom: none;
}

li:only-child {
  text-align: center;
}

p:first-of-type {
  font-size: 1.2rem;
}

p:last-of-type {
  margin-bottom: 0;
}

/* nth-child patterns */
tr:nth-child(odd) {
  background-color: #f9f9f9; /* Zebra striping */
}

tr:nth-child(even) {
  background-color: white;
}

li:nth-child(3) {
  color: red; /* Third item */
}

li:nth-child(3n) {
  /* Every 3rd: 3, 6, 9... */
  font-weight: bold;
}

li:nth-child(3n+1) {
  /* 1, 4, 7, 10... */
  color: blue;
}

li:nth-child(3n+2) {
  /* 2, 5, 8, 11... */
  color: green;
}

div:nth-child(-n+3) {
  /* First 3 elements */
  border-color: red;
}

li:nth-last-child(2) {
  /* Second from last */
  font-style: italic;
}

/* Form pseudo-classes */
input:focus {
  border-color: blue;
  outline: none;
}

input:disabled {
  background-color: #f0f0f0;
  cursor: not-allowed;
}

input:enabled {
  cursor: text;
}

input:read-only {
  background-color: #f9f9f9;
}

input:read-write {
  border: 1px solid #ccc;
}

input:required {
  border-left: 3px solid blue;
}

input:optional {
  border-left: 3px solid gray;
}

input:valid {
  border-color: green;
}

input:invalid {
  border-color: red;
}

input:in-range {
  border-color: green;
}

input:out-of-range {
  border-color: red;
  background-color: #ffe6e6;
}

input[type="checkbox"]:checked {
  background-color: blue;
}

input[type="checkbox"]:indeterminate {
  background-color: gray;
}

option:checked {
  background-color: lightblue;
}

/* Placeholder state */
input:placeholder-shown {
  border-color: #ccc;
}

input:not(:placeholder-shown) {
  border-color: blue;
}

/* Target pseudo-class */
:target {
  background-color: yellow;
  animation: highlight 2s;
}

@keyframes highlight {
  from { background-color: yellow; }
  to { background-color: transparent; }
}

/* Negation pseudo-class */
li:not(.special) {
  color: gray;
}

input:not([type="submit"]):not([type="button"]) {
  padding: 0.5rem;
}

/* Empty pseudo-class */
p:empty {
  display: none;
}

div:empty::before {
  content: "No content available";
  color: gray;
  font-style: italic;
}

/* Modern pseudo-classes */
:is(h1, h2, h3):hover {
  color: blue;
}

:where(article, section) p {
  line-height: 1.6;
}

.card:has(img) {
  display: grid;
  grid-template-columns: 200px 1fr;
}

form:has(input:invalid) {
  border: 2px solid red;
}

label:has(+ input:focus) {
  color: blue;
  font-weight: bold;
}

/* Language pseudo-class */
:lang(en) { quotes: '"' '"'; }
:lang(fr) { quotes: '«' '»'; }

/* User action pseudo-classes */
.tooltip:hover::after {
  content: attr(data-tooltip);
  display: block;
}
2 files · css Explain with highlit

Pseudo-classes select elements based on state like :hover, :focus, :active, and :visited. I use :nth-child() and :nth-of-type() for pattern-based selection. The :first-child, :last-child, and :only-child target specific positions. Form pseudo-classes include :valid, :invalid, :required, :disabled, and :checked. Pseudo-elements create virtual elements with ::before and ::after using the content property. The ::first-line and ::first-letter style text portions. Using ::placeholder customizes input placeholders. The ::selection changes text highlight colors. Modern ::marker styles list bullets and numbers. The ::backdrop styles fullscreen and dialog backgrounds. Understanding pseudo-classes vs pseudo-elements improves CSS capabilities.