Pseudo Class Selectors
Pseudo Class Selectors are used to style HTML elements when they are in a special condition or state.
That means: You don’t need to add any class or ID — CSS will automatically detect the condition and apply the style.
We use pseudo-classes when we want to style things like:
- When a user hovers the mouse on something,
- When a link is visited,
- When an input is focused (clicked or active),
- When an element is the first or last in a list.
By using pseudo-class selectors, you can make your website more interactive and smart, without needing any extra code.

What is a Pseudo-class?
A pseudo-class is used to style an element when something special happens to it — like when the mouse is on it, it’s clicked, it’s focused, or it is the first one in a list.
You don’t need to add any new class or ID in your HTML.
A pseudo-class starts with a colon : and is written with the element name.
It helps you style elements only in certain situations, like:
- When the user hovers the mouse,
- When an input is selected,
- Or when an element is the first one in a group.
General Syntax:
selector:pseudo-class {
property: value;
}Types of Pseudo-Class
- Structural Pseudo-classes
- User Action Pseudo-classes
Structural Pseudo-classes
What are Structural Pseudo-classes in CSS?
Structural pseudo-classes help us style elements based on their position or structure in the HTML.
That means you can target:
- The first element,
- The last element,
- The second, third, or even/odd ones,
- Or if there’s only one element inside a parent.
You don’t need to give any extra class or ID.
CSS will check the structure of the HTML and apply the style automatically.
Structural pseudo-classes are:
:first-child:last-child:only-child:nth-child(n):nth-last-child(n):first-of-type:last-of-type:only-of-type:nth-of-type(n):nth-last-of-type(n):empty
Let’s understand one by one
:first-child
This selector targets an element only if it is the very first child inside its parent.
If a tag is the first item inside another tag, this pseudo-class can style it.
If there are multiple children inside a parent, only the first one will be selected.
Example:
<div>
<p>This is first</p> <!-- First child -->
<p>This is second</p>
</div>CSS:
p:first-child {
color: red;
}Only the first <p> will become red, because it is the first child inside the <div>.
If <p> is not the first tag (for example if an <h1> comes first), then the rule will not apply.
:last-child
Example:
<div> <p>This is first</p> <p>This is second</p> <!-- Last child --> </div>
CSS:
p:last-child {
color: blue;
}Only the second <p> will become blue, because it is the last child in the <div>.
If some other element comes after it (like a <span>), then the rule won’t apply to <p>.
:only-child
This selector targets an element only if it is the only child inside its parent.
It works only when there is just one element inside a parent.
Example:
<div> <p>This is the only child</p> <!-- Only child --> </div>
CSS:
p:only-child {
font-weight: bold;
}The <p> will become bold because it is the only child of the <div>.
But if there is even one more tag inside the <div>, this CSS will not apply.
:nth-child(n)
This selector selects an element based on its number position inside its parent.
It allows you to style the 1st, 2nd, 3rd, 4th… child in a container.
Example:
<ul> <li>Apple</li> <!-- 1st --> <li>Mango</li> <!-- 2nd --> <li>Banana</li> <!-- 3rd --> </ul>
CSS:
li:nth-child(2) {
color: green;
}Only “Mango” will become green because it is the second <li>.
You can also use:
:nth-child(odd)→ Selects 1st, 3rd, 5th…:nth-child(even)→ Selects 2nd, 4th, 6th…
But remember, :nth-child counts all types of tags inside the parent.
:nth-last-child(n)
This selector is just like :nth-child, but it counts from the end.
It helps you style the last one, second last, third last, etc.
Example:
<ul> <li>One</li> <!-- 1st from start --> <li>Two</li> <li>Three</li> <!-- 1st from end --> </ul>
CSS:
li:nth-last-child(1) {
color: orange;
}“Three” will become orange because it is the first from the bottom.
This is useful when you don’t know how many items are there but want to style the last few.
:first-of-type
This selector selects the first element of a specific type (like first <p>, first <h1>, etc.) inside a parent.
It ignores other types and looks for the first one of that kind.
Example:
<div> <h2>Heading</h2> <p>First paragraph</p> <!-- First <p> --> <p>Second paragraph</p> </div>
CSS:
div p:first-of-type {
color: brown;
}“First paragraph” will become brown, because it’s the first <p>, even though it’s not the first child overall.
:last-of-type
This selects the last element of a specific type inside the parent.
It selects the last <p>, <div>, <li>, or any tag type you mention.
Example:
<div>
<p>First paragraph</p>
<p>Last paragraph</p> <!-- Last <p> -->
</div>CSS:
div p:last-of-type {
color: purple;
}“Last paragraph” will turn purple, because it’s the last <p> inside the <div>.
:only-of-type
This selects an element only if it’s the only one of its tag type in its parent.
It works when there is just one <p> or one <div> inside a parent.
Example:
<div>
<h1>This is a heading</h1>
<p>This is the only paragraph</p> <!-- Only <p> -->
</div>CSS:
div p:only-of-type {
color: teal;
}The <p> will become teal because it is the only <p> inside the <div>.
Even if there are other elements like <h1>, it will still work, as long as there’s only one <p>.
:nth-of-type(n)
This selects the nth element of the same tag type, inside its parent.
It helps you pick the 1st <p>, 2nd <p>, 3rd <p>, and so on.
Example:
<div>
<p>First paragraph</p> <!-- 1st <p> -->
<p>Second paragraph</p> <!-- 2nd <p> -->
</div>CSS:
p:nth-of-type(2) {
color: navy;
}“Second paragraph” will become navy, because it is the second <p>.
It does not count other types of elements, only <p>
:nth-last-of-type(n)
This is like :nth-of-type but it counts from the end.
It selects the last <p>, second last <p>, and so on.
Example:
<div>
<p>First paragraph</p> <!-- 2nd from end -->
<p>Last paragraph</p> <!-- 1st from end -->
</div>CSS:
p:nth-last-of-type(1) {
color: green;
}“Last paragraph” will become green, because it is the last <p>.
:empty
This selects an element that has no children at all.
It will apply only if the tag is completely empty. No text, no space, no tag inside it.
Example:
<div>
<p>This is not empty</p>
<p></p> <!-- Empty element -->
</div>CSS:
p:empty {
height: 20px;
background: gray;
}The empty <p> will get a height and background color.
If it has even a space inside, it is not considered empty.
User Action Pseudo-classes
These pseudo-classes are used in CSS to apply styles when a user interacts with an element on the webpage.
When someone clicks, hovers, focuses, or visits something — these selectors help us style the element during that action.
You don’t need to write any extra class or ID in HTML.
CSS will automatically detect the action and apply the style.
User Action Pseudo-classes are:
:hover:active:focus:focus-visible:focus-within:visited:link:target:root:enabled:disabled:checked:indeterminate:default:valid:invalid:in-range:out-of-range:required:optional:read-only:read-write
:hover
:hover is a user action pseudo-class in CSS. It is used to apply styles to an element when the mouse pointer is placed over it.
This does not require any clicking. Just moving the mouse over the element is enough to trigger it.
When does it get activated?
:hover gets activated:
- When the user moves the mouse onto the element.
- The style stays as long as the mouse is on the element.
- As soon as the mouse leaves the element, the style is removed.
This works on most HTML elements like:
<a>(links)<button><div><img><input>
:hover is mainly used to:
- Show visual feedback when the user points to something
- Indicate that something is clickable
- Improve user experience
Example: Button hover effect
HTML
<button>Hover me</button>
CSS
button:hover {
background-color: lightblue;
color: black;
}When the user moves the mouse over the button, its background becomes light blue and text becomes black.
As soon as the mouse moves away, the original style comes back.
:active
:active is a user action pseudo-class in CSS.
It is used to apply styles to an element at the exact moment when the user is clicking it.
It means, the style will appear only while the mouse button is pressed down on the element.
When a user clicks on a button, link, or any element:
- As soon as the user presses down the mouse button, the style appears.
- When the user releases the mouse button, the style goes away immediately.
Example: Button active effect
HTML
<button>Click Me</button>CSS
button:active {
background-color: gray;
transform: scale(0.95);
}When the user clicks and holds the button, it becomes gray and slightly shrinks (due to scale(0.95)).
As soon as the click is released, the button returns to normal.
:focus
:focus is a user action pseudo-class in CSS.
It is used to apply styles to an element when the element is focused by the user.
Focus means the element is ready to receive input or is selected by the user.
For example:
- When you click on an input box or press Tab key to move to an input box, that box is said to be “focused”.
- When an element gets focus, it is active for typing or interacting.
Example: Input field focus effect
HTML
<input type="text" placeholder="Type here">CSS
input:focus {
border: 2px solid blue;
background-color: lightyellow;
}Explanation:
When you click inside the input box or press Tab to focus it, the border turns blue and background becomes light yellow.
:visited
:visited is a user action pseudo-class in CSS.
It is used to apply styles to a link (<a> tag) after the user has already clicked it or visited it before.
If you have clicked on a link and visited that page in the past,
CSS will automatically detect that and apply the style you set using :visited.
It only works with <a> (anchor) tags having an href attribute.
Example: Basic visited link effect
HTML
<a href="https://example.com">Visit Example</a>CSS
a:visited {
color: purple;
}Explanation:
- When the user clicks the link and visits the page,
the link turns purple after they return to the original page. - This helps the user know they have already visited that link.
:link
:link is a user action pseudo-class in CSS.
It is used to style a link (<a> tag) that has not been visited yet by the user.
This pseudo-class applies styles to links that the user has never clicked or visited before.
It works only on links having an href attribute.
Example: Basic link styling
HTML
<a href="https://example.com">Example Website</a>CSS
a:link {
color: blue;
}Explanation:
- The link appears blue if the user has never clicked it before.
- Once the user clicks it and visits the page, it will no longer be blue (unless you also style :visited).
Most Important Questions
What is the difference between :nth-child() and :nth-of-type() pseudo-classes? Explain with examples.
Both selectors are used to select elements based on their position, but they have different scopes:
:nth-child(n)
- Selects the element that is the nth child of its parent, no matter what type it is.
- Counts all types of siblings.
:nth-of-type(n)
- Selects the nth child of the same type among its siblings.
- Only counts siblings of the same tag name.
Example:
HTML
<ul>
<li>Item 1</li>
<p>Paragraph</p>
<li>Item 2</li>
<li>Item 3</li>
</ul>CSS
li:nth-child(2) {
color: red; /* Targets <p>, because it's the 2nd child overall */
}
li:nth-of-type(2) {
color: blue; /* Targets the 2nd <li> element among its siblings */
}:nth-child()counts every child.:nth-of-type()counts only the same type of tag.:nth-of-type()counts only the same type of tag.
How does :not() pseudo-class work? Give a scenario where it is very useful.
:not() is called the negation pseudo-class. It selects everything except the element(s) specified inside it.
Example:
button:not(.primary) {
background-color: grey;
}This example styles all buttons except those with the class .primary.
Scenario:
Imagine you have multiple buttons, but you want to apply a common style to all except a specific one. Instead of assigning classes everywhere, :not() makes the code cleaner.
What is the difference between :hover and :focus? When would you use each?
| Pseudo-Class | Meaning | Use Case |
:hover | When the user points to an element (with mouse) | Styling links or buttons on mouse hover |
:focus | When the element is focused (via keyboard, click, or programmatically) | Styling form inputs during typing or interaction |
input:hover {
border-color: green; /* When mouse hovers over input */
}
input:focus {
border-color: blue; /* When user clicks or tabs into input */
}:hoverneeds a pointing device (like mouse).:focusworks for keyboard navigation and accessibility.
How does :checked pseudo-class work? Can it be used for non-form elements?
:checked selects form elements that are in the checked state, such as:
- Radio buttons (
<input type="radio">) - Checkboxes (
<input type="checkbox">) <option>in a<select>
Example:
input[type="checkbox"]:checked {
background-color: yellow;
}- It cannot be used on non-form elements.
- It’s exclusively for form controls that have a “checked” state.
Why is :root preferred over html for CSS variables?
:rootselects the root element of the document, which is usually<html>.- However,
:roothas higher specificity thanhtmlselector. - Best practice is to define CSS variables inside
:rootto ensure they are available throughout the document.
Example:
:root {
--main-color: #333;
}
body {
color: var(--main-color);
}Why Not Just html?
htmland:roottechnically select the same element, but:rootworks better with variables and cascading because of specificity rules.- Helps avoid conflicts in larger stylesheets.
Can :hover and :focus happen at the same time? If yes, give an example.
Yes, they can occur at the same time.
- A user hovers on an input field and then clicks to focus it.
- Both
:hoverand:focusbecome active simultaneously.
input:hover {
border-color: green;
}
input:focus {
border-color: blue;
}Practical Use:
- You may need to handle this overlap carefully in design to avoid conflicting styles.
Does :hover work on mobile devices? Why or why not?
:hoverhas limited or no support on mobile and touchscreen-only devices.- Touchscreens do not have a concept of “hover” since there is no pointer.
- Some browsers simulate hover on first tap, but this is inconsistent.
- Best practice: Avoid relying solely on
:hoverfor critical actions on mobile.
Can :active work on non-link elements? Give an example.
Yes, :active can apply to any interactive element, not just links.
Example with Button:
button:active {
background-color: red;
}When the user clicks and holds the button, it enters :active state.
Why can’t we change certain properties (like display) in :visited pseudo-class?
Browsers restrict CSS properties in :visited to prevent websites from detecting a user’s browsing history.
Allowed Properties:
colorbackground-coloroutlineborder-color- Others that do not affect layout
Reason:
If unrestricted, malicious sites could detect whether you visited a specific URL by testing CSS changes.
What is the difference between :hover, :active, and :focus pseudo-classes?
| Pseudo-Class | Triggered When? | Use Case |
:hover | When user places the mouse over the element | Button hover, link hover, tooltips |
:active | When user clicks or activates the element | Button press effect, click effect |
:focus | When an element receives focus via mouse, keyboard (Tab), or script | Forms, inputs, buttons for accessibility |
Example:
button:hover { background: lightblue; }
button:active { background: blue; }
button:focus { outline: 2px solid orange; }:hoverhappens when mouse is over the element (before click).:activehappens during the actual click or activation (while button is being pressed).:focushappens when the element is focused (via keyboard, mouse click, or programmatically).
Important:
:focusremains active even after click until focus is lost.:hoverand:activeare temporary states.:focusimproves keyboard accessibility;:hoverdoes not work on touch-only devices.