Target elements precisely — properties and values, attribute selectors, combinator selectors, pseudo-classes, and pseudo-elements.
A CSS declaration is a property: value pair. Values have types — keywords (red, bold), numbers with units (16px, 1.5em), functions like rgb() and calc(), or bare numbers (0, 1.6).
<!DOCTYPE html>
<html><head>
<style>
p {
color: steelblue; /* keyword */
font-size: 18px; /* number + unit */
line-height: 1.6; /* bare number (multiplier) */
background: rgb(240, 248, 255); /* function */
padding: 12px;
border-radius: 6px;
}
</style>
</head><body>
<p>Each line is one declaration: property + value.</p>
</body></html>Why: target elements by their attribute values, not just tags or classes. [attr] = presence; [attr="val"] = exact; [attr^="val"] = starts with; [attr$="val"] = ends with; [attr*="val"] = contains.
<!DOCTYPE html>
<html><head>
<style>
a[href^="https"] { color: green; }
a[href$=".pdf"] { color: tomato; }
input[type="text"] { border: 2px solid steelblue; padding: 6px; }
input[type="submit"] { background: steelblue; color: white; padding: 6px 14px; border: none; }
[disabled] { opacity: 0.4; cursor: not-allowed; }
</style>
</head><body style="font-family:sans-serif;padding:16px;display:flex;flex-direction:column;gap:12px">
<a href="https://example.com">Secure link (green)</a>
<a href="doc.pdf">PDF link (red)</a>
<input type="text" placeholder="Text input" />
<input type="submit" value="Submit" />
<input type="text" placeholder="Disabled" disabled />
</body></html>Select elements based on their DOM relationship. Space = any descendant. > = direct child only. + = immediately adjacent sibling. ~ = all following siblings.
<!DOCTYPE html>
<html><head>
<style>
.box em { color: tomato; } /* any em inside .box */
.box > p { font-weight: bold; } /* direct p children only */
h2 + p { color: steelblue; } /* p right after h2 */
h2 ~ p { border-left: 3px solid #ddd; padding-left: 8px; }
.box { border: 1px solid #ccc; padding: 12px; margin-bottom: 16px; }
</style>
</head><body style="font-family:sans-serif;padding:16px">
<div class="box">
<p>Direct child — bold</p>
<div><p>Nested — not a direct child</p></div>
<p>Another direct child <em>(red em)</em></p>
</div>
<h2>Heading</h2>
<p>Right after h2 — blue (adjacent sibling)</p>
<p>General sibling — border-left</p>
<p>General sibling — border-left</p>
</body></html>Style elements based on their state or DOM position without adding extra classes in HTML.
<!DOCTYPE html>
<html><head>
<style>
a:hover { color: tomato; text-decoration: none; }
input:focus { outline: 3px solid steelblue; }
li:first-child { font-weight: bold; }
li:last-child { color: gray; }
li:nth-child(2) { color: steelblue; }
p:not(.skip) { background: #f0f8ff; padding: 8px; border-radius: 4px; }
</style>
</head><body style="font-family:sans-serif;padding:16px;display:flex;flex-direction:column;gap:12px">
<a href="#">Hover me</a>
<input type="text" placeholder="Click to focus" />
<ul>
<li>First (bold)</li>
<li>Second (blue)</li>
<li>Third</li>
<li>Last (gray)</li>
</ul>
<p>Gets the blue background.</p>
<p class="skip">Skipped by :not(.skip) — no background.</p>
</body></html>Inject or style parts of an element without adding HTML. Always need content: "" to render ::before and ::after. Use :: (double colon) to distinguish from pseudo-classes.
<!DOCTYPE html>
<html><head>
<style>
.tip::before { content: "💡 "; }
.note::after { content: " — Note"; color: gray; font-style: italic; font-size: 0.85em; }
p::first-line { font-weight: bold; color: steelblue; }
input::placeholder { color: #bbb; font-style: italic; }
</style>
</head><body style="font-family:sans-serif;padding:16px;display:flex;flex-direction:column;gap:12px">
<p class="tip">Pseudo-elements inject content via CSS.</p>
<p class="note">This line gets a suffix</p>
<p>The first line of this paragraph is bold and blue. Keep reading — the rest is normal weight once you wrap to the next line.</p>
<input type="text" placeholder="Styled placeholder" />
</body></html>