Skip to content

@media 使用技巧

一、基础语法

css
@media <媒体类型> and (<条件1>) and (<条件2>) {
  /* 样式 */
}

媒体类型(通常省略,默认 all):

  • screen — 屏幕
  • print — 打印
  • all — 所有设备

二、常用条件特性

1. 宽度相关

css
/* 精确宽度(少用) */
@media (width: 768px) { }

/* 最大宽度:<= 768px 生效(Desktop First) */
@media (max-width: 768px) { }

/* 最小宽度:>= 768px 生效(Mobile First) */
@media (min-width: 768px) { }

/* 范围:768px ~ 1024px */
@media (min-width: 768px) and (max-width: 1024px) { }

2. 新范围语法(Media Queries Level 4)

更直观的写法,现代浏览器均已支持:

css
/* 等价于 max-width: 768px */
@media (width <= 768px) { }

/* 等价于 min-width: 768px */
@media (width >= 768px) { }

/* 等价于 min-width: 768px and max-width: 1024px */
@media (768px <= width <= 1024px) { }

3. 高度相关

css
/* 矮屏幕(如横屏手机) */
@media (max-height: 500px) {
  .header { padding: 4px 16px; }
}

4. 屏幕方向

css
/* 竖屏 */
@media (orientation: portrait) {
  .grid { grid-template-columns: 1fr; }
}

/* 横屏 */
@media (orientation: landscape) {
  .grid { grid-template-columns: 1fr 1fr; }
}

5. 交互能力检测

