css
CSS Pseudo-classes and Pseudo-elements
Pseudo-classes and pseudo-elements allow you to style elements based on their state or position, and to style specific parts of elements.
Pseudo-classes
Pseudo-classes select elements based on their state or position. They use a single colon :.
Link and User Action Pseudo-classes
css
/* Unvisited link */
a:link {
color: blue;
}
/* Visited link */
a:visited {
color: purple;
}
/* Mouse hover */
a:hover {
color: red;
text-decoration: underline;
}
/* Active (being clicked) */
a:active {
color: orange;
}
/* Keyboard focus */
input:focus {
border-color: blue;
outline: 2px solid lightblue;
}
html
<style>
.demo-link {
color: blue;
text-decoration: none;
padding: 10px;
display: inline-block;
}
.demo-link:hover {
color: red;
background: #f0f0f0;
}
.demo-input:focus {
border: 2px solid blue;
outline: none;
}
</style>
<a href="#" class="demo-link">Hover over this link</a>
<br><br>
<input type="text" class="demo-input" placeholder="Click to focus">
Preview
Structural Pseudo-classes
css
/* First child */
li:first-child {
font-weight: bold;
}
/* Last child */
li:last-child {
border-bottom: none;
}
/* Nth child */
li:nth-child(2) {
color: blue;
}
/* Odd rows */
tr:nth-child(odd) {
background: #f0f0f0;
}
/* Even rows */
tr:nth-child(even) {
background: white;
}
/* Every 3rd element */
li:nth-child(3n) {
color: red;
}
html
<style>
.demo-list li {
padding: 8px;
border-bottom: 1px solid #ddd;
}
.demo-list li:first-child {
font-weight: bold;
background: #e3f2fd;
}
.demo-list li:last-child {
border-bottom: none;
background: #fff3e0;
}
.demo-list li:nth-child(even) {
background: #f5f5f5;
}
</style>
<ul class="demo-list">
<li>First item (bold, blue bg)</li>
<li>Second item (gray bg)</li>
<li>Third item</li>
<li>Fourth item (gray bg)</li>
<li>Last item (orange bg)</li>
</ul>
Preview
Form Pseudo-classes
css
/* Enabled input */
input:enabled {
background: white;
}
/* Disabled input */
input:disabled {
background: #f0f0f0;
cursor: not-allowed;
}
/* Checked checkbox/radio */
input:checked {
accent-color: green;
}
/* Required field */
input:required {
border-left: 3px solid red;
}
/* Optional field */
input:optional {
border-left: 3px solid gray;
}
/* Valid input */
input:valid {
border-color: green;
}
/* Invalid input */
input:invalid {
border-color: red;
}
html
<style>
.form-demo input {
display: block;
margin: 10px 0;
padding: 8px;
border: 2px solid #ddd;
}
.form-demo input:focus {
border-color: blue;
outline: none;
}
.form-demo input:disabled {
background: #f0f0f0;
cursor: not-allowed;
}
.form-demo input:valid {
border-color: green;
}
.form-demo input:invalid {
border-color: red;
}
</style>
<form class="form-demo">
<input type="text" placeholder="Normal input">
<input type="email" placeholder="Email (try invalid)" required>
<input type="text" value="Disabled" disabled>
</form>
Preview
Other Useful Pseudo-classes
css
/* Empty element */
p:empty {
display: none;
}
/* Not selector */
li:not(.special) {
color: gray;
}
/* Only child */
p:only-child {
font-weight: bold;
}
/* Target (from URL hash) */
:target {
background: yellow;
}
Pseudo-elements
Pseudo-elements style specific parts of elements. They use double colons ::.
::before and ::after
Insert content before or after an element:
css
.quote::before {
content: '"';
font-size: 2em;
color: gray;
}
.quote::after {
content: '"';
font-size: 2em;
color: gray;
}
/* Decorative elements */
.badge::after {
content: 'NEW';
background: red;
color: white;
padding: 2px 6px;
margin-left: 10px;
border-radius: 3px;
font-size: 0.8em;
}
html
<style>
.quote {
font-style: italic;
padding: 20px;
background: #f5f5f5;
}
.quote::before {
content: '"';
font-size: 3em;
color: #3498db;
line-height: 0;
margin-right: 5px;
}
.quote::after {
content: '"';
font-size: 3em;
color: #3498db;
line-height: 0;
margin-left: 5px;
}
.badge::after {
content: 'NEW';
background: #e74c3c;
color: white;
padding: 3px 8px;
margin-left: 10px;
border-radius: 3px;
font-size: 0.7em;
font-weight: bold;
}
</style>
<p class="quote">This is a quoted text with decorative quotes</p>
<p class="badge">Product Name</p>
Preview
::first-letter and ::first-line
css
/* Style first letter */
p::first-letter {
font-size: 3em;
font-weight: bold;
color: #3498db;
float: left;
margin-right: 5px;
}
/* Style first line */
p::first-line {
font-weight: bold;
color: #2c3e50;
}
html
<style>
.drop-cap::first-letter {
font-size: 3em;
font-weight: bold;
color: #3498db;
float: left;
line-height: 0.8;
margin-right: 8px;
margin-top: 5px;
}
.first-line::first-line {
font-weight: bold;
color: #e74c3c;
}
</style>
<p class="drop-cap">This paragraph has a drop cap. The first letter is styled differently to create a magazine-style effect.</p>
<p class="first-line">This paragraph has its first line styled in bold red. The rest of the text remains normal.</p>
Preview
::selection
Style selected text:
css
::selection {
background: #3498db;
color: white;
}
html
<style>
.selectable::selection {
background: #3498db;
color: white;
}
</style>
<p class="selectable">Try selecting this text to see the custom selection color!</p>
Preview
::placeholder
Style input placeholders:
css
input::placeholder {
color: #999;
font-style: italic;
}
html
<style>
.styled-input::placeholder {
color: #3498db;
font-style: italic;
opacity: 0.7;
}
</style>
<input type="text" class="styled-input" placeholder="Styled placeholder text">
Preview
Complete Example
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Pseudo-classes & Pseudo-elements</title>
<style>
body {
font-family: Arial, sans-serif;
padding: 20px;
max-width: 800px;
margin: 0 auto;
}
/* Navigation with hover effects */
.nav {
list-style: none;
padding: 0;
background: #2c3e50;
display: flex;
}
.nav li {
flex: 1;
}
.nav a {
display: block;
padding: 15px;
color: white;
text-decoration: none;
text-align: center;
}
.nav a:hover {
background: #34495e;
}
.nav a:active {
background: #1a252f;
}
/* Striped table */
table {
width: 100%;
border-collapse: collapse;
margin: 20px 0;
}
tr:nth-child(odd) {
background: #f8f9fa;
}
tr:hover {
background: #e3f2fd;
}
td {
padding: 10px;
border-bottom: 1px solid #ddd;
}
/* Form styling */
.form-group {
margin: 15px 0;
}
input[type="text"],
input[type="email"] {
width: 100%;
padding: 10px;
border: 2px solid #ddd;
border-radius: 4px;
}
input:focus {
border-color: #3498db;
outline: none;
}
input:valid {
border-color: #27ae60;
}
input:invalid:not(:placeholder-shown) {
border-color: #e74c3c;
}
/* Pseudo-elements */
.article::first-letter {
font-size: 2.5em;
font-weight: bold;
color: #3498db;
float: left;
line-height: 0.8;
margin-right: 8px;
margin-top: 5px;
}
.badge::after {
content: 'Popular';
background: #e74c3c;
color: white;
padding: 3px 8px;
margin-left: 10px;
border-radius: 3px;
font-size: 0.7em;
font-weight: bold;
}
::selection {
background: #3498db;
color: white;
}
</style>
</head>
<body>
<h1>Pseudo-classes & Pseudo-elements Demo</h1>
<h2>Navigation (Hover Effects)</h2>
<ul class="nav">
<li><a href="#">Home</a></li>
<li><a href="#">About</a></li>
<li><a href="#">Services</a></li>
<li><a href="#">Contact</a></li>
</ul>
<h2 class="badge">Striped Table</h2>
<table>
<tr>
<td>Row 1</td>
<td>Data</td>
</tr>
<tr>
<td>Row 2</td>
<td>Data</td>
</tr>
<tr>
<td>Row 3</td>
<td>Data</td>
</tr>
<tr>
<td>Row 4</td>
<td>Data</td>
</tr>
</table>
<h2>Form Validation</h2>
<div class="form-group">
<input type="email" placeholder="Enter your email" required>
</div>
<h2>Drop Cap Article</h2>
<p class="article">Lorem ipsum dolor sit amet, consectetur adipiscing elit. This paragraph demonstrates a drop cap effect using the ::first-letter pseudo-element. Try selecting text to see custom selection colors!</p>
</body>
</html>
Preview