CSS syntax is built from selectors and declarations. The selector chooses what to style, and each declaration says which property should receive which value.
Selectors are the first debugging skill every CSS learner needs. If the selector does not match the intended element, the declaration block can be perfectly written and still do nothing.
A CSS rule combines a selector with declarations; correctness depends on what actually matches and which competing declaration wins the cascade.
A CSS rule consists of a selector and a declaration block. The selector targets HTML elements; the declaration block contains one or more property-value pairs separated by semicolons.
Whitespace is mostly flexible in CSS, but punctuation matters. Missing braces, colons, or semicolons can cause later declarations to be ignored or parsed incorrectly.
selector {
property: value;
property: value;
}
| Selector | Syntax | Targets |
|---|---|---|
| Universal | * | Every element |
| Element (Type) | h1 | All <h1> elements |
| Class | .classname | Elements with that class |
| ID | #idname | Element with that ID (unique) |
| Attribute | [type="text"] | Elements with matching attribute |
| Descendant | div p | <p> inside any <div> |
| Child | div > p | Direct <p> children of <div> |
| Adjacent Sibling | h1 + p | <p> immediately after <h1> |
| General Sibling | h1 ~ p | All <p> siblings after <h1> |
| Group | h1, h2, h3 | All listed elements |
/* Universal selector - applies to ALL elements */
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
/* Element (type) selector */
h1 { color: #2c3e50; }
p { line-height: 1.6; }
/* Class selector - reusable */
.btn {
padding: 10px 20px;
border-radius: 4px;
cursor: pointer;
}
.btn-primary { background-color: #3498db; color: white; }
.btn-danger { background-color: #e74c3c; color: white; }
/* ID selector - unique per page */
#navbar {
background-color: #2c3e50;
position: sticky;
top: 0;
}
/* Attribute selectors */
input[type="text"] { border: 1px solid #ccc; }
input[type="password"] { border: 1px solid #e74c3c; }
a[href^="https"] { color: green; } /* href starts with https */
a[href$=".pdf"] { color: red; } /* href ends with .pdf */
a[href*="example"] { font-weight: bold; } /* href contains "example" */
/* Combinators */
div p { color: #555; } /* descendant: any p inside div */
div > p { color: #333; } /* child: direct p children of div */
h2 + p { font-size: 1.1em; } /* adjacent sibling: p right after h2 */
h2 ~ p { color: #666; } /* general sibling: all p after h2 */
/* Grouping */
h1, h2, h3, h4 {
font-family: 'Georgia', serif;
font-weight: bold;
}
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="selectors.css">
</head>
<body>
<nav id="navbar">Navigation</nav>
<h1>Page Title</h1>
<h2>Section</h2>
<p>This p is adjacent sibling of h2</p>
<p>This p is general sibling of h2</p>
<div>
<p>Direct child p of div</p>
<section>
<p>Descendant p (not direct child)</p>
</section>
</div>
<button class="btn tl-btn-primary">Save</button>
<button class="btn tl-btn-danger">Delete</button>
<input type="text" placeholder="Username">
<input type="password" placeholder="Password">
</body>
</html>
Pseudo-classes select elements based on their state or position. They use the : prefix.
/* State pseudo-classes */
a:link { color: blue; } /* unvisited link */
a:visited { color: purple; } /* visited link */
a:hover { color: red; text-decoration: underline; } /* mouse over */
a:active { color: orange; } /* being clicked */
input:focus { outline: 2px solid #3498db; } /* focused input */
input:disabled { opacity: 0.5; cursor: not-allowed; }
input:checked { accent-color: #3498db; }
/* Structural pseudo-classes */
li:first-child { font-weight: bold; } /* first list item */
li:last-child { color: gray; } /* last list item */
li:nth-child(2) { background: #f0f0f0; } /* 2nd item */
li:nth-child(odd) { background: #fff; } /* odd items */
li:nth-child(even) { background: #f9f9f9; } /* even items */
p:first-of-type { font-size: 1.2em; } /* first p in parent */
p:last-of-type { margin-bottom: 0; }
/* Negation */
li:not(:last-child) { border-bottom: 1px solid #eee; }
input:not([type="submit"]) { border: 1px solid #ccc; }
Pseudo-elements style a specific part of an element. They use the :: prefix (double colon).
/* ::before - insert content before element */
.required-field::before {
content: "* ";
color: red;
}
/* ::after - insert content after element */
.price::after {
content: " USD";
font-size: 0.8em;
color: gray;
}
/* ::first-letter - style first letter */
p::first-letter {
font-size: 2em;
font-weight: bold;
float: left;
margin-right: 4px;
color: #3498db;
}
/* ::first-line - style first line */
p::first-line {
font-weight: bold;
color: #2c3e50;
}
/* ::selection - style selected text */
::selection {
background-color: #3498db;
color: white;
}
/* ::placeholder - style input placeholder */
input::placeholder {
color: #aaa;
font-style: italic;
}
CSS syntax has two main parts: a selector and a declaration block. The selector chooses which elements receive the style, and the declarations describe what visual properties change. A small typo in either part can make the rule look ignored even when the browser is simply matching something different.
Selectors should be learned as matching patterns. A class selector matches class names, an id selector matches one id, an attribute selector matches an element with a specific attribute, and pseudo selectors match states or generated parts. Once selector matching is clear, specificity and cascade behavior become much easier.
.card[data-status="active"] .card-title {
color: #1d4ed8;
font-weight: 700;
}
.card:hover {
border-color: #60a5fa;
}
A space means descendant. For example, .card p targets any p inside .card.
.box targets a class. #box targets an ID, which should be unique on the page.
Check whether the selector matches, whether another rule overrides it, and whether the syntax is valid.
Explore 500+ free tutorials across 20+ languages and frameworks.