| name | cc-css-essentials |
| description | CSS fundamentals — box model, flexbox, grid, units, specificity, positioning, z-index, and responsive design. Library-agnostic. Use when writing, reviewing, or debugging styles in any web project regardless of CSS library or framework. |
| user-invocable | false |
CSS Essentials
Quick-reference for CSS fundamentals. This skill is
library-agnostic — all examples use plain CSS. For
styled-components API patterns, see the cc-styled-components
skill.
The Box Model
Every HTML element is a rectangular box. From inside out:
content → padding → border → margin.
+---------------------------+
| margin |
| +---------------------+ |
| | border | |
| | +---------------+ | |
| | | padding | | |
| | | +---------+ | | |
| | | | content | | | |
| | | +---------+ | | |
| | +---------------+ | |
| +---------------------+ |
+---------------------------+
box-sizing: border-box
By default, width sets only the content box. Padding and
border are added on top, making the element larger than its
declared width. Always apply globally:
*, *::before, *::after {
box-sizing: border-box;
}
With border-box, width includes padding and border — far
more intuitive.
Common bug: An element is wider than expected. Almost always
caused by missing box-sizing: border-box.
Flexbox
Flexbox is a one-dimensional layout model (row or column). It
is the right tool for most component-level layouts.
.row {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
gap: 16px;
flex-wrap: wrap;
}
Alignment Quick Reference
| Property | Axis | Common values |
|---|
justify-content | Main (row = horizontal) | flex-start, flex-end, center, space-between, space-evenly |
align-items | Cross (row = vertical) | flex-start, flex-end, center, stretch, baseline |
align-self | Cross — one item only | Same as align-items |
Common Patterns
.centre {
display: flex;
justify-content: center;
align-items: center;
}
nav {
display: flex;
justify-content: space-between;
align-items: center;
}
.page {
display: flex;
flex-direction: column;
min-height: 100vh;
}
.content {
flex: 1;
}
Flex Item Properties
.item {
flex: 1;
flex-shrink: 0;
flex-basis: 200px;
min-width: 0;
}
Common bug: Text inside a flex item overflows or does not
wrap. Add min-width: 0 — flex items default to
min-width: auto, which prevents shrinking below content size.
CSS Grid
Grid is a two-dimensional layout model. Use it for page-level
and complex layouts.
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 16px;
}
Common Column Patterns
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
grid-template-columns: 250px 1fr;
grid-template-columns: repeat(12, 1fr);
Placing Items
.hero {
grid-column: 1 / -1;
}
.sidebar {
grid-column: 1 / 2;
grid-row: 1 / 3;
}
Flexbox vs Grid
- Flexbox: One direction — navbars, button groups, card
rows where items wrap naturally
- Grid: Two directions — page layouts, image galleries,
dashboards, anything requiring explicit row + column alignment
Units
| Unit | What it is | When to use |
|---|
px | Fixed pixels | Borders, shadows, min-width |
rem | Relative to root font-size (default 16px) | Font sizes, spacing, sizing |
em | Relative to font-size context | Padding tied to text size |
% | Relative to parent dimension | Fluid widths |
vw / vh | 1% of viewport width / height | Full-viewport sections |
fr | Fraction unit in grid | Grid column widths |
ch | Width of the 0 character | Constraining text line width |
Recommendation:
- Use
rem for most sizing — respects the user's browser font
setting, making the UI accessible
1rem = 16px by default; 1.5rem = 24px
- Avoid
px for font sizes — it overrides user accessibility
preferences
- Avoid
vw for widths — on desktop, 100vw includes the
scrollbar, causing horizontal overflow; use 100% instead
Specificity
Specificity helps break ties only after cascade origin, layer,
and importance are resolved. Within the same origin/layer and
importance, higher specificity wins.
Specificity order (lowest to highest):
- Element selector:
p, div → 0,0,1
- Class selector:
.btn → 0,1,0
- ID selector:
#main → 1,0,0
- Inline style:
style="..." → wins over normal author
stylesheet rules
!important is not a specificity level — it changes cascade
importance and should be used sparingly.
Rules:
- Prefer class selectors over ID selectors for styling
- Never use
!important to fix a specificity problem —
restructure your selectors instead
- Flat selectors (
.card-title) are easier to override than
deeply nested ones (.card .header .title)
Positioning
position: static;
position: relative;
position: absolute;
position: fixed;
position: sticky;
Key rules:
absolute positioning uses the nearest containing block.
Commonly this is the nearest ancestor with
position: relative/absolute/fixed, but transforms,
filters, and containment can also create containing blocks.
- Always set
position: relative on the parent when using
position: absolute on a child.
sticky requires a non-auto inset (top, bottom, etc.)
and sticks relative to the nearest ancestor with a scrolling
mechanism (overflow: auto | scroll | hidden | overlay).
.card-wrapper {
position: relative;
}
.badge {
position: absolute;
top: 8px;
right: 8px;
}
Z-index and Stacking Context
z-index controls the vertical stacking order of overlapping
elements. It applies to positioned elements and also flex/grid
items.
Stacking Context Rules
Common stacking context triggers include:
position (not static) + z-index (not auto)
position: fixed or position: sticky
opacity less than 1
transform, filter, will-change, perspective
isolation: isolate, contain: paint|layout,
container-type: size|inline-size
z-index only competes within the same stacking context. A
z-index: 9999 child cannot escape its parent's stacking
context.
Common bug: A modal with z-index: 9999 disappears behind
a navigation bar. The modal's parent likely has transform or
opacity set, trapping the modal inside a lower context.
:root {
--z-base: 0;
--z-dropdown: 100;
--z-sticky: 200;
--z-modal-bg: 300;
--z-modal: 400;
--z-toast: 500;
}
.modal {
z-index: var(--z-modal);
position: fixed;
}
Responsive Design
Mobile-first approach: write base styles for mobile, then
override with min-width media queries for larger screens.
This ensures the smallest, simplest layout is the default.
.container {
padding: 16px;
}
@media (min-width: 768px) {
.container {
padding: 24px;
}
}
@media (min-width: 1024px) {
.container {
padding: 32px;
max-width: 1200px;
margin: 0 auto;
}
}
Common Breakpoints
| Name | Min-width |
|---|
| Mobile (base) | 0 |
| Tablet | 768px |
| Desktop | 1024px |
| Wide | 1280px |
Key points:
- Always add
max-width on page containers to prevent content
from stretching too wide on large screens
- Images:
max-width: 100% prevents overflow; use
object-fit: cover on fixed-size image containers
- Test at 375px (iPhone SE) and 768px (tablet) regularly
Common Layout Bugs
| Bug | Cause | Fix |
|---|
| Element wider than container | Missing box-sizing: border-box | Apply global box-sizing reset |
| Text overflows flex item | min-width: auto default | Add min-width: 0 to the flex item |
absolute child in wrong position | No position: relative on parent | Add position: relative to parent |
z-index has no effect | Wrong stacking context or target | Ensure positioned/flex/grid item, then inspect stacking contexts |
sticky not sticking | No inset or wrong scroll ancestor | Set top/bottom; check nearest overflow ancestor |
| Horizontal scroll on mobile | 100vw includes scrollbar | Use width: 100% instead of 100vw |
| Image stretches in flex/grid | Stretch alignment or intrinsic sizing mismatch | Set align-self: start and/or explicit size/object-fit |
| Margins between siblings merge | Adjacent block margins collapse | Use gap or padding instead |
| Modal behind nav bar | Parent has transform/opacity | Render modal at the document root |
Common Mistakes to Flag
- No global
box-sizing: border-box — elements will be
larger than their declared width
- Using
px for font sizes — overrides the user's
accessibility font preferences; use rem instead
- Using
!important — creates a specificity arms race;
restructure selectors to fix the real cause
- Hardcoded magic numbers —
margin-top: 37px;
extract values into CSS variables or design tokens
absolute child without relative parent — element
jumps to an unexpected ancestor or the document root
z-index arms race — z-index: 9999 scattered
everywhere; define a z-index scale with CSS variables
- Using
width: 100vw — includes the scrollbar on
desktop, causing horizontal scroll; use width: 100%
- Not testing on mobile — always test at 375px width;
desktop-only development produces broken mobile layouts
- Forgetting
min-width: 0 on flex items — text and
long words will not wrap or truncate as expected