Pseudo-elements let you style specific parts of elements without extra markup. Here's how to use them.
Basic Syntax#
1/* Double colon syntax (CSS3) */
2.element::before {
3 content: '';
4}
5
6.element::after {
7 content: '';
8}
9
10/* Single colon (CSS2, still works) */
11.element:before {
12 content: '';
13}
14
15/* Common pseudo-elements */
16::before /* Insert before element content */
17::after /* Insert after element content */
18::first-line /* First line of text */
19::first-letter /* First letter of text */
20::selection /* User-selected text */
21::placeholder /* Input placeholder text */
22::marker /* List item markers */::before and ::after Basics#
1/* Content is required */
2.quote::before {
3 content: '"';
4}
5
6.quote::after {
7 content: '"';
8}
9
10/* Empty content for decorative elements */
11.decorated::before {
12 content: '';
13 display: block;
14 width: 50px;
15 height: 2px;
16 background: #007bff;
17}
18
19/* Using attr() */
20.tooltip::after {
21 content: attr(data-tooltip);
22 position: absolute;
23 /* ... positioning styles */
24}
25
26/* Counters */
27.numbered::before {
28 counter-increment: section;
29 content: counter(section) '. ';
30}Decorative Elements#
1/* Underline effect */
2.fancy-underline {
3 position: relative;
4 display: inline-block;
5}
6
7.fancy-underline::after {
8 content: '';
9 position: absolute;
10 left: 0;
11 bottom: -2px;
12 width: 100%;
13 height: 2px;
14 background: linear-gradient(90deg, #007bff, #00d4ff);
15 transform: scaleX(0);
16 transition: transform 0.3s ease;
17}
18
19.fancy-underline:hover::after {
20 transform: scaleX(1);
21}
22
23/* Corner decorations */
24.corner-box {
25 position: relative;
26 padding: 2rem;
27 border: 2px solid #333;
28}
29
30.corner-box::before,
31.corner-box::after {
32 content: '';
33 position: absolute;
34 width: 20px;
35 height: 20px;
36 border: 2px solid #007bff;
37}
38
39.corner-box::before {
40 top: -5px;
41 left: -5px;
42 border-right: none;
43 border-bottom: none;
44}
45
46.corner-box::after {
47 bottom: -5px;
48 right: -5px;
49 border-left: none;
50 border-top: none;
51}Shapes and Icons#
1/* Triangle */
2.arrow-right::after {
3 content: '';
4 display: inline-block;
5 width: 0;
6 height: 0;
7 border-top: 5px solid transparent;
8 border-bottom: 5px solid transparent;
9 border-left: 8px solid currentColor;
10 margin-left: 0.5rem;
11}
12
13/* Circle bullet */
14.custom-bullet {
15 list-style: none;
16}
17
18.custom-bullet li {
19 position: relative;
20 padding-left: 1.5rem;
21}
22
23.custom-bullet li::before {
24 content: '';
25 position: absolute;
26 left: 0;
27 top: 0.5em;
28 width: 8px;
29 height: 8px;
30 background: #007bff;
31 border-radius: 50%;
32}
33
34/* Checkbox icon */
35.custom-checkbox::before {
36 content: '';
37 display: inline-block;
38 width: 18px;
39 height: 18px;
40 border: 2px solid #666;
41 border-radius: 3px;
42 margin-right: 0.5rem;
43 vertical-align: middle;
44}
45
46.custom-checkbox.checked::before {
47 background: #007bff;
48 border-color: #007bff;
49}
50
51.custom-checkbox.checked::after {
52 content: '✓';
53 position: absolute;
54 color: white;
55 font-size: 12px;
56}Overlays and Effects#
1/* Image overlay */
2.image-card {
3 position: relative;
4 overflow: hidden;
5}
6
7.image-card::before {
8 content: '';
9 position: absolute;
10 inset: 0;
11 background: linear-gradient(
12 to top,
13 rgba(0, 0, 0, 0.8),
14 transparent
15 );
16 opacity: 0;
17 transition: opacity 0.3s ease;
18}
19
20.image-card:hover::before {
21 opacity: 1;
22}
23
24/* Shine effect */
25.shine-button {
26 position: relative;
27 overflow: hidden;
28}
29
30.shine-button::before {
31 content: '';
32 position: absolute;
33 top: 0;
34 left: -100%;
35 width: 50%;
36 height: 100%;
37 background: linear-gradient(
38 90deg,
39 transparent,
40 rgba(255, 255, 255, 0.3),
41 transparent
42 );
43 transform: skewX(-25deg);
44 transition: left 0.5s ease;
45}
46
47.shine-button:hover::before {
48 left: 150%;
49}
50
51/* Glassmorphism border */
52.glass-card {
53 position: relative;
54 background: rgba(255, 255, 255, 0.1);
55 backdrop-filter: blur(10px);
56}
57
58.glass-card::before {
59 content: '';
60 position: absolute;
61 inset: 0;
62 border-radius: inherit;
63 padding: 1px;
64 background: linear-gradient(
65 135deg,
66 rgba(255, 255, 255, 0.4),
67 transparent
68 );
69 mask: linear-gradient(#fff 0 0) content-box,
70 linear-gradient(#fff 0 0);
71 mask-composite: exclude;
72 pointer-events: none;
73}Text Effects#
1/* Drop cap */
2.article p:first-of-type::first-letter {
3 float: left;
4 font-size: 4rem;
5 line-height: 1;
6 font-weight: bold;
7 margin-right: 0.5rem;
8 color: #007bff;
9}
10
11/* First line styling */
12.article p::first-line {
13 font-weight: bold;
14 font-variant: small-caps;
15}
16
17/* Custom selection */
18::selection {
19 background: #007bff;
20 color: white;
21}
22
23.dark-theme ::selection {
24 background: #ffd700;
25 color: #333;
26}
27
28/* Placeholder styling */
29input::placeholder {
30 color: #999;
31 font-style: italic;
32}
33
34input:focus::placeholder {
35 opacity: 0.5;
36}Labels and Badges#
1/* Required field indicator */
2.required::after {
3 content: '*';
4 color: red;
5 margin-left: 0.25rem;
6}
7
8/* External link indicator */
9a[href^="http"]::after {
10 content: ' ↗';
11 font-size: 0.8em;
12}
13
14/* New badge */
15.new-item::before {
16 content: 'NEW';
17 display: inline-block;
18 padding: 0.125rem 0.5rem;
19 font-size: 0.625rem;
20 font-weight: bold;
21 background: #ff4444;
22 color: white;
23 border-radius: 3px;
24 margin-right: 0.5rem;
25 vertical-align: middle;
26}
27
28/* Price with currency */
29.price::before {
30 content: '$';
31}
32
33/* File type indicator */
34a[href$=".pdf"]::before {
35 content: '📄 ';
36}
37
38a[href$=".zip"]::before {
39 content: '📦 ';
40}Clearfix and Layout#
1/* Classic clearfix */
2.clearfix::after {
3 content: '';
4 display: table;
5 clear: both;
6}
7
8/* Divider line */
9.divider {
10 display: flex;
11 align-items: center;
12 text-align: center;
13}
14
15.divider::before,
16.divider::after {
17 content: '';
18 flex: 1;
19 height: 1px;
20 background: #ddd;
21}
22
23.divider::before {
24 margin-right: 1rem;
25}
26
27.divider::after {
28 margin-left: 1rem;
29}
30
31/* Section separator */
32.section::after {
33 content: '';
34 display: block;
35 width: 60px;
36 height: 3px;
37 background: #007bff;
38 margin: 2rem auto;
39}Custom List Markers#
1/* Custom bullet with ::marker */
2ul.custom::marker {
3 color: #007bff;
4 font-size: 1.2em;
5}
6
7/* Numbered list styling */
8ol.fancy {
9 list-style: none;
10 counter-reset: list-counter;
11}
12
13ol.fancy li {
14 counter-increment: list-counter;
15 position: relative;
16 padding-left: 3rem;
17 margin-bottom: 1rem;
18}
19
20ol.fancy li::before {
21 content: counter(list-counter);
22 position: absolute;
23 left: 0;
24 width: 2rem;
25 height: 2rem;
26 background: #007bff;
27 color: white;
28 border-radius: 50%;
29 display: flex;
30 align-items: center;
31 justify-content: center;
32 font-weight: bold;
33}Form Enhancements#
1/* Styled radio button */
2.radio-custom {
3 display: flex;
4 align-items: center;
5 gap: 0.5rem;
6 cursor: pointer;
7}
8
9.radio-custom input {
10 position: absolute;
11 opacity: 0;
12}
13
14.radio-custom::before {
15 content: '';
16 width: 20px;
17 height: 20px;
18 border: 2px solid #666;
19 border-radius: 50%;
20 transition: all 0.2s;
21}
22
23.radio-custom:has(input:checked)::before {
24 border-color: #007bff;
25 background: #007bff;
26 box-shadow: inset 0 0 0 4px white;
27}
28
29/* Focus ring */
30.focus-ring:focus-visible::before {
31 content: '';
32 position: absolute;
33 inset: -4px;
34 border: 2px solid #007bff;
35 border-radius: inherit;
36 pointer-events: none;
37}Best Practices#
Usage:
✓ Use for decorative elements
✓ Always include content property
✓ Use position: relative on parent
✓ Prefer double colon syntax
Performance:
✓ Keep pseudo-elements simple
✓ Use transform for animations
✓ Avoid excessive nesting
✓ Test on mobile devices
Accessibility:
✓ Don't use for important content
✓ Decorative content only
✓ Screen readers may ignore
✓ Ensure color contrast
Avoid:
✗ Critical content in ::before/::after
✗ Overusing for everything
✗ Complex layouts with pseudo-elements
✗ Replacing semantic HTML
Conclusion#
CSS pseudo-elements enable powerful styling without additional markup. Use ::before and ::after for decorations, icons, and effects. Remember that content property is required, and pseudo-element content is not accessible to screen readers. Use them for visual enhancements, not critical content.