Control how elements are targeted by CSS and JavaScript with id and class. Store custom data with data-* attributes and apply quick styles inline.
Why unique: two elements with the same id break CSS specificity, confuse getElementById (it returns only one), and break anchor links. When to use: when you need to target one specific element — JavaScript interaction, anchor links, or a high-specificity CSS override.
<!-- Unique per page — used for CSS, JS, and anchor links -->
<h2 id="getting-started">Getting Started</h2>
<!-- Jump to it with an anchor link -->
<a href="#getting-started">Skip to Getting Started</a>
<!-- Target in CSS -->
<style>
#getting-started { color: navy; }
</style>
<!-- Target in JS -->
<script>
const el = document.getElementById('getting-started')
</script>Why: class is the primary hook for CSS and JavaScript — unlike id, many elements can share the same class. When: use it for any styling or behaviour you want to apply to more than one element. An element can hold multiple classes by separating them with spaces.
<!-- Multiple classes separated by spaces -->
<button class="btn btn-primary btn-large">Submit</button>
<!-- Shared styling across multiple elements -->
<p class="highlight">First highlight.</p>
<p class="highlight">Second highlight.</p>
<style>
.highlight { background: yellow; }
</style>Why: before data-*, developers invented fake attributes like user-id="42" which invalidated HTML. data-* is the official way to embed custom data in markup. Where: readable in JavaScript via element.dataset — the hyphenated name becomes camelCase automatically (data-user-id → dataset.userId).
<!-- Store custom data on any element -->
<button data-user-id="42" data-action="delete">
Delete User
</button>
<div data-theme="dark" data-version="2">...</div>
<script>
const btn = document.querySelector('button')
console.log(btn.dataset.userId) // "42"
console.log(btn.dataset.action) // "delete"
</script>Why avoid it: inline styles have the highest CSS specificity, making them nearly impossible to override without !important. When it is acceptable: dynamic values set by JavaScript (e.g. element.style.width = x + 'px'), or generated content where adding a class is impractical.
<!-- Inline CSS — use sparingly -->
<p style="color: red; font-size: 18px;">
This text is red.
</p>
<div style="display: flex; gap: 16px; padding: 12px;">
<span>Item 1</span>
<span>Item 2</span>
</div>