From ccube-frontend-dev
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.
How this skill is triggered — by the user, by Claude, or both
Slash command
/ccube-frontend-dev:cc-css-essentialsThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Quick-reference for CSS fundamentals. This skill is
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.
Every HTML element is a rectangular box. From inside out: content → padding → border → margin.
+---------------------------+
| margin |
| +---------------------+ |
| | border | |
| | +---------------+ | |
| | | padding | | |
| | | +---------+ | | |
| | | | content | | | |
| | | +---------+ | | |
| | +---------------+ | |
| +---------------------+ |
+---------------------------+
box-sizing: border-boxBy 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 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; /* default: row | column */
justify-content: center; /* main axis alignment */
align-items: center; /* cross axis alignment */
gap: 16px; /* space between items */
flex-wrap: wrap; /* allow items to wrap */
}
| 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 |
/* Centre a single item horizontally and vertically */
.centre {
display: flex;
justify-content: center;
align-items: center;
}
/* Space items apart (e.g. nav bar) */
nav {
display: flex;
justify-content: space-between;
align-items: center;
}
/* Sticky footer layout */
.page {
display: flex;
flex-direction: column;
min-height: 100vh;
}
.content {
flex: 1; /* pushes footer to the bottom */
}
.item {
flex: 1; /* shorthand: 1 1 0 (browsers use 0%) */
flex-shrink: 0; /* prevent shrinking below flex-basis */
flex-basis: 200px; /* starting size before flex algorithm */
min-width: 0; /* fix text overflow in flex items */
}
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.
Grid is a two-dimensional layout model. Use it for page-level and complex layouts.
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr); /* 3 equal columns */
gap: 16px;
}
/* Responsive: as many columns as fit at min 200px each */
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
/* Fixed sidebar + flexible main content */
grid-template-columns: 250px 1fr;
/* 12-column grid */
grid-template-columns: repeat(12, 1fr);
.hero {
grid-column: 1 / -1; /* span all columns */
}
.sidebar {
grid-column: 1 / 2;
grid-row: 1 / 3;
}
| 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:
rem for most sizing — respects the user's browser font
setting, making the UI accessible1rem = 16px by default; 1.5rem = 24pxpx for font sizes — it overrides user accessibility
preferencesvw for widths — on desktop, 100vw includes the
scrollbar, causing horizontal overflow; use 100% insteadSpecificity 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):
p, div → 0,0,1.btn → 0,1,0#main → 1,0,0style="..." → wins over normal author
stylesheet rules!important is not a specificity level — it changes cascade
importance and should be used sparingly.
Rules:
!important to fix a specificity problem —
restructure your selectors instead.card-title) are easier to override than
deeply nested ones (.card .header .title)position: static; /* default — stays in normal document flow */
position: relative; /* offsets from its normal position */
position: absolute; /* removed from flow; positioned relative to
its containing block */
position: fixed; /* relative to the viewport unless an ancestor
establishes a containing block */
position: sticky; /* normal flow until scroll threshold, then
sticks to top/bottom */
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.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)./* Overlay a badge on a card */
.card-wrapper {
position: relative;
}
.badge {
position: absolute;
top: 8px;
right: 8px;
}
z-index controls the vertical stacking order of overlapping
elements. It applies to positioned elements and also flex/grid
items.
Common stacking context triggers include:
position (not static) + z-index (not auto)position: fixed or position: stickyopacity less than 1transform, filter, will-change, perspectiveisolation: isolate, contain: paint|layout,
container-type: size|inline-sizez-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.
/* Define a z-index scale — never scatter magic numbers */
: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;
}
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; /* base — mobile */
}
@media (min-width: 768px) {
.container {
padding: 24px; /* tablet and up */
}
}
@media (min-width: 1024px) {
.container {
padding: 32px;
max-width: 1200px;
margin: 0 auto;
}
}
| Name | Min-width |
|---|---|
| Mobile (base) | 0 |
| Tablet | 768px |
| Desktop | 1024px |
| Wide | 1280px |
Key points:
max-width on page containers to prevent content
from stretching too wide on large screensmax-width: 100% prevents overflow; use
object-fit: cover on fixed-size image containers| 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 |
box-sizing: border-box — elements will be
larger than their declared widthpx for font sizes — overrides the user's
accessibility font preferences; use rem instead!important — creates a specificity arms race;
restructure selectors to fix the real causemargin-top: 37px;
extract values into CSS variables or design tokensabsolute child without relative parent — element
jumps to an unexpected ancestor or the document rootz-index arms race — z-index: 9999 scattered
everywhere; define a z-index scale with CSS variableswidth: 100vw — includes the scrollbar on
desktop, causing horizontal scroll; use width: 100%min-width: 0 on flex items — text and
long words will not wrap or truncate as expectednpx claudepluginhub lifesg/ccube-agent-plugin-marketplace --plugin ccube-frontend-devProvides behavioral guidelines to reduce common LLM coding mistakes, focusing on simplicity, surgical changes, assumption surfacing, and verifiable success criteria.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.