css
/* 有鼠标悬停能力的设备(PC) */
@media (hover: hover) and (pointer: fine) {
  .btn:hover { background: #333; }
  .tooltip { display: block; }
}

/* 触屏设备(手机/平板) */
@media (hover: none) and (pointer: coarse) {
  .btn { min-height: 48px; }   /* 增大触摸区域 */
}
特性finecoarse
hover: hoverPC 鼠标
hover: none手机/平板触屏
pointer: fine鼠标精确指针
pointer: coarse手指粗略指针

6. 高分辨率屏幕(Retina)

css
@media (min-resolution: 2dppx) {
  .logo { background-image: url('logo@2x.png'); }
}

/* 等价的旧写法 */
@media (-webkit-min-device-pixel-ratio: 2) {
  .logo { background-image: url('logo@2x.png'); }
}

7. 用户偏好

css
/* 深色模式 */
@media (prefers-color-scheme: dark) {
  :root {
    --bg: #1a1a1a;
    --text: #e0e0e0;
  }
}

/* 浅色模式 */
@media (prefers-color-scheme: light) {
  :root {
    --bg: #ffffff;
    --text: #333333;
  }
}

/* 减少动画(无障碍) */
@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

/* 低数据流量模式 */
@media (prefers-reduced-data: reduce) {
  .hero-video { display: none; }
  .hero-image { display: block; }
}

三、逻辑运算符

and — 同时满足

css
@media (min-width: 768px) and (orientation: landscape) { }

,(逗号)— 或(满足任一)

css
/* 宽度 <= 480px 或 横屏时 */
@media (max-width: 480px), (orientation: landscape) { }

not — 取反(对整条规则取反)

css
/* 非打印设备 */
@media not print { }

/* 注意:not 作用于整条,加括号更清晰 */
@media not (hover: hover) {
  /* 没有悬停能力的设备 */
}

only — 防旧浏览器误读

css
@media only screen and (max-width: 768px) { }

四、Mobile First vs Desktop First

Mobile First(推荐)

先写手机样式,用 min-width 向上增强:

css
/* 基础:手机 */
.sidebar { display: none; }
.content { padding: 12px; }

/* >= 768px:平板 */
@media (min-width: 768px) {
  .sidebar { display: block; width: 200px; }
  .content { padding: 24px; }
}

/* >= 1200px:桌面 */
@media (min-width: 1200px) {
  .sidebar { width: 280px; }
  .content { padding: 32px; }
}

Desktop First

先写桌面样式,用 max-width 向下覆盖:

css
/* 基础:桌面 */
.sidebar { width: 280px; }

/* <= 1024px */
@media (max-width: 1024px) {
  .sidebar { width: 200px; }
}

/* <= 768px */
@media (max-width: 768px) {
  .sidebar { display: none; }
}

建议:新项目用 Mobile First。手机端通常更简单,逐步增强比逐步削减更容易维护。


五、断点管理技巧

1. 用 CSS 变量 + 统一断点

CSS 自身不支持变量作为媒体查询值,但可以用 SCSS/Less 统一管理:

scss
// _breakpoints.scss
$bp-mobile:  480px;
$bp-tablet:  768px;
$bp-desktop: 1024px;
$bp-wide:    1440px;

@mixin mobile  { @media (max-width: #{$bp-tablet - 1}) { @content; } }
@mixin tablet  { @media (min-width: $bp-tablet) and (max-width: #{$bp-desktop - 1}) { @content; } }
@mixin desktop { @media (min-width: $bp-desktop) { @content; } }

// 使用
.card {
  padding: 12px;
  @include tablet  { padding: 20px; }
  @include desktop { padding: 32px; }
}

2. 内容驱动断点

不要盲目使用 768/1024 这些"标准"数字。当布局开始"坏掉"的地方,就是断点

css
/* 当卡片在 600px 以下挤不下两列时,切换为单列 */
@media (max-width: 600px) {
  .card-grid { grid-template-columns: 1fr; }
}

六、@media 书写位置

方式一:集中写在底部

css
/* 所有组件样式 */
.header { ... }
.card { ... }
.footer { ... }

/* 底部集中写响应式 */
@media (max-width: 768px) {
  .header { ... }
  .card { ... }
  .footer { ... }
}

方式二:跟随组件就近写(推荐)

css
.header { padding: 16px 32px; }

@media (max-width: 768px) {
  .header { padding: 8px 16px; }
}

.card { display: grid; grid-template-columns: 1fr 1fr; }

@media (max-width: 768px) {
  .card { grid-template-columns: 1fr; }
}

就近写的好处:修改某个组件时,所有相关的响应式规则都在旁边,维护更方便。浏览器会自动合并重复的 @media 块,不影响性能。


七、打印样式

css
@media print {
  /* 隐藏不需要打印的元素 */
  .navbar, .sidebar, .footer, .no-print {
    display: none !important;
  }

  /* 全宽显示内容 */
  .content {
    width: 100%;
    margin: 0;
    padding: 0;
  }

  /* 显示链接地址 */
  a[href]::after {
    content: " (" attr(href) ")";
    font-size: 0.8em;
    color: #666;
  }

  /* 避免在元素中间分页 */
  .card, img, table {
    break-inside: avoid;
  }
}

八、@container 查询(补充)

@media 基于视口@container 基于父容器,用于组件级响应式:

css
.card-wrapper {
  container-type: inline-size;
  container-name: card;
}

/* 当 card-wrapper 宽度 <= 400px 时 */
@container card (max-width: 400px) {
  .card {
    flex-direction: column;
  }
  .card-image {
    width: 100%;
  }
}

@container card (min-width: 401px) {
  .card {
    flex-direction: row;
  }
  .card-image {
    width: 40%;
  }
}

@media 适合页面级布局切换,@container 适合可复用组件的自适应。两者配合使用效果最佳。


速查表

需求写法
手机端@media (max-width: 768px)(width <= 768px)
平板竖屏@media (min-width: 768px) and (max-width: 1024px) and (orientation: portrait)
桌面端@media (min-width: 1024px)
深色模式@media (prefers-color-scheme: dark)
触屏设备@media (hover: none) and (pointer: coarse)
Retina 屏@media (min-resolution: 2dppx)
减少动画@media (prefers-reduced-motion: reduce)
打印@media print
横屏@media (orientation: landscape)

Released under the MIT License.