These two pseudo-elements each "generate" a virtual child element before and after the content of the selected element, letting us add decorative content with pure CSS without modifying the HTML structure. They are the most frequently used pair in the pseudo-element family.
The content Property
Without the content property, ::before / ::after will not be rendered — even an empty string must be declared explicitly.
Because a pseudo-element is essentially a box that can be positioned and sized, combining position and border lets you draw many shapes that need no extra images.
counter-reset / counter-increment together with content: counter(name) enable automatic numbering that can span multiple levels of lists:
ol { counter-reset: step; list-style: none; }
ol li { counter-increment: step; }
ol li::before {
content: counter(step) ".";
color: #8a5a2e;
margin-right: 6px;
}
Common Pitfalls
::before / ::after do not work on replaced elements such as img and input, because they have no "inside" into which content can be inserted.
Generated content is inline by default; set display explicitly when needed.
Pseudo-element content is not well supported by assistive technologies beyond screen readers, so important information should not rely solely on pseudo-elements.