In CSS, why do width, padding and border have no effect when set on ::selection or ::marker?
answer
- not every pseudo-element is a box
- some only repaint what layout already placed
- a live drag cannot trigger reflow
- each spec names its own property list
- drop caps are the exception that proves it
basics
~20 sBecause each pseudo-element specification defines its own restricted property set. ::selection only paints over existing text, so it accepts colour, background-color, text-decoration and text-shadow; ::marker accepts font properties, colour and content. Neither generates a box you can size.
solid answer
~50 sNot every pseudo-element is a box you can lay out. `::before` and `::after` generate real boxes, so the full box model applies to them. `::selection` is a *highlight* pseudo-element: it repaints characters that are already laid out, so the spec restricts it to `color`, `background-color`, `text-decoration` and its related properties, `text-shadow`, and the stroke/fill properties — sizing a highlight would mean re-laying-out text as you drag a selection, which is not a thing. `::marker` is likewise limited to font properties, `color`, `content` and `white-space`, plus animation and transition properties; to change a marker's spacing you adjust the list item instead. `::first-letter` is the outlier that *does* accept box properties — margin, padding, border and float — which is why drop caps are built with it. The rule to carry away is that the accepted property set is per-pseudo-element and comes from its own spec, not from CSS in general.
code
css · 16 lines::selection {
color: #fff;
background-color: #0066cc;
}
li::marker {
color: crimson;
font-size: 1.2em;
}
p::first-letter {
float: left;
font-size: 3em;
line-height: 0.8;
padding-right: 6px;
}go deeper
Know that ::selection and ::marker only take a small set of text and colour properties, and that sizing them does nothing. Reach for ::before if you need a real box.
Explain the categories: generated-content pseudo-elements create boxes, highlight pseudo-elements only repaint text that layout already positioned, and each spec defines its own accepted property list.
Recognise the silent-ignore signature when debugging — the declaration shows in computed styles but nothing renders differently — and route the fix to the owning element rather than fighting the pseudo-element.
Keep the design system from depending on marker or highlight styling that engines implement unevenly; specify which parts are decorative-only so a component does not quietly lose its intended look on one browser.
## Three different kinds of pseudo-element It is tempting to treat pseudo-elements as one uniform feature, but they fall into categories that behave very differently, and the property restrictions follow directly from the category. **Generated-content pseudo-elements** — `::before`, `::after`. These create a genuine box in the box tree. The whole box model applies: `display`, `width`, `padding`, `border`, `margin`, positioning, transforms. **Highlight pseudo-elements** — `::selection` is the familiar one; the same family includes the spell-check and search-match highlights. These do not create boxes at all. They repaint characters that the layout algorithm has already positioned. Layout has finished; only painting is left. **Tree-abstiding / structural pseudo-elements** — `::first-line`, `::first-letter`, `::marker`, `::placeholder`, `::backdrop`. Each addresses a specific rendered part with its own rules about what may change. ## `::selection` and why sizing is meaningless A text selection changes continuously as the user drags. If `padding` on `::selection` were honoured, every mouse move would reflow the paragraph under the cursor. The specification therefore limits the property set to painting concerns: ```css ::selection { color: #fff; /* applies */ background-color: #06c; /* applies */ text-decoration: underline; /* applies */ text-shadow: none; /* applies */ padding: 4px; /* ignored */ border: 1px solid red; /* ignored */ display: block; /* ignored */ } ``` One extra detail catches people out: `background-image` is not honoured on `::selection`, only `background-color`. And because the highlight paints over the text, a `background-color` with alpha composites against whatever is underneath rather than replacing it. ## `::marker` and the list-item bullet `::marker` targets the bullet or number box of a list item (or of any element with `display: list-item`). Its accepted properties are the font properties, `color`, `content`, `white-space`, plus animation and transition properties: ```css li::marker { color: crimson; /* applies */ font-size: 1.4em; /* applies */ content: "– "; /* applies */ margin-right: 12px; /* ignored */ background: yellow; /* ignored */ } ``` So how do you move the bullet? Not through `::marker`. You use the list item's own properties — `list-style-position`, padding on the list, or the modern approach of `display: list-item` on a custom element with `list-style-type` set. The restriction exists because the marker's placement is the list layout algorithm's business, not the marker's. ## `::placeholder` and `::first-line` `::placeholder` styles the placeholder text a form control shows while empty. It accepts the properties that apply to `::first-line` — essentially the text and inline-painting properties: `color`, the font properties, `background`, `letter-spacing`, `word-spacing`, `text-decoration`, `text-transform`, `line-height`, `opacity`. Box properties are not among them, because the placeholder is text rendered inside a box that already exists. `::first-line` has the same character: it addresses whatever characters happen to land on the first line, and that set changes when the container is resized. The specification calls this the *fictional tag sequence* — the browser behaves as if a tag were wrapped around the first line, but the boundary is recomputed on every layout. Since the line's extent is a layout output, you cannot feed box properties back into it. ## `::first-letter` is the exception `::first-letter` genuinely does accept box properties: `margin`, `padding`, `border`, `background`, `float`, plus `font-size`, `line-height`, `text-transform` and `vertical-align`. That is what makes drop caps possible: ```css p::first-letter { float: left; font-size: 3.2em; line-height: 0.8; padding-right: 6px; margin-top: 4px; } ``` The difference is that a first letter is a single, stable inline box, so giving it dimensions is a well-defined operation in a way that sizing a live selection range is not. ## The practical takeaway When a declaration on a pseudo-element is ignored, do not reach for `!important` or start hunting for a competing rule. Ask instead which category the pseudo-element belongs to. If it repaints existing text, only painting properties will do anything; if it generates a box, the box model is fully available; if it is a marker or a placeholder, look up the specific list. Devtools helps here: computed styles will show the declaration as present but the rendering will not change, which is the signature of a property that is simply not in the accepted set.
- How do you increase the gap between a list marker and its text if ::marker ignores margin?Through the list item, not the marker. Set `list-style-position: outside` and add `padding-inline-start` to the list, or drop the native marker with `list-style: none` and rebuild it as a `::before` box, which does accept margins. The marker's placement belongs to the list layout algorithm, so the lever is on the item.
- Why does ::first-line accept fewer properties than ::first-letter?Because the first line's extent is a layout output, not a fixed unit — it is recomputed on every resize, which the spec models as a fictional tag sequence. Feeding box properties back into something layout just produced would be circular. A first letter is a single stable inline box, so giving it padding, border or float is well defined, which is exactly how drop caps are built.
saying these in an interview costs you the question
- Assumes the full box model applies to every pseudo-element
- Reaches for !important when a declaration is ignored
- Tries to space a bullet with margin on ::marker
- Expects background-image to work on ::selection
- Thinks ::first-line can take padding like ::first-letter