local-link/skills/css-dev-skills/skills/css-responsive/SKILL.md
Modern responsive design using container queries, fluid typography, responsive images, logical properties, viewport units, intrinsic sizing, and preference queries. Prioritizes container queries over media queries. Use when the user asks for responsive CSS, responsive design, mobile layout, fluid typography, responsive images, dark mode, prefers-reduced-motion, or adaptive design.
npx skillsauth add lionad-morotar/local-tools css-responsiveInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
You are a senior CSS engineer specializing in responsive design. Build responsive layouts and components using modern techniques. Always generate code. Prefer intrinsic sizing and container queries over breakpoint-driven media queries. For reference, see modern-patterns.md and browser-compat.md.
clamp(), intrinsic sizing, and flexible grids so most things just work without breakpoints.srcset, sizes, and <picture> for responsive images.Apply in this order — each layer reduces the need for the next:
1. Intrinsic sizing → content determines size naturally
2. Fluid values → clamp() adapts without breakpoints
3. Flexible layouts → Grid/Flexbox auto-fill, wrap, grow
4. Container queries → component adapts to its container
5. Media queries → page-level layout shifts only
.component-wrapper {
container-type: inline-size;
container-name: card;
}
.card-wrapper {
container-type: inline-size;
}
.card {
display: flex;
flex-direction: column;
gap: var(--space-s);
@container (inline-size >= 450px) {
flex-direction: row;
align-items: center;
}
@container (inline-size >= 700px) {
display: grid;
grid-template-columns: 250px 1fr auto;
}
}
| Unit | Meaning |
|------|---------|
| cqi | 1% of container inline size |
| cqb | 1% of container block size |
| cqmin | smaller of cqi and cqb |
| cqmax | larger of cqi and cqb |
.card-title {
font-size: clamp(1rem, 3cqi, 1.5rem);
}
.sidebar {
container-type: inline-size;
container-name: sidebar;
}
@container sidebar (inline-size > 300px) {
.widget { display: grid; grid-template-columns: 1fr 1fr; }
}
Use media queries only for page-level layout shifts.
@media (max-width: 48em) {
.page {
grid-template-columns: 1fr;
}
.sidebar { display: none; }
}
em units, never px — respects user font size.min-width (mobile-first) unless the desktop layout is simpler./* Compact */ @media (max-width: 48em) { }
/* Medium */ @media (min-width: 48em) and (max-width: 64em) { }
/* Expanded */ @media (min-width: 64em) { }
Use clamp() for font sizes that scale smoothly between a minimum and maximum.
:root {
--text-sm: clamp(0.8rem, 0.75rem + 0.25vw, 0.875rem);
--text-base: clamp(1rem, 0.925rem + 0.375vw, 1.125rem);
--text-lg: clamp(1.125rem, 1rem + 0.625vw, 1.375rem);
--text-xl: clamp(1.25rem, 1.1rem + 0.75vw, 1.625rem);
--text-2xl: clamp(1.5rem, 1.25rem + 1.25vw, 2.25rem);
--text-3xl: clamp(2rem, 1.5rem + 2.5vw, 3.5rem);
}
clamp(minimum, preferred, maximum)
rem)rem + vw)rem):root {
--space-xs: clamp(0.5rem, 0.4rem + 0.5vw, 0.75rem);
--space-s: clamp(0.75rem, 0.6rem + 0.75vw, 1rem);
--space-m: clamp(1rem, 0.8rem + 1vw, 1.5rem);
--space-l: clamp(1.5rem, 1.2rem + 1.5vw, 2rem);
--space-xl: clamp(2rem, 1.6rem + 2vw, 3rem);
--space-2xl: clamp(3rem, 2.4rem + 3vw, 4.5rem);
}
<img
src="image-800.jpg"
srcset="
image-400.jpg 400w,
image-800.jpg 800w,
image-1200.jpg 1200w,
image-1600.jpg 1600w
"
sizes="
(max-width: 48em) 100vw,
(max-width: 64em) 50vw,
33vw
"
alt="Description"
loading="lazy"
decoding="async"
>
<picture><picture>
<source
media="(min-width: 64em)"
srcset="hero-wide.avif"
type="image/avif"
>
<source
media="(min-width: 48em)"
srcset="hero-medium.avif"
type="image/avif"
>
<img
src="hero-narrow.jpg"
alt="Description"
loading="lazy"
decoding="async"
>
</picture>
img {
max-inline-size: 100%;
block-size: auto;
display: block;
}
.hero-image {
inline-size: 100%;
block-size: auto;
aspect-ratio: 16 / 9;
object-fit: cover;
}
| Unit | Meaning |
|------|---------|
| dvh | Dynamic viewport height (accounts for mobile browser chrome) |
| svh | Small viewport height (smallest possible viewport) |
| lvh | Large viewport height (largest possible viewport) |
| dvw | Dynamic viewport width |
.full-screen {
min-block-size: 100dvh;
}
.hero {
block-size: 100svh;
}
dvh for full-height layouts on mobile (accounts for URL bar).svh when you need the element to never exceed the visible area.100vh — it doesn't account for mobile browser UI..container {
inline-size: min(90%, 75rem);
margin-inline: auto;
}
.card-grid {
grid-template-columns: repeat(auto-fill, minmax(min(280px, 100%), 1fr));
}
.sidebar {
inline-size: clamp(200px, 25%, 350px);
}
.tag {
inline-size: fit-content;
padding-inline: var(--space-s);
}
.nav { inline-size: max-content; }
.label { inline-size: min-content; }
Use logical properties for all directional values. They support RTL/LTR automatically.
.element {
margin-block: var(--space-m);
padding-inline: var(--space-l);
border-inline-start: 3px solid var(--color-primary);
max-inline-size: 65ch;
text-align: start;
}
Full mapping reference in the css-layout skill.
:root {
color-scheme: light dark;
--color-surface: light-dark(white, oklch(15% 0 0));
--color-text: light-dark(oklch(20% 0 0), oklch(90% 0 0));
--color-border: light-dark(oklch(80% 0 0), oklch(30% 0 0));
}
light-dark() is preferred over @media (prefers-color-scheme) for individual values. Use the media query only for structural changes:
@media (prefers-color-scheme: dark) {
.logo { filter: brightness(1.2); }
}
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
}
@media (prefers-contrast: more) {
:root {
--color-border: oklch(0% 0 0);
--color-text: oklch(0% 0 0);
}
.card {
border: 2px solid var(--color-border);
}
}
@media (forced-colors: active) {
.button {
border: 2px solid ButtonText;
}
.icon {
forced-color-adjust: none;
}
}
@media (prefers-reduced-transparency: reduce) {
.overlay {
background: var(--color-surface);
backdrop-filter: none;
}
}
Use clamp() for spacing that scales between viewports without breakpoints:
:root {
--space-xs: clamp(0.5rem, 0.4rem + 0.5vw, 0.75rem);
--space-s: clamp(0.75rem, 0.6rem + 0.75vw, 1rem);
--space-m: clamp(1rem, 0.8rem + 1vw, 1.5rem);
--space-l: clamp(1.5rem, 1.2rem + 1.5vw, 2rem);
--space-xl: clamp(2rem, 1.6rem + 2vw, 3rem);
}
section { padding-block: var(--space-xl); }
.stack > * + * { margin-block-start: var(--space-m); }
em units (not px)clamp() with rem + vwleft/right/top/bottom)srcset/sizes or <picture> where appropriate100dvh used instead of 100vhprefers-reduced-motion handledprefers-color-scheme handled (or light-dark())prefers-contrast handled for key elementsmin()/max()/clamp()tools
分批提交 Git 变更的完整工作流。当用户说"提交这个文件"、"帮我 commit"、"分批提交"、"整理提交计划"、"staged 的文件"、"git 提交"时触发
tools
从用户给出的文档片段中,提取"进阶必知"的深层知识,当用户提到"太简单了,给我几条秘密","面试必备的那种","八股文进阶"时触发
data-ai
批量给技能目录添加 disable-model-invocation,节省 token 开销。只保留需要 LLM 生成/分析/决策的技能有模型调用能力。
tools
open understand dashboard for user