Pseudo-Elements
Overview
Pseudo-element modifiers let you apply utility styles to specific sub-parts of an element. They wrap utility declarations in CSS pseudo-element selectors like ::before, ::after, and ::placeholder, generating variant utility classes that target these element fragments.
Why Use Pseudo-Element Modifiers?
Pseudo-element modifiers help you:
- Style generated content: Control the appearance of
::beforeand::afterpseudo-elements - Customize form placeholders: Style placeholder text without custom CSS
- Enhance text selection: Change the appearance of selected text
- Style list markers: Customize bullet points and list numbers
- Target file inputs: Style the file upload button in file input elements
useBeforeModifier
The useBeforeModifier() function creates a modifier that applies styles to the ::before pseudo-element. It automatically injects content: '' to ensure the pseudo-element is rendered.
import { styleframe } from "styleframe";
import { useBackgroundColorUtility, useWidthUtility, useHeightUtility } from "@styleframe/theme";
import { useBeforeModifier } from "@styleframe/theme";
const s = styleframe();
const before = useBeforeModifier(s);
useBackgroundColorUtility(s, {
primary: '#006cff',
}, [before]);
useWidthUtility(s, {
full: '100%',
}, [before]);
useHeightUtility(s, {
px: '1px',
}, [before]);
export default s;
._background-color\:primary { background-color: #006cff; }
._before\:background-color\:primary {
&::before { content: ''; background-color: #006cff; }
}
._before\:width\:full {
&::before { content: ''; width: 100%; }
}
._before\:height\:px {
&::before { content: ''; height: 1px; }
}
<!-- Add a decorative line before an element -->
<h2 class="_before:background-color:primary _before:width:full _before:height:px">
Section Title
</h2>
CSS Selector
| Modifier Name | CSS Selector | Auto-injected |
|---|---|---|
before | &::before | content: '' |
before and after modifiers automatically inject content: '' into the declarations. This ensures the pseudo-element is rendered without requiring a separate content utility.useAfterModifier
The useAfterModifier() function creates a modifier that applies styles to the ::after pseudo-element. It automatically injects content: ''.
import { styleframe } from "styleframe";
import { useBackgroundColorUtility } from "@styleframe/theme";
import { useAfterModifier } from "@styleframe/theme";
const s = styleframe();
const after = useAfterModifier(s);
useBackgroundColorUtility(s, {
overlay: 'rgba(0, 0, 0, 0.5)',
}, [after]);
export default s;
._background-color\:overlay { background-color: rgba(0, 0, 0, 0.5); }
._after\:background-color\:overlay {
&::after { content: ''; background-color: rgba(0, 0, 0, 0.5); }
}
<!-- Add an overlay after an element -->
<div class="_after:background-color:overlay">
Content with overlay
</div>
CSS Selector
| Modifier Name | CSS Selector | Auto-injected |
|---|---|---|
after | &::after | content: '' |
usePlaceholderModifier
The usePlaceholderModifier() function creates a modifier that applies styles to the ::placeholder pseudo-element of form inputs.
import { styleframe } from "styleframe";
import { useTextColorUtility, useOpacityUtility } from "@styleframe/theme";
import { usePlaceholderModifier } from "@styleframe/theme";
const s = styleframe();
const placeholder = usePlaceholderModifier(s);
useTextColorUtility(s, {
muted: '#6c757d',
}, [placeholder]);
useOpacityUtility(s, {
75: '0.75',
}, [placeholder]);
export default s;
._text-color\:muted { color: #6c757d; }
._placeholder\:text-color\:muted {
&::placeholder { color: #6c757d; }
}
._placeholder\:opacity\:75 {
&::placeholder { opacity: 0.75; }
}
<input
class="_placeholder:text-color:muted _placeholder:opacity:75"
placeholder="Enter your name..."
>
CSS Selector
| Modifier Name | CSS Selector |
|---|---|
placeholder | &::placeholder |
useSelectionModifier
The useSelectionModifier() function creates a modifier that applies styles to the text selection highlight.
import { styleframe } from "styleframe";
import { useBackgroundColorUtility, useTextColorUtility } from "@styleframe/theme";
import { useSelectionModifier } from "@styleframe/theme";
const s = styleframe();
const selection = useSelectionModifier(s);
useBackgroundColorUtility(s, {
primary: '#006cff',
}, [selection]);
useTextColorUtility(s, {
white: '#ffffff',
}, [selection]);
export default s;
._selection\:background-color\:primary {
&::selection { background-color: #006cff; }
}
._selection\:text-color\:white {
&::selection { color: #ffffff; }
}
<!-- Custom text selection colors -->
<p class="_selection:background-color:primary _selection:text-color:white">
Select this text to see custom highlight colors.
</p>
CSS Selector
| Modifier Name | CSS Selector |
|---|---|
selection | &::selection |
useFirstLetterModifier
The useFirstLetterModifier() function creates a modifier that applies styles to the first letter of a text block.
CSS Selector
| Modifier Name | CSS Selector |
|---|---|
first-letter | &::first-letter |
useFirstLineModifier
The useFirstLineModifier() function creates a modifier that applies styles to the first line of a text block.
CSS Selector
| Modifier Name | CSS Selector |
|---|---|
first-line | &::first-line |
useMarkerModifier
The useMarkerModifier() function creates a modifier that applies styles to list item markers (bullets, numbers).
import { styleframe } from "styleframe";
import { useTextColorUtility } from "@styleframe/theme";
import { useMarkerModifier } from "@styleframe/theme";
const s = styleframe();
const marker = useMarkerModifier(s);
useTextColorUtility(s, {
primary: '#006cff',
}, [marker]);
export default s;
._marker\:text-color\:primary {
&::marker { color: #006cff; }
}
<ul>
<li class="_marker:text-color:primary">Colored bullet item</li>
<li class="_marker:text-color:primary">Another item</li>
</ul>
CSS Selector
| Modifier Name | CSS Selector |
|---|---|
marker | &::marker |
useBackdropModifier
The useBackdropModifier() function creates a modifier that applies styles to the ::backdrop pseudo-element, used with <dialog> elements and fullscreen API.
CSS Selector
| Modifier Name | CSS Selector |
|---|---|
backdrop | &::backdrop |
useFileModifier
The useFileModifier() function creates a modifier that applies styles to the file upload button in <input type="file"> elements.
CSS Selector
| Modifier Name | CSS Selector |
|---|---|
file | &::file-selector-button |
usePseudoElementModifiers
The usePseudoElementModifiers() function registers all pseudo-element modifiers at once and returns them as a destructurable object.
import { styleframe } from "styleframe";
import { useTextColorUtility, useBackgroundColorUtility } from "@styleframe/theme";
import { usePseudoElementModifiers } from "@styleframe/theme";
const s = styleframe();
const { before, after, placeholder, selection } = usePseudoElementModifiers(s);
useTextColorUtility(s, {
muted: '#6c757d',
white: '#ffffff',
}, [placeholder, selection]);
useBackgroundColorUtility(s, {
primary: '#006cff',
}, [before, after, selection]);
export default s;
<input class="_placeholder:text-color:muted" placeholder="Styled placeholder">
<p class="_selection:background-color:primary _selection:text-color:white">
Custom selection highlight
</p>
Returned Modifiers
| Key | Modifier Name | CSS Selector | Notes |
|---|---|---|---|
before | before | &::before | Auto-injects content: '' |
after | after | &::after | Auto-injects content: '' |
placeholder | placeholder | &::placeholder | |
selection | selection | &::selection | |
firstLetter | first-letter | &::first-letter | |
firstLine | first-line | &::first-line | |
marker | marker | &::marker | |
backdrop | backdrop | &::backdrop | |
file | file | &::file-selector-button |
Examples
Drop Cap Typography
import { styleframe } from "styleframe";
import { useFontSizeUtility, useFontWeightUtility, useTextColorUtility } from "@styleframe/theme";
import { useFirstLetterModifier } from "@styleframe/theme";
const s = styleframe();
const firstLetter = useFirstLetterModifier(s);
useFontSizeUtility(s, {
'3xl': '3rem',
}, [firstLetter]);
useFontWeightUtility(s, {
bold: '700',
}, [firstLetter]);
useTextColorUtility(s, {
primary: '#006cff',
}, [firstLetter]);
export default s;
<p class="_first-letter:font-size:3xl _first-letter:font-weight:bold _first-letter:text-color:primary">
Once upon a time, there was a beautiful drop cap that started a paragraph.
</p>
Styled File Input
import { styleframe } from "styleframe";
import { useBackgroundColorUtility, useTextColorUtility } from "@styleframe/theme";
import { useFileModifier, useHoverModifier } from "@styleframe/theme";
const s = styleframe();
const file = useFileModifier(s);
const hover = useHoverModifier(s);
useBackgroundColorUtility(s, {
primary: '#006cff',
}, [file]);
useTextColorUtility(s, {
white: '#ffffff',
}, [file]);
export default s;
<input
type="file"
class="_file:background-color:primary _file:text-color:white"
>
Best Practices
- Use before/after for decorative content: Pseudo-elements are ideal for decorative elements that don't need to be in the DOM
- Style placeholders subtly: Use muted colors for placeholder text to distinguish it from actual input values
- Customize selection colors to match your brand: Use the
selectionmodifier for on-brand text highlighting - Remember content injection: The
beforeandaftermodifiers auto-injectcontent: ''; override this if you need specific content - Test marker styles: Not all CSS properties work with
::marker; it supports a limited set includingcolor,font-size, andcontent
FAQ
::before and ::after require the content property to render. Without it, the pseudo-element won't appear. The auto-injection of content: '' ensures the pseudo-element is always rendered, saving you from a common gotcha.content: '' is injected as a default. If you need different content, you can create a custom content utility and apply it with the before or after modifier, which will override the default empty string.::marker pseudo-element supports a limited set of properties: color, direction, font properties, content, unicode-bidi, animation and transition properties, and white-space. Most layout properties like display, width, and margin are not supported.::backdrop to style the area behind <dialog> elements and fullscreen elements. This is useful for creating modal overlays and customizing the fullscreen background.