The id attribute has existed since the early days of HTML to give a single element on the page a unique name. In CSS, it produces a powerful but temperamental selector, one that deserves to be handled with some caution.
Many developers discover the id selector before the class selector, simply because it looks like a proper name. The trouble is that this apparent simplicity hides a trap that complicates maintenance once a project grows.
Definition
The id selector targets the single HTML element whose id attribute matches the given name, written with a hash sign in the stylesheet. An element written as <header id="header"> is targeted by the selector #header.
Uniqueness of the id on the page
The HTML rule is strict: an id must appear only once per page. Two elements sharing the same id produce an invalid document, and browser behavior becomes unpredictable from there, especially for any script that looks up that id.
/* targets the single element with id="main-menu" */
#main-menu {
position: fixed;
top: 0;
}A very high specificity
In the Specificity calculation that settles which rule wins when two rules target the same element, an id carries far more weight than a class, an attribute, or a pseudo-class. In practice, a single id-based rule beats a rule that stacks ten classes together. That enormous weight makes the rule very hard to override elsewhere in the stylesheet, short of adding another id or reaching for !important, which only makes the problem worse for the rest of the project.
Why it is avoided in CSS
For these reasons, most teams reserve the id for purposes other than styling: a navigation anchor reached with href="#section", or a target that JavaScript looks up with document.getElementById(). The Class selector covers nearly every everyday styling need, with a lower and more predictable specificity, plus the advantage of being placeable on several elements at once.
| Aspect | id | class |
|---|---|---|
| Number of elements targeted | Only one | As many as needed |
| Weight in specificity | Very high | Moderate |
| Ease of overriding | Low | Good |
!important: it is to move that style off the id and onto a class instead.Migrating a legacy project full of ids
It is not unusual to inherit a project where styling relies heavily on ids, often because a previous developer looked for a quick fix without understanding the consequences on specificity. Rewriting the whole stylesheet at once is risky, but a gradual migration works well: each time a component gets touched, replace the id used for styling with an equivalent class, while leaving the id in place if it still serves as an anchor target or a script hook. That approach avoids breaking features that depend on the id for reasons other than styling, while gradually lowering the average specificity across the project. Over time, the stylesheet becomes predictable again, and every new rule can once more override previous ones without resorting to workarounds.
Frequently asked questions
Nothing technically forbids it, but as soon as a project grows, that style becomes the hardest one to change or reuse elsewhere, because of its specificity being too high compared with other rules.
No, a valid id must start with a letter. Numbers, dashes, and underscores are allowed afterward, but never as the first character of the name.
One of the two ids needs to be renamed so both become unique again, then any CSS selectors and scripts that relied on that id should be checked to make sure they still point to the right element afterward.