HTML Elements, Forms & Inputs, Semantic HTML, CSS Selectors, Box Model, Flexbox, Grid, Animations, Media Queries — web fundamentals.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Page description for SEO">
<meta name="theme-color" content="#6366f1">
<title>Page Title</title>
<!-- Preload critical resources -->
<link rel="preload" href="font.woff2" as="font" crossorigin>
<link rel="preconnect" href="https://fonts.googleapis.com">
<!-- Favicon -->
<link rel="icon" href="/favicon.ico" sizes="48x48">
<link rel="icon" href="/icon.svg" type="image/svg+xml">
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
</head>
<body>
<!-- Content -->
<script src="app.js" defer></script>
</body>
</html><!-- ── Text Elements ── -->
<h1>Heading 1</h1> <!-- 6 levels: h1-h6 -->
<p>Paragraph text</p>
<strong>Bold (important)</strong>
<em>Italic (emphasis)</em>
<mark>Highlighted text</mark>
<small>Small text</small>
<del>Deleted text</del>
<ins>Inserted text</ins>
<sub>Subscript</sub> <sup>Superscript</sup>
<abbr title="HyperText Markup Language">HTML</abbr>
<code>Inline code</code>
<kbd>Ctrl</kbd> + <kbd>C</kbd>
<blockquote cite="url">
<p>Block quotation</p>
<cite>Source Title</cite>
</blockquote>
<!-- ── Links & Media ── -->
<a href="https://example.com" target="_blank" rel="noopener noreferrer">
External link
</a>
<a href="#section-id">Jump to section</a>
<a href="mailto:hi@example.com">Email link</a>
<a href="tel:+1234567890">Phone link</a>
<img src="photo.jpg" alt="Description" width="800" height="600" loading="lazy">
<video src="video.mp4" controls preload="metadata" poster="thumb.jpg">
<track kind="captions" src="captions.vtt" srclang="en" label="English">
</video>
<audio src="audio.mp3" controls preload="none"></audio>
<figure>
<img src="chart.png" alt="Sales chart">
<figcaption>Figure 1: Q4 Sales</figcaption>
</figure><!-- ── Lists ── -->
<ul> <!-- Unordered -->
<li>Item 1</li>
<li>Item 2
<ul> <!-- Nested list -->
<li>Sub-item</li>
</ul>
</li>
</ul>
<ol> <!-- Ordered -->
<li>First</li>
<li>Second</li>
<li>Third</li>
</ol>
<dl> <!-- Description list -->
<dt>Term</dt>
<dd>Definition of term</dd>
</dl>
<!-- ── Table ── -->
<table>
<caption>Monthly Sales</caption>
<thead>
<tr>
<th scope="col">Month</th>
<th scope="col">Sales</th>
</tr>
</thead>
<tbody>
<tr>
<td>January</td>
<td>$4,000</td>
</tr>
<tr>
<td>February</td>
<td>$5,200</td>
</tr>
</tbody>
<tfoot>
<tr>
<td>Total</td>
<td>$9,200</td>
</tr>
</tfoot>
</table>| Attribute | Description |
|---|---|
| id | Unique element identifier |
| class | CSS class(es) |
| style | Inline CSS styles |
| title | Tooltip text on hover |
| lang | Language code (en, es, fr) |
| dir | Text direction (ltr, rtl) |
| tabindex | Tab order (0=default, -1=skip) |
| hidden | Hides element |
| draggable | Enable drag (true/false) |
| contenteditable | Editable content (true) |
| role | ARIA role for accessibility |
| data-* | Custom data attributes |
| Element | Purpose |
|---|---|
| header | Page or section header |
| nav | Navigation links |
| main | Primary content (one per page) |
| article | Self-contained content |
| section | Thematic grouping |
| aside | Sidebar / tangential content |
| footer | Page or section footer |
| figure / figcaption | Media with caption |
| details / summary | Collapsible disclosure |
| time | Date/time with machine-readable value |
| mark | Highlighted text |
| progress | Progress bar |
| meter | Scalar measurement within range |
<div> tags. Semantic elements improve accessibility (screen readers), SEO (search engines understand structure), and code maintainability. Use <article> for blog posts, <section> for content groupings, and <nav> for navigation.<form action="/api/submit" method="POST" enctype="multipart/form-data">
<!-- ── Text Inputs ── -->
<input type="text" name="name" placeholder="Full Name" required
minlength="2" maxlength="100" autocomplete="name">
<input type="email" name="email" placeholder="Email" required autocomplete="email">
<input type="password" name="password" minlength="8" autocomplete="new-password">
<input type="tel" name="phone" placeholder="Phone" autocomplete="tel">
<input type="url" name="website" placeholder="Website" autocomplete="url">
<!-- ── Number Inputs ── -->
<input type="number" name="age" min="18" max="120" step="1">
<!-- ── Date & Time ── -->
<input type="date" name="birthday" min="1900-01-01">
<input type="time" name="appointment">
<input type="datetime-local" name="event">
<input type="month" name="expiry">
<input type="week" name="schedule">
<!-- ── Selection ── -->
<input type="checkbox" name="terms" required>
<input type="radio" name="plan" value="free" checked>
<input type="radio" name="plan" value="pro">
<select name="country">
<optgroup label="North America">
<option value="us">United States</option>
<option value="ca">Canada</option>
</optgroup>
<optgroup label="Europe">
<option value="uk">United Kingdom</option>
</optgroup>
</select>
<!-- ── Textarea ── -->
<textarea name="message" rows="5" cols="40"
placeholder="Your message..." maxlength="1000"></textarea>
<!-- ── Range & Color ── -->
<input type="range" name="volume" min="0" max="100" value="50">
<input type="color" name="theme" value="#6366f1">
<!-- ── File Upload ── -->
<input type="file" name="avatar" accept="image/*" multiple>
<!-- ── Hidden & Submit ── -->
<input type="hidden" name="csrf_token" value="abc123">
<button type="submit">Submit</button>
<button type="reset">Reset</button>
<button type="button">Custom Action</button>
</form><!-- ── Built-in Validation Attributes ── -->
<input required> <!-- Must have value -->
<input minlength="3"> <!-- Min 3 characters -->
<input maxlength="100"> <!-- Max 100 characters -->
<input pattern="[A-Za-z]+"> <!-- Regex pattern -->
<input min="0" max="100"> <!-- Number range -->
<input type="email"> <!-- Email format -->
<input type="url"> <!-- URL format -->
<input step="0.01"> <!-- Number step -->
<!-- ── CSS Validation Pseudo-classes ── -->
<style>
input:valid { border-color: green; }
input:invalid { border-color: red; }
input:required { border-left: 3px solid blue; }
input:optional { border-left: 3px solid gray; }
input:out-of-range { background: #fee; }
input:placeholder-shown { opacity: 0.5; }
/* Show validation message */
input:invalid:focus ~ .error-message { display: block; }
</style>
<!-- ── Constraint Validation API ── -->
<script>
const form = document.querySelector('form');
const email = document.querySelector('[name="email"]');
form.addEventListener('submit', (e) => {
e.preventDefault();
if (!form.checkValidity()) {
// Show all validation errors
form.reportValidity();
return;
}
// Submit form data
});
// Custom validation
email.addEventListener('input', () => {
if (email.validity.typeMismatch) {
email.setCustomValidity('Please enter a valid email');
} else {
email.setCustomValidity('');
}
});
// Check individual validity
email.validity.valid; // boolean
email.validity.valueMissing; // required but empty
email.validity.tooShort; // below minlength
email.validity.tooLong; // above maxlength
email.validity.patternMismatch; // doesn't match pattern
email.validity.rangeOverflow; // above max
email.validity.rangeUnderflow; // below min
</script>| Type | Purpose | Mobile Keyboard |
|---|---|---|
| text | General text | Default |
| Email address | @ keyboard | |
| password | Password | Secure input |
| tel | Phone number | Numeric keypad |
| number | Numeric value | Numeric keypad |
| url | URL | URL keyboard |
| search | Search | Search keyboard |
| date | Date picker | Date picker |
| time | Time picker | Time picker |
| color | Color picker | Color wheel |
| range | Slider | Slider |
| file | File upload | File picker |
| Attribute | Description |
|---|---|
| action | URL to submit to |
| method | GET or POST |
| enctype | MIME type (multipart/form-data) |
| novalidate | Disable browser validation |
| autocomplete | on/off/off-"field" |
| target | _blank, _self, _parent |
| name | Form name for JS access |
| rel | Relationship (noopener) |
autocomplete attributes on all form fields to improve UX. Browser autofill speeds up form completion. Use for="id" on <label> elements to link them to inputs for accessibility./* ── Basic Selectors ── */
p { } /* Element selector */
.className { } /* Class selector */
#id { } /* ID selector */
* { } /* Universal selector */
/* ── Combinators ── */
div, p { } /* Multiple elements */
div p { } /* Descendant (any level) */
div > p { } /* Direct child only */
div + p { } /* Adjacent sibling (next) */
div ~ p { } /* General sibling */
/* ── Attribute Selectors ── */
[type="text"] { } /* Exact match */
[type^="email"] { } /* Starts with */
[type$="number"] { } /* Ends with */
[type*="pass"] { } /* Contains */
[data-active] { } /* Has attribute */
[data-active="true"] { } /* Attribute equals */
/* ── Pseudo-classes ── */
a:hover { } /* Mouse over */
a:active { } /* Being clicked */
a:focus { } /* Focused */
a:focus-visible { } /* Keyboard focus only */
a:visited { } /* Already visited */
input:disabled { } /* Disabled input */
input:checked { } /* Checked checkbox */
input:read-only { } /* Read-only input */
p:first-child { } /* First child of parent */
p:last-child { } /* Last child of parent */
p:nth-child(2) { } /* 2nd child */
p:nth-child(odd) { } /* Odd-numbered children */
p:nth-child(3n+1) { } /* Every 3rd, starting at 1 */
p:not(.active) { } /* Negation */
p:empty { } /* No children */
p:has(> img) { } /* Parent matching (new!) */
p:is(.a, .b) { } /* Matches any selector */
p:where(.a, .b) { } /* Zero specificity */
/* ── Pseudo-elements ── */
p::before { content: ""; } /* Before element */
p::after { content: ""; } /* After element */
p::first-line { } /* First line only */
p::first-letter { } /* First letter */
::selection { } /* Selected text */
::placeholder { } /* Input placeholder */
::marker { } /* List marker *//* ── Specificity (high to low) ── */
/* !important → 1,0,0,0,0 */
/* Inline style → 1,0,0,0 */
/* #id → 0,1,0,0 */
/* .class, :pseudo → 0,0,1,0 */
/* element, ::pseudo → 0,0,0,1 */
/* * → 0,0,0,0 */
/* ── Specificity Examples ── */
#nav .item a /* 0,1,1,1 → 113 */
.nav .item a /* 0,0,2,1 → 21 */
ul li a /* 0,0,0,3 → 3 */
a /* 0,0,0,1 → 1 */
/* ── Cascade Layers (CSS @layer) ── */
@layer reset, base, components, utilities;
@layer reset {
* { margin: 0; padding: 0; box-sizing: border-box; }
}
@layer base {
body { font-family: system-ui, sans-serif; }
}
@layer components {
.card { border-radius: 8px; padding: 1rem; }
}
@layer utilities {
.text-center { text-align: center; }
}
/* Unlayered styles beat ALL layers */
/* Layer order: reset < base < components < utilities */
/* ── !important in layers ── */
/* !important in a lower layer wins over a higher layer */| Do | Avoid | Reason |
|---|---|---|
| .class | div.class | Class alone is faster |
| .nav-link | nav > ul > li > a | Simpler = faster |
| #main | #main div div div | Less nesting = faster |
| .card:hover | div div div:hover | Direct class |
| p:first-child | p:nth-child(1) | Simpler selector |
| Unit | Type | Description |
|---|---|---|
| px | Absolute | Pixels (fixed) |
| rem | Relative | Root font size (default 16px) |
| em | Relative | Parent font size |
| % | Relative | Parent element value |
| vw | Viewport | 1% of viewport width |
| vh | Viewport | 1% of viewport height |
| vmin | Viewport | Min of vw/vh |
| vmax | Viewport | Max of vw/vh |
| ch | Relative | Width of "0" character |
| fr | Grid | Fraction of available space |
/* ── Box Model (inside → out) ── */
/* content → padding → border → margin */
/* ── box-sizing ── */
/* content-box (default): width = content only */
/* border-box: width = content + padding + border */
*, *::before, *::after {
box-sizing: border-box; /* ALWAYS use this! */
}
/* ── Width & Height ── */
.box {
width: 300px;
height: 200px;
min-width: 200px;
max-width: 100%;
min-height: 100px;
max-height: 80vh;
}
/* ── Padding ── */
.box {
padding: 16px; /* All sides */
padding: 16px 24px; /* Top/bottom, left/right */
padding: 8px 16px 24px 32px; /* Top, right, bottom, left */
padding-top: 16px;
padding-inline: 24px; /* Logical: start/end */
}
/* ── Margin ── */
.box {
margin: 16px;
margin: auto; /* Center horizontally (block) */
margin: 0 auto; /* Center block */
margin-block: 16px; /* Logical: block start/end */
margin-inline: auto; /* Logical: inline start/end */
}
/* ── Margin Collapse ── */
/* Only vertical margins collapse between block-level siblings */
/* The larger margin wins (not additive) *//* ── Border ── */
.box {
border: 1px solid #ccc;
border: 2px dashed red;
border: 3px dotted blue;
border-top: 4px solid #333;
border-radius: 8px;
border-radius: 50%; /* Circle */
border-radius: 12px 0; /* Pill shape */
}
/* ── Outline (doesn't affect layout!) ── */
.box:focus {
outline: 2px solid blue;
outline-offset: 4px; /* Gap between outline and element */
outline: none; /* Remove (bad for accessibility!) */
outline: 2px solid transparent; /* Hidden but space reserved */
}
/* ── Box Shadow ── */
.card {
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1),
0 2px 4px -2px rgba(0, 0, 0, 0.1);
/* Syntax: offset-x, offset-y, blur, spread, color */
}
/* Inset shadow (inner shadow) */
.input {
box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.1);
}
/* Multiple shadows */
.card {
box-shadow:
0 0 0 1px rgba(0, 0, 0, 0.05),
0 4px 6px -1px rgba(0, 0, 0, 0.1),
0 10px 15px -3px rgba(0, 0, 0, 0.1);
}| Value | Behavior |
|---|---|
| block | Full width, new line (div, p, h1) |
| inline | No line break, no width/height (span, a) |
| inline-block | Inline flow but block sizing |
| flex | Flexbox container |
| inline-flex | Inline flexbox container |
| grid | CSS Grid container |
| inline-grid | Inline grid container |
| none | Removed from layout (no space) |
| contents | Box disappears, children remain |
| table | Table display model |
| Value | Behavior |
|---|---|
| visible | Content overflows (default) |
| hidden | Content clipped, no scrollbar |
| scroll | Always show scrollbar |
| auto | Scrollbar only when needed |
| clip | Clip like hidden, no programmatic scroll |
box-sizing: border-box on all elements. Apply it globally with *, *::before, *::after { box-sizing: border-box; }. This makes width/height include padding and border, making layouts predictable and easier to reason about..container {
display: flex;
/* ── Direction ── */
flex-direction: row; /* left → right (default) */
flex-direction: row-reverse; /* right → left */
flex-direction: column; /* top → bottom */
flex-direction: column-reverse; /* bottom → top */
/* ── Wrapping ── */
flex-wrap: nowrap; /* Single line (default) */
flex-wrap: wrap; /* Multi-line */
flex-wrap: wrap-reverse; /* Reverse wrap */
/* ── Shorthand: flex-flow ── */
flex-flow: row wrap;
/* ── Main Axis Alignment (justify-content) ── */
justify-content: flex-start; /* Pack to start */
justify-content: flex-end; /* Pack to end */
justify-content: center; /* Center */
justify-content: space-between; /* Equal space between */
justify-content: space-around; /* Equal space around */
justify-content: space-evenly; /* Equal space everywhere */
/* ── Cross Axis Alignment (align-items) ── */
align-items: stretch; /* Stretch to fill (default) */
align-items: flex-start; /* Align to start */
align-items: flex-end; /* Align to end */
align-items: center; /* Center */
align-items: baseline; /* Align text baselines */
/* ── Multi-line Alignment (align-content) ── */
align-content: flex-start;
align-content: center;
align-content: space-between;
/* ── Gap ── */
gap: 16px; /* Both axes */
gap: 8px 16px; /* Row gap, column gap */
row-gap: 8px;
column-gap: 16px;
}.item {
/* ── Grow ── */
flex-grow: 0; /* Don't grow (default) */
flex-grow: 1; /* Grow equally */
flex-grow: 2; /* Grow twice as much */
/* ── Shrink ── */
flex-shrink: 1; /* Shrink when needed (default) */
flex-shrink: 0; /* Never shrink */
/* ── Basis ── */
flex-basis: auto; /* Based on content/width */
flex-basis: 200px; /* Start at 200px */
flex-basis: 0; /* Start at 0 (grow distributes all space) */
/* ── Shorthand: flex (grow shrink basis) ── */
flex: 0 1 auto; /* Default */
flex: 1; /* flex: 1 1 0% */
flex: 1 200px; /* flex: 1 1 200px */
flex: none; /* flex: 0 0 auto */
/* ── Individual Alignment ── */
align-self: auto; /* Inherit from container */
align-self: flex-start;
align-self: center;
align-self: stretch;
/* ── Order ── */
order: 0; /* Default order */
order: -1; /* Move to front */
order: 1; /* Move to back */
}/* Center everything */
.center {
display: flex;
align-items: center;
justify-content: center;
}
/* Sticky footer */
.page {
display: flex;
flex-direction: column;
min-height: 100vh;
}
.page main { flex: 1; }
/* Navbar */
.nav {
display: flex;
align-items: center;
justify-content: space-between;
}
/* Equal-width columns */
.columns {
display: flex;
gap: 1rem;
}
.columns > * { flex: 1; }
/* Media object */
.media {
display: flex;
align-items: flex-start;
gap: 1rem;
}
.media img { flex: 0 0 48px; }| flex: | grow | shrink | basis |
|---|---|---|---|
| flex: 0 1 auto | 0 | 1 | auto (default) |
| flex: 1 | 1 | 1 | 0% |
| flex: auto | 1 | 1 | auto |
| flex: none | 0 | 0 | auto |
| flex: 2 | 2 | 1 | 0% |
| flex: 0 0 200px | 0 | 0 | 200px |
| flex: 1 0 200px | 1 | 0 | 200px |
.grid {
display: grid;
/* ── Columns & Rows ── */
grid-template-columns: 200px 1fr 200px; /* 3 columns */
grid-template-columns: repeat(3, 1fr); /* 3 equal cols */
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); /* Responsive! */
grid-template-columns: 1fr 2fr 1fr; /* Ratio columns */
grid-template-columns: 100px repeat(3, 1fr) 100px; /* Fixed + repeat */
grid-template-rows: auto 1fr auto;
/* ── Gap ── */
gap: 16px;
gap: 16px 24px; /* row, column */
/* ── Shorthand: grid ── */
grid: auto-flow 1fr / 200px 1fr 200px;
/* ── Alignment ── */
justify-items: start | end | center | stretch; /* Column align */
align-items: start | end | center | stretch; /* Row align */
place-items: center; /* Both */
justify-content: center; /* Grid on page (horizontal) */
align-content: center; /* Grid on page (vertical) */
}
/* ── Named Grid Areas ── */
.layout {
display: grid;
grid-template-areas:
"header header header"
"nav main aside"
"footer footer footer";
grid-template-columns: 200px 1fr 200px;
grid-template-rows: auto 1fr auto;
min-height: 100vh;
}
.header { grid-area: header; }
.nav { grid-area: nav; }
.main { grid-area: main; }
.aside { grid-area: aside; }
.footer { grid-area: footer; }.item {
/* ── Span ── */
grid-column: span 2; /* Span 2 columns */
grid-row: span 3; /* Span 3 rows */
grid-column: 1 / 3; /* From line 1 to 3 */
grid-column: 1 / -1; /* Full width (first to last) */
grid-row: 2 / 4; /* From row 2 to 4 */
/* ── Shorthand ── */
grid-area: 2 / 1 / 4 / 3; /* row-start / col-start / row-end / col-end */
grid-area: header; /* Named area */
/* ── Placement ── */
grid-column-start: 2;
grid-column-end: span 2;
justify-self: start | center | end | stretch;
align-self: start | center | end | stretch;
place-self: center; /* Both */
}
/* ── Auto-fill vs Auto-fit ── */
.grid-auto-fit {
/* auto-fit: collapses empty tracks */
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}
.grid-auto-fill {
/* auto-fill: keeps empty tracks */
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}| Aspect | Flexbox | Grid |
|---|---|---|
| Dimension | 1D (row or column) | 2D (rows and columns) |
| Best for | Content flow, alignment | Page layouts, complex grids |
| Content-driven | Yes | No |
| Sizing | flex-grow/shrink | fr, minmax, auto-fit |
| Gaps | gap property | gap property |
| Overlap | No | Yes (grid-area overlap) |
| Function | Description |
|---|---|
| repeat(n, ...) | Repeat n times |
| minmax(min, max) | Size range |
| auto-fit | Collapse empty tracks |
| auto-fill | Keep empty tracks |
| min() | Min of values |
| max() | Max of values |
| clamp(min, pref, max) | Clamped value |
/* ── Transition Syntax ── */
.element {
/* property | duration | timing-function | delay */
transition: background-color 0.3s ease, transform 0.2s ease;
/* Shorthand for all properties */
transition: all 0.3s ease-in-out;
/* Individual properties */
transition-property: transform, opacity;
transition-duration: 300ms;
transition-timing-function: ease;
transition-delay: 0s;
}
.element:hover {
transform: translateY(-2px);
background-color: #333;
}
/* ── Timing Functions ── */
.timing {
transition-timing-function: ease; /* Smooth (default) */
transition-timing-function: ease-in; /* Slow start */
transition-timing-function: ease-out; /* Slow end */
transition-timing-function: ease-in-out; /* Slow start & end */
transition-timing-function: linear; /* Constant speed */
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); /* Custom curve */
/* Popular curves */
/* cubic-bezier(0.4, 0, 0.2, 1) — Material ease */
/* cubic-bezier(0.22, 1, 0.36, 1) — Ease out expo */
/* cubic-bezier(0.68, -0.55, 0.265, 1.55) — Back (bounce) */
}/* ── @keyframes ── */
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes slideUp {
0% { transform: translateY(20px); opacity: 0; }
100% { transform: translateY(0); opacity: 1; }
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
@keyframes pulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.05); }
}
@keyframes shake {
0%, 100% { transform: translateX(0); }
10%, 30%, 50%, 70%, 90% { transform: translateX(-4px); }
20%, 40%, 60%, 80% { transform: translateX(4px); }
}
/* ── Animation Syntax ── */
.animated {
/* name | duration | timing | delay | iteration | direction | fill | play */
animation: fadeIn 0.3s ease-out forwards;
animation: slideUp 0.5s ease-out 0.2s forwards; /* With delay */
animation: spin 1s linear infinite; /* Infinite loop */
animation: pulse 2s ease-in-out infinite; /* Pulse */
animation: shake 0.5s ease; /* One shot */
/* Individual properties */
animation-name: fadeIn;
animation-duration: 300ms;
animation-timing-function: ease-out;
animation-delay: 0s;
animation-iteration-count: 1; /* or infinite */
animation-direction: normal; /* or reverse, alternate */
animation-fill-mode: forwards; /* Keep final state */
animation-play-state: running; /* or paused */
}.element {
/* ── Transform Functions ── */
transform: translateX(10px); /* Move right */
transform: translateY(-20px); /* Move up */
transform: translate(10px, -20px); /* Move both */
transform: translate(50%); /* 50% of own size */
transform: scale(1.5); /* Grow 50% */
transform: scale(0.8); /* Shrink 20% */
transform: scaleX(2); /* Wider */
transform: scaleY(0.5); /* Shorter */
transform: rotate(45deg); /* Rotate 45 degrees */
transform: rotateX(45deg); /* 3D rotate X */
transform: rotateY(45deg); /* 3D rotate Y */
transform: skewX(10deg); /* Skew X axis */
transform: skewY(5deg); /* Skew Y axis */
/* ── Combine transforms (order matters!) ── */
transform: translateX(50%) rotate(45deg) scale(1.2);
/* ── Transform Origin ── */
transform-origin: center; /* Default */
transform-origin: top left;
transform-origin: 50% 100%; /* Bottom center */
transform-origin: 0 0; /* Top left corner */
/* ── 3D Transforms ── */
perspective: 1000px; /* Parent: depth */
transform-style: preserve-3d; /* Parent: children 3D */
backface-visibility: hidden; /* Hide back face */
}| Feature | Transition | Animation |
|---|---|---|
| Trigger | State change (:hover) | Auto or via class |
| Run once? | Yes (one state change) | Can loop infinitely |
| Keyframes | No (from → to only) | Yes (multiple steps) |
| Delay | Yes | Yes |
| Direction | N/A | Normal, reverse, alternate |
| JS control | Limited | Animation API |
| Best for | Hover effects, toggles | Loading, attention, looping |
transform and opacity for 60fps performance. These properties are GPU-composited and don't trigger layout reflow. Avoid animating width, height, top, left, or margin — they cause expensive reflows./* ── Breakpoint-based Queries ── */
/* Mobile-first approach: base → larger */
/* Base: Mobile (0 - 639px) */
.container {
padding: 1rem;
font-size: 14px;
}
/* Tablet (640px+) */
@media (min-width: 640px) {
.container { padding: 1.5rem; font-size: 15px; }
}
/* Desktop (768px+) */
@media (min-width: 768px) {
.container { padding: 2rem; }
.grid { display: grid; grid-template-columns: 250px 1fr; }
}
/* Large Desktop (1024px+) */
@media (min-width: 1024px) {
.container { max-width: 1200px; margin: 0 auto; }
}
/* ── Desktop-first (max-width) ── */
@media (max-width: 767px) {
.sidebar { display: none; }
}
/* ── Range Queries ── */
@media (min-width: 768px) and (max-width: 1023px) {
/* Tablet only */
}
/* ── Feature Queries ── */
@supports (display: grid) {
.layout { display: grid; }
}
@supports not (backdrop-filter: blur()) {
.glass { background: rgba(0, 0, 0, 0.8); }
}
/* ── Dark Mode ── */
@media (prefers-color-scheme: dark) {
body { background: #111; color: #eee; }
}
/* ── Reduced Motion ── */
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
}
/* ── Print ── */
@media print {
nav, footer { display: none; }
body { font-size: 12pt; color: black; }
a::after { content: " (" attr(href) ")"; }
}/* ── Container Queries (modern responsive!) ── */
/* Style based on parent container size, not viewport */
.card-container {
container-type: inline-size;
container-name: card;
}
@container card (min-width: 400px) {
.card { display: flex; gap: 1rem; }
.card img { width: 150px; }
}
@container card (max-width: 399px) {
.card { display: block; }
.card img { width: 100%; }
}
/* ── Responsive Typography (clamp) ── */
h1 {
font-size: clamp(1.5rem, 5vw, 3rem);
/* min: 1.5rem, preferred: 5vw, max: 3rem */
line-height: 1.2;
}
p {
font-size: clamp(0.875rem, 2vw, 1.125rem);
}| Name | Min Width | Tailwind |
|---|---|---|
| Mobile | 0px | default |
| SM | 640px | sm: |
| MD | 768px | md: |
| LG | 1024px | lg: |
| XL | 1280px | xl: |
| 2XL | 1536px | 2xl: |
| Feature | Syntax | Support |
|---|---|---|
| Container Queries | @container | Chrome 105+ |
| :has() Selector | div:has(> img) | Chrome 105+ |
| :where() | Zero specificity | All modern |
| :is() | Matches any | All modern |
| Subgrid | grid: subgrid | Firefox 71+ |
| @layer | Cascade layers | All modern |
| clamp() | clamp(min, pref, max) | All modern |
| min()/max() | min(100%, 300px) | All modern |
| color-mix() | color-mix(in srgb) | Chrome 111+ |
| nesting | & .child {} | Chrome 120+ |
clamp() for fluid typography instead of breakpoint-based font sizes. font-size: clamp(1rem, 2.5vw, 2rem) smoothly scales between 1rem and 2rem as the viewport grows. Add @media (prefers-reduced-motion: reduce) to respect user preferences.Every element has 4 layers: content → padding →border → margin. With box-sizing: content-box (default), width/height only applies to the content area — padding and border add to the total size. With box-sizing: border-box, width/height includes padding and border, making it much easier to calculate element dimensions. Always use border-box globally.
CSS specificity determines which rules apply when multiple rules target the same element. From highest to lowest: !important → inline styles → #id→ .class / :pseudo-class→ element / ::pseudo-element. The cascade also considers: origin (user agent, author, user), importance, specificity, and source order. Later rules win when specificity is equal.
| Aspect | Flexbox (1D) | Grid (2D) |
|---|---|---|
| Dimensions | Row OR column | Rows AND columns |
| Content-driven | Yes, items drive layout | No, grid defines structure |
| Alignment | Main + cross axis | Row + column axis + areas |
| Use case | Navbars, cards, forms | Page layouts, dashboards |
| Wrapping | flex-wrap | auto-fit/auto-fill |
| Overlap | Not possible | Possible with grid-area |
| Gap | gap property | gap property |
Reflow (Layout): Browser recalculates element positions and sizes. Expensive. Triggered by changes to geometry: width, height, padding, margin, border, position, font-size.Repaint: Browser redraws pixels without recalculating layout. Cheaper. Triggered by: color, background, visibility, box-shadow, outline. Composite: GPU-only layer operations. Cheapest. Only transform and opacity. Optimize by only animatingtransform and opacity, and usingwill-change sparingly.
/* ── CSS Custom Properties ── */
:root {
--color-primary: #6366f1;
--spacing-unit: 8px;
--font-size-base: 16px;
}
.button {
--button-bg: var(--color-primary);
background: var(--button-bg);
padding: calc(var(--spacing-unit) * 2);
font-size: var(--font-size-base);
}
/* Differ from Sass/LESS variables: */
/* 1. Live in the browser (can be changed at runtime) */
/* 2. Cascade (can be overridden per element) */
/* 3. Inherit (child can access parent's custom props) */
/* 4. Work with media queries */
/* 5. Can be changed via JavaScript */
/* element.style.setProperty('--color', 'red'); */| Position | Behavior | Use Case |
|---|---|---|
| static | Normal document flow (default) | Base elements |
| relative | Offset from normal position, still in flow | Offset container for absolute children |
| absolute | Removed from flow, relative to nearest positioned ancestor | Tooltips, modals, dropdowns |
| fixed | Removed from flow, relative to viewport | Sticky nav, cookie banner |
| sticky | In flow until scroll threshold, then fixed | Section headers, table headers |