A decorative mark needs to appear beside a label, but adding another HTML element for every instance makes the markup harder to maintain. CSS can generate content after an element’s existing children, while a matching before pseudo-element can add a mark at the start of an HTML element. Both are useful for presentation; essential information still belongs in the document.
HTML Before After: Start With a Working Example
The ::before and ::after pseudo-elements generate boxes as the first and last children of the selected element. They are not new DOM nodes. The content property supplies their generated content; content: "" creates an empty box that can be styled.
<p class="note">Changes saved</p>
.note::before {
content: "";
display: inline-block;
width: 0.5rem;
height: 0.5rem;
margin-right: 0.5rem;
border-radius: 50%;
background: seagreen;
}
.note::after {
content: " •";
color: seagreen;
}
The first rule adds a colored dot before the text; the second adds a bullet after it. Both marks are decorative. The status itself remains in the paragraph. This HTML before after example lets you remove the stylesheet without losing the message.
The generated boxes are inline by default. The empty ::before box needs inline-block here so its width and height take effect. The ::after box contains a string, so it can stay inline with the text. CSS-generated content after the paragraph’s text follows its existing children. Use the double-colon spelling to distinguish pseudo-elements from pseudo-classes such as :hover.
Position a Decoration
To place CSS content after a heading without shifting its text, position an empty pseudo-element relative to the heading:
<h2 class="section-title">Recent work</h2>
.section-title {
position: relative;
padding-bottom: 0.5rem;
}
.section-title::after {
content: "";
position: absolute;
left: 0;
bottom: 0;
width: 3rem;
height: 2px;
background: currentColor;
}
The heading establishes the positioning reference; the generated line sits at its lower edge. The content of the CSS ::after pseudo-element is empty, but its box remains visible through the background. currentColor uses the heading’s text color. The padding reserves space for the line, which is removed from normal flow by absolute positioning. Test at larger text sizes and narrow widths to make sure it does not obscure adjacent content.
This approach is appropriate for a visual accent. It is less useful if the line needs its own interactive behavior: a pseudo-element is not an independent DOM control, so use an actual element for a button, link, or other interactive component.
Keep Meaning in HTML
A stylesheet can add content after a label in CSS, but generated text is a poor place for an error message, required-field notice, or instruction. It is not part of the DOM, and assistive technology support can vary. It also disappears when CSS is unavailable. Put meaningful words in HTML and use a pseudo-element only for decoration. MDN’s content reference explains the accessibility considerations.
For example, render “Required” as part of the field’s actual label or related text, and use CSS to add a decorative mark if desired. A visible symbol should not be the only way to understand the requirement. Generated content before or after an HTML element should complement the document, not carry information the document otherwise lacks.
If Nothing Appears
The most likely cause is a missing or overridden content declaration. In developer tools, inspect the selected element and its pseudo-element rules: if content is absent or resolves to none or normal, the box is not rendered. Add content: "" for a decorative shape or a quoted string for visible text. If it still does not appear, check the selector, dimensions, color, and positioning; replaced elements such as <img> do not support these pseudo-elements in the usual way, so apply the rule to a wrapper instead.
