本章概述
本章将深入探讨 UnoCSS 的响应式设计能力,学习如何使用断点系统创建适配不同设备的界面。我们将从基础的断点概念开始,逐步学习高级的响应式技巧和最佳实践。
响应式设计基础
什么是响应式设计
响应式设计(Responsive Design)是一种网页设计方法,使网站能够在不同设备和屏幕尺寸上提供最佳的用户体验。它通过使用灵活的布局、图片和CSS媒体查询来实现。
响应式设计的核心原则
- 移动优先:从最小屏幕开始设计,逐步增强
- 灵活布局:使用相对单位而非固定像素
- 弹性图片:图片能够适应容器大小
- 媒体查询:根据设备特性应用不同样式
- 渐进增强:基础功能在所有设备上可用,高级功能在支持的设备上增强
UnoCSS的响应式方法
// UnoCSS 响应式配置
export default defineConfig({
theme: {
breakpoints: {
'xs': '320px',
'sm': '640px',
'md': '768px',
'lg': '1024px',
'xl': '1280px',
'2xl': '1536px',
}
},
// 响应式变体
variants: [
// 移动优先的断点
(matcher) => {
const breakpoints = ['sm', 'md', 'lg', 'xl', '2xl']
for (const bp of breakpoints) {
if (matcher.startsWith(`${bp}:`)) {
return {
matcher: matcher.slice(bp.length + 1),
parent: `@media (min-width: ${theme.breakpoints[bp]})`,
}
}
}
return matcher
},
],
})
断点系统详解
默认断点
UnoCSS 提供了一套默认的断点系统,遵循移动优先的设计原则:
/* 默认断点对应的媒体查询 */
/* xs: 无媒体查询(默认,移动优先) */
/* sm: @media (min-width: 640px) */
/* md: @media (min-width: 768px) */
/* lg: @media (min-width: 1024px) */
/* xl: @media (min-width: 1280px) */
/* 2xl: @media (min-width: 1536px) */
断点使用语法
<!-- 基础语法:{断点}:{工具类} -->
<div class="w-full md:w-1/2 lg:w-1/3">
<!-- 默认全宽,中等屏幕半宽,大屏幕三分之一宽 -->
</div>
<!-- 多个断点组合 -->
<div class="text-sm sm:text-base md:text-lg lg:text-xl xl:text-2xl">
<!-- 不同屏幕尺寸下的不同字体大小 -->
</div>
<!-- 复杂响应式布局 -->
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
<!-- 响应式网格布局 -->
</div>
自定义断点
// 自定义断点配置
export default defineConfig({
theme: {
breakpoints: {
// 覆盖默认断点
'xs': '375px', // iPhone SE
'sm': '640px', // 小平板
'md': '768px', // 平板
'lg': '1024px', // 小桌面
'xl': '1280px', // 桌面
'2xl': '1536px', // 大桌面
// 添加自定义断点
'mobile': '480px',
'tablet': '768px',
'laptop': '1024px',
'desktop': '1280px',
'wide': '1920px',
// 特殊设备断点
'iphone': '375px',
'ipad': '768px',
'macbook': '1440px',
}
},
// 自定义变体生成器
variants: [
// 标准断点
...Object.entries(theme.breakpoints).map(([name, size]) => {
return (matcher) => {
if (!matcher.startsWith(`${name}:`)) return matcher
return {
matcher: matcher.slice(name.length + 1),
parent: `@media (min-width: ${size})`,
}
}
}),
// 最大宽度断点
(matcher) => {
const maxBreakpoints = {
'max-sm': '639px',
'max-md': '767px',
'max-lg': '1023px',
'max-xl': '1279px',
}
for (const [name, size] of Object.entries(maxBreakpoints)) {
if (matcher.startsWith(`${name}:`)) {
return {
matcher: matcher.slice(name.length + 1),
parent: `@media (max-width: ${size})`,
}
}
}
return matcher
},
// 范围断点
(matcher) => {
const rangeBreakpoints = {
'sm-only': '(min-width: 640px) and (max-width: 767px)',
'md-only': '(min-width: 768px) and (max-width: 1023px)',
'lg-only': '(min-width: 1024px) and (max-width: 1279px)',
}
for (const [name, query] of Object.entries(rangeBreakpoints)) {
if (matcher.startsWith(`${name}:`)) {
return {
matcher: matcher.slice(name.length + 1),
parent: `@media ${query}`,
}
}
}
return matcher
},
],
})
响应式布局技巧
容器和网格系统
<!-- 响应式容器 -->
<div class="container mx-auto px-4">
<!-- 内容会在不同屏幕尺寸下有不同的最大宽度 -->
</div>
<!-- 自定义容器 -->
<div class="w-full max-w-screen-sm mx-auto px-4 sm:max-w-screen-md md:max-w-screen-lg lg:max-w-screen-xl">
<!-- 渐进式容器宽度 -->
</div>
<!-- 响应式网格 -->
<div class="grid gap-4 grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-6">
<div class="bg-gray-200 p-4 rounded">项目 1</div>
<div class="bg-gray-200 p-4 rounded">项目 2</div>
<div class="bg-gray-200 p-4 rounded">项目 3</div>
<div class="bg-gray-200 p-4 rounded">项目 4</div>
<div class="bg-gray-200 p-4 rounded">项目 5</div>
<div class="bg-gray-200 p-4 rounded">项目 6</div>
</div>
<!-- 复杂网格布局 -->
<div class="grid gap-4 grid-cols-1 md:grid-cols-3">
<!-- 主内容区域 -->
<div class="md:col-span-2">
<div class="bg-white p-6 rounded-lg shadow">
<h2 class="text-2xl font-bold mb-4">主要内容</h2>
<p>这里是主要内容区域...</p>
</div>
</div>
<!-- 侧边栏 -->
<div class="md:col-span-1">
<div class="bg-white p-6 rounded-lg shadow">
<h3 class="text-lg font-semibold mb-4">侧边栏</h3>
<p>这里是侧边栏内容...</p>
</div>
</div>
</div>
Flexbox 响应式布局
<!-- 响应式导航栏 -->
<nav class="flex flex-col md:flex-row items-center justify-between p-4">
<div class="flex items-center mb-4 md:mb-0">
<img src="logo.svg" alt="Logo" class="h-8 w-8 mr-2">
<span class="text-xl font-bold">品牌名称</span>
</div>
<div class="flex flex-col md:flex-row space-y-2 md:space-y-0 md:space-x-6">
<a href="#" class="text-gray-700 hover:text-blue-600">首页</a>
<a href="#" class="text-gray-700 hover:text-blue-600">产品</a>
<a href="#" class="text-gray-700 hover:text-blue-600">关于</a>
<a href="#" class="text-gray-700 hover:text-blue-600">联系</a>
</div>
</nav>
<!-- 响应式卡片布局 -->
<div class="flex flex-col lg:flex-row gap-6">
<div class="flex-1">
<div class="bg-white p-6 rounded-lg shadow">
<h3 class="text-lg font-semibold mb-2">卡片 1</h3>
<p class="text-gray-600">卡片内容...</p>
</div>
</div>
<div class="flex-1">
<div class="bg-white p-6 rounded-lg shadow">
<h3 class="text-lg font-semibold mb-2">卡片 2</h3>
<p class="text-gray-600">卡片内容...</p>
</div>
</div>
<div class="flex-1">
<div class="bg-white p-6 rounded-lg shadow">
<h3 class="text-lg font-semibold mb-2">卡片 3</h3>
<p class="text-gray-600">卡片内容...</p>
</div>
</div>
</div>
<!-- 响应式侧边栏布局 -->
<div class="flex flex-col lg:flex-row min-h-screen">
<!-- 侧边栏 -->
<aside class="w-full lg:w-64 bg-gray-800 text-white">
<div class="p-4">
<h2 class="text-xl font-bold mb-4">菜单</h2>
<nav class="space-y-2">
<a href="#" class="block px-3 py-2 rounded hover:bg-gray-700">仪表板</a>
<a href="#" class="block px-3 py-2 rounded hover:bg-gray-700">用户</a>
<a href="#" class="block px-3 py-2 rounded hover:bg-gray-700">设置</a>
</nav>
</div>
</aside>
<!-- 主内容 -->
<main class="flex-1 p-6">
<h1 class="text-3xl font-bold mb-6">主要内容</h1>
<div class="bg-white p-6 rounded-lg shadow">
<p>这里是主要内容区域...</p>
</div>
</main>
</div>
响应式间距和尺寸
<!-- 响应式间距 -->
<div class="p-4 sm:p-6 md:p-8 lg:p-12">
<!-- 不同屏幕尺寸下的不同内边距 -->
</div>
<div class="space-y-4 sm:space-y-6 md:space-y-8">
<!-- 响应式垂直间距 -->
<div>项目 1</div>
<div>项目 2</div>
<div>项目 3</div>
</div>
<!-- 响应式尺寸 -->
<div class="w-full sm:w-3/4 md:w-1/2 lg:w-1/3 xl:w-1/4">
<!-- 响应式宽度 -->
</div>
<div class="h-32 sm:h-40 md:h-48 lg:h-56 xl:h-64">
<!-- 响应式高度 -->
</div>
<!-- 响应式字体大小 -->
<h1 class="text-2xl sm:text-3xl md:text-4xl lg:text-5xl xl:text-6xl font-bold">
响应式标题
</h1>
<p class="text-sm sm:text-base md:text-lg">
响应式段落文本
</p>
高级响应式技巧
显示和隐藏元素
<!-- 基于屏幕尺寸显示/隐藏 -->
<div class="block md:hidden">
<!-- 只在小屏幕显示 -->
<button class="w-full p-3 bg-blue-500 text-white rounded">
移动端菜单
</button>
</div>
<div class="hidden md:block">
<!-- 只在大屏幕显示 -->
<nav class="flex space-x-6">
<a href="#">首页</a>
<a href="#">产品</a>
<a href="#">关于</a>
</nav>
</div>
<!-- 渐进式显示 -->
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3">
<div class="bg-gray-200 p-4">始终显示</div>
<div class="bg-gray-200 p-4">小屏幕及以上显示</div>
<div class="bg-gray-200 p-4 hidden lg:block">只在大屏幕显示</div>
</div>
<!-- 响应式图片 -->
<picture>
<source media="(min-width: 1024px)" srcset="large-image.jpg">
<source media="(min-width: 768px)" srcset="medium-image.jpg">
<img src="small-image.jpg" alt="响应式图片" class="w-full h-auto">
</picture>
<!-- 使用CSS类控制图片显示 -->
<div class="relative">
<img src="mobile-image.jpg" alt="移动端图片" class="w-full h-auto md:hidden">
<img src="desktop-image.jpg" alt="桌面端图片" class="w-full h-auto hidden md:block">
</div>
响应式排版
<!-- 响应式标题层次 -->
<h1 class="text-3xl sm:text-4xl md:text-5xl lg:text-6xl font-bold leading-tight">
主标题
</h1>
<h2 class="text-xl sm:text-2xl md:text-3xl lg:text-4xl font-semibold mt-8 mb-4">
副标题
</h2>
<p class="text-base sm:text-lg md:text-xl leading-relaxed text-gray-700">
正文内容,在不同屏幕尺寸下有不同的字体大小和行高。
</p>
<!-- 响应式文本对齐 -->
<div class="text-center sm:text-left">
<h3 class="text-2xl font-bold">标题</h3>
<p class="text-gray-600">在小屏幕居中,大屏幕左对齐</p>
</div>
<!-- 响应式行高和字间距 -->
<p class="leading-normal sm:leading-relaxed md:leading-loose tracking-normal sm:tracking-wide">
响应式行高和字间距的文本内容。
</p>
<!-- 响应式文本截断 -->
<div class="w-full">
<p class="truncate sm:whitespace-normal">
这是一段很长的文本,在小屏幕上会被截断,在大屏幕上正常显示。
</p>
</div>
响应式表单
<!-- 响应式表单布局 -->
<form class="space-y-6">
<!-- 响应式表单组 -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">
姓名
</label>
<input type="text"
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500">
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">
邮箱
</label>
<input type="email"
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500">
</div>
</div>
<!-- 全宽字段 -->
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">
消息
</label>
<textarea rows="4"
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500">
</textarea>
</div>
<!-- 响应式按钮组 -->
<div class="flex flex-col sm:flex-row gap-4 sm:justify-end">
<button type="button"
class="w-full sm:w-auto px-6 py-2 border border-gray-300 text-gray-700 rounded-md hover:bg-gray-50">
取消
</button>
<button type="submit"
class="w-full sm:w-auto px-6 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700">
提交
</button>
</div>
</form>
<!-- 响应式搜索栏 -->
<div class="flex flex-col sm:flex-row gap-4">
<div class="flex-1">
<input type="search"
placeholder="搜索..."
class="w-full px-4 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500">
</div>
<button class="w-full sm:w-auto px-6 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700">
搜索
</button>
</div>
实际应用案例
响应式电商产品页面
<div class="min-h-screen bg-gray-50">
<!-- 响应式头部 -->
<header class="bg-white shadow-sm">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex items-center justify-between h-16">
<!-- Logo -->
<div class="flex items-center">
<img class="h-8 w-auto" src="logo.svg" alt="Logo">
<span class="ml-2 text-xl font-bold text-gray-900 hidden sm:block">
商店名称
</span>
</div>
<!-- 搜索栏 -->
<div class="flex-1 max-w-lg mx-4 hidden md:block">
<div class="relative">
<input type="search"
placeholder="搜索产品..."
class="w-full pl-10 pr-4 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500">
<div class="absolute inset-y-0 left-0 pl-3 flex items-center">
<svg class="h-5 w-5 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path>
</svg>
</div>
</div>
</div>
<!-- 用户操作 -->
<div class="flex items-center space-x-4">
<button class="p-2 text-gray-400 hover:text-gray-500">
<svg class="h-6 w-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z"></path>
</svg>
</button>
<button class="p-2 text-gray-400 hover:text-gray-500 relative">
<svg class="h-6 w-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 3h2l.4 2M7 13h10l4-8H5.4m0 0L7 13m0 0l-2.5 5M7 13l2.5 5m6 0a1 1 0 100-2 1 1 0 000 2zm-6 0a1 1 0 100-2 1 1 0 000 2z"></path>
</svg>
<span class="absolute -top-1 -right-1 h-4 w-4 bg-red-500 text-white text-xs rounded-full flex items-center justify-center">
3
</span>
</button>
</div>
</div>
<!-- 移动端搜索栏 -->
<div class="md:hidden pb-4">
<input type="search"
placeholder="搜索产品..."
class="w-full px-4 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500">
</div>
</div>
</header>
<!-- 主要内容 -->
<main class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
<!-- 面包屑导航 -->
<nav class="flex mb-8 text-sm">
<a href="#" class="text-gray-500 hover:text-gray-700">首页</a>
<span class="mx-2 text-gray-400">/</span>
<a href="#" class="text-gray-500 hover:text-gray-700">电子产品</a>
<span class="mx-2 text-gray-400">/</span>
<span class="text-gray-900">智能手机</span>
</nav>
<!-- 产品详情 -->
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8 lg:gap-12">
<!-- 产品图片 -->
<div class="space-y-4">
<div class="aspect-w-1 aspect-h-1 bg-gray-200 rounded-lg overflow-hidden">
<img src="product-main.jpg"
alt="产品主图"
class="w-full h-full object-center object-cover">
</div>
<!-- 缩略图 -->
<div class="grid grid-cols-4 gap-4">
<div class="aspect-w-1 aspect-h-1 bg-gray-200 rounded-md overflow-hidden cursor-pointer">
<img src="product-thumb-1.jpg" alt="缩略图 1" class="w-full h-full object-center object-cover">
</div>
<div class="aspect-w-1 aspect-h-1 bg-gray-200 rounded-md overflow-hidden cursor-pointer">
<img src="product-thumb-2.jpg" alt="缩略图 2" class="w-full h-full object-center object-cover">
</div>
<div class="aspect-w-1 aspect-h-1 bg-gray-200 rounded-md overflow-hidden cursor-pointer">
<img src="product-thumb-3.jpg" alt="缩略图 3" class="w-full h-full object-center object-cover">
</div>
<div class="aspect-w-1 aspect-h-1 bg-gray-200 rounded-md overflow-hidden cursor-pointer">
<img src="product-thumb-4.jpg" alt="缩略图 4" class="w-full h-full object-center object-cover">
</div>
</div>
</div>
<!-- 产品信息 -->
<div class="space-y-6">
<div>
<h1 class="text-2xl sm:text-3xl lg:text-4xl font-bold text-gray-900">
iPhone 15 Pro Max
</h1>
<p class="mt-2 text-lg text-gray-600">
最新一代智能手机,配备先进的A17 Pro芯片
</p>
</div>
<!-- 评分 -->
<div class="flex items-center space-x-2">
<div class="flex items-center">
<svg class="w-5 h-5 text-yellow-400" fill="currentColor" viewBox="0 0 20 20">
<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"/>
</svg>
<span class="text-sm text-gray-600 ml-1">4.8 (2,847 评价)</span>
</div>
</div>
<!-- 价格 -->
<div class="space-y-2">
<div class="flex items-baseline space-x-2">
<span class="text-3xl font-bold text-gray-900">¥9,999</span>
<span class="text-lg text-gray-500 line-through">¥10,999</span>
<span class="px-2 py-1 bg-red-100 text-red-800 text-sm font-medium rounded">
限时优惠
</span>
</div>
<p class="text-sm text-gray-600">
分期付款低至 ¥833/月
</p>
</div>
<!-- 选项 -->
<div class="space-y-4">
<!-- 颜色选择 -->
<div>
<h3 class="text-sm font-medium text-gray-900 mb-3">颜色</h3>
<div class="flex space-x-3">
<button class="w-8 h-8 bg-gray-800 rounded-full border-2 border-gray-300 focus:border-gray-500">
<span class="sr-only">深空灰色</span>
</button>
<button class="w-8 h-8 bg-blue-600 rounded-full border-2 border-gray-300 focus:border-gray-500">
<span class="sr-only">海蓝色</span>
</button>
<button class="w-8 h-8 bg-purple-600 rounded-full border-2 border-gray-300 focus:border-gray-500">
<span class="sr-only">紫色</span>
</button>
</div>
</div>
<!-- 存储容量 -->
<div>
<h3 class="text-sm font-medium text-gray-900 mb-3">存储容量</h3>
<div class="grid grid-cols-2 sm:grid-cols-4 gap-3">
<button class="px-3 py-2 text-sm border border-gray-300 rounded-md hover:border-gray-400 focus:border-blue-500">
128GB
</button>
<button class="px-3 py-2 text-sm border border-blue-500 bg-blue-50 text-blue-700 rounded-md">
256GB
</button>
<button class="px-3 py-2 text-sm border border-gray-300 rounded-md hover:border-gray-400 focus:border-blue-500">
512GB
</button>
<button class="px-3 py-2 text-sm border border-gray-300 rounded-md hover:border-gray-400 focus:border-blue-500">
1TB
</button>
</div>
</div>
</div>
<!-- 操作按钮 -->
<div class="space-y-4">
<button class="w-full bg-blue-600 text-white py-3 px-6 rounded-md text-lg font-medium hover:bg-blue-700 transition-colors">
立即购买
</button>
<button class="w-full border border-gray-300 text-gray-700 py-3 px-6 rounded-md text-lg font-medium hover:bg-gray-50 transition-colors">
加入购物车
</button>
</div>
<!-- 产品特性 -->
<div class="border-t pt-6">
<h3 class="text-lg font-medium text-gray-900 mb-4">产品特性</h3>
<ul class="space-y-2 text-sm text-gray-600">
<li class="flex items-center">
<svg class="w-4 h-4 text-green-500 mr-2" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"/>
</svg>
A17 Pro 芯片,性能提升 20%
</li>
<li class="flex items-center">
<svg class="w-4 h-4 text-green-500 mr-2" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"/>
</svg>
Pro 级别摄像头系统
</li>
<li class="flex items-center">
<svg class="w-4 h-4 text-green-500 mr-2" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"/>
</svg>
全天候电池续航
</li>
<li class="flex items-center">
<svg class="w-4 h-4 text-green-500 mr-2" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"/>
</svg>
IP68 防水等级
</li>
</ul>
</div>
</div>
</div>
<!-- 相关产品 -->
<section class="mt-16">
<h2 class="text-2xl font-bold text-gray-900 mb-8">相关产品</h2>
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6">
<!-- 产品卡片 -->
<div class="bg-white rounded-lg shadow-md overflow-hidden hover:shadow-lg transition-shadow">
<div class="aspect-w-1 aspect-h-1">
<img src="related-product-1.jpg" alt="相关产品" class="w-full h-48 object-cover">
</div>
<div class="p-4">
<h3 class="text-lg font-medium text-gray-900 mb-2">iPhone 15</h3>
<p class="text-gray-600 text-sm mb-2">标准版智能手机</p>
<div class="flex items-center justify-between">
<span class="text-xl font-bold text-gray-900">¥6,999</span>
<button class="px-3 py-1 bg-blue-600 text-white text-sm rounded hover:bg-blue-700">
查看
</button>
</div>
</div>
</div>
<!-- 重复其他产品卡片... -->
</div>
</section>
</main>
</div>
响应式博客布局
<div class="min-h-screen bg-gray-50">
<!-- 响应式头部 -->
<header class="bg-white shadow-sm sticky top-0 z-50">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex items-center justify-between h-16">
<div class="flex items-center">
<h1 class="text-xl sm:text-2xl font-bold text-gray-900">
我的博客
</h1>
</div>
<nav class="hidden md:flex space-x-8">
<a href="#" class="text-gray-700 hover:text-blue-600 font-medium">首页</a>
<a href="#" class="text-gray-700 hover:text-blue-600 font-medium">文章</a>
<a href="#" class="text-gray-700 hover:text-blue-600 font-medium">分类</a>
<a href="#" class="text-gray-700 hover:text-blue-600 font-medium">关于</a>
</nav>
<button class="md:hidden p-2">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"></path>
</svg>
</button>
</div>
</div>
</header>
<!-- 主要内容 -->
<main class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
<div class="grid grid-cols-1 lg:grid-cols-4 gap-8">
<!-- 文章列表 -->
<div class="lg:col-span-3 space-y-8">
<!-- 特色文章 -->
<article class="bg-white rounded-lg shadow-md overflow-hidden">
<div class="md:flex">
<div class="md:w-1/3">
<img src="featured-post.jpg"
alt="特色文章"
class="w-full h-48 md:h-full object-cover">
</div>
<div class="p-6 md:w-2/3">
<div class="flex items-center text-sm text-gray-500 mb-2">
<span>2024年1月15日</span>
<span class="mx-2">•</span>
<span>技术</span>
</div>
<h2 class="text-xl sm:text-2xl font-bold text-gray-900 mb-3">
UnoCSS:下一代原子化CSS引擎
</h2>
<p class="text-gray-600 mb-4 line-clamp-3">
UnoCSS是一个即时按需的原子化CSS引擎,它提供了极高的性能和灵活性...
</p>
<div class="flex items-center justify-between">
<div class="flex items-center space-x-2">
<img src="author.jpg" alt="作者" class="w-8 h-8 rounded-full">
<span class="text-sm text-gray-700">张三</span>
</div>
<a href="#" class="text-blue-600 hover:text-blue-800 font-medium">
阅读更多 →
</a>
</div>
</div>
</div>
</article>
<!-- 普通文章列表 -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<article class="bg-white rounded-lg shadow-md overflow-hidden">
<img src="post-1.jpg" alt="文章1" class="w-full h-48 object-cover">
<div class="p-6">
<div class="flex items-center text-sm text-gray-500 mb-2">
<span>2024年1月10日</span>
<span class="mx-2">•</span>
<span>设计</span>
</div>
<h3 class="text-lg font-semibold text-gray-900 mb-2">
响应式设计的最佳实践
</h3>
<p class="text-gray-600 text-sm mb-4 line-clamp-2">
在移动设备普及的今天,响应式设计已经成为了网页开发的标准...
</p>
<a href="#" class="text-blue-600 hover:text-blue-800 font-medium text-sm">
阅读更多 →
</a>
</div>
</article>
<article class="bg-white rounded-lg shadow-md overflow-hidden">
<img src="post-2.jpg" alt="文章2" class="w-full h-48 object-cover">
<div class="p-6">
<div class="flex items-center text-sm text-gray-500 mb-2">
<span>2024年1月8日</span>
<span class="mx-2">•</span>
<span>开发</span>
</div>
<h3 class="text-lg font-semibold text-gray-900 mb-2">
JavaScript ES2024 新特性
</h3>
<p class="text-gray-600 text-sm mb-4 line-clamp-2">
ES2024带来了许多令人兴奋的新特性,让我们一起来看看...
</p>
<a href="#" class="text-blue-600 hover:text-blue-800 font-medium text-sm">
阅读更多 →
</a>
</div>
</article>
</div>
<!-- 分页 -->
<div class="flex items-center justify-center space-x-2">
<button class="px-3 py-2 text-sm border border-gray-300 rounded-md hover:bg-gray-50">
上一页
</button>
<button class="px-3 py-2 text-sm bg-blue-600 text-white rounded-md">
1
</button>
<button class="px-3 py-2 text-sm border border-gray-300 rounded-md hover:bg-gray-50">
2
</button>
<button class="px-3 py-2 text-sm border border-gray-300 rounded-md hover:bg-gray-50">
3
</button>
<button class="px-3 py-2 text-sm border border-gray-300 rounded-md hover:bg-gray-50">
下一页
</button>
</div>
</div>
<!-- 侧边栏 -->
<aside class="lg:col-span-1 space-y-6">
<!-- 搜索 -->
<div class="bg-white p-6 rounded-lg shadow-md">
<h3 class="text-lg font-semibold text-gray-900 mb-4">搜索</h3>
<div class="relative">
<input type="search"
placeholder="搜索文章..."
class="w-full pl-10 pr-4 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500">
<div class="absolute inset-y-0 left-0 pl-3 flex items-center">
<svg class="h-5 w-5 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path>
</svg>
</div>
</div>
</div>
<!-- 分类 -->
<div class="bg-white p-6 rounded-lg shadow-md">
<h3 class="text-lg font-semibold text-gray-900 mb-4">分类</h3>
<ul class="space-y-2">
<li>
<a href="#" class="flex items-center justify-between text-gray-700 hover:text-blue-600">
<span>技术</span>
<span class="text-sm text-gray-500">12</span>
</a>
</li>
<li>
<a href="#" class="flex items-center justify-between text-gray-700 hover:text-blue-600">
<span>设计</span>
<span class="text-sm text-gray-500">8</span>
</a>
</li>
<li>
<a href="#" class="flex items-center justify-between text-gray-700 hover:text-blue-600">
<span>生活</span>
<span class="text-sm text-gray-500">5</span>
</a>
</li>
</ul>
</div>
<!-- 热门文章 -->
<div class="bg-white p-6 rounded-lg shadow-md">
<h3 class="text-lg font-semibold text-gray-900 mb-4">热门文章</h3>
<div class="space-y-4">
<div class="flex space-x-3">
<img src="popular-1.jpg" alt="热门文章" class="w-16 h-16 object-cover rounded">
<div class="flex-1">
<h4 class="text-sm font-medium text-gray-900 line-clamp-2">
CSS Grid 完全指南
</h4>
<p class="text-xs text-gray-500 mt-1">2024年1月5日</p>
</div>
</div>
<div class="flex space-x-3">
<img src="popular-2.jpg" alt="热门文章" class="w-16 h-16 object-cover rounded">
<div class="flex-1">
<h4 class="text-sm font-medium text-gray-900 line-clamp-2">
React Hooks 最佳实践
</h4>
<p class="text-xs text-gray-500 mt-1">2024年1月3日</p>
</div>
</div>
</div>
</div>
<!-- 标签云 -->
<div class="bg-white p-6 rounded-lg shadow-md">
<h3 class="text-lg font-semibold text-gray-900 mb-4">标签</h3>
<div class="flex flex-wrap gap-2">
<span class="px-3 py-1 bg-gray-100 text-gray-700 text-sm rounded-full hover:bg-gray-200 cursor-pointer">
CSS
</span>
<span class="px-3 py-1 bg-gray-100 text-gray-700 text-sm rounded-full hover:bg-gray-200 cursor-pointer">
JavaScript
</span>
<span class="px-3 py-1 bg-gray-100 text-gray-700 text-sm rounded-full hover:bg-gray-200 cursor-pointer">
React
</span>
<span class="px-3 py-1 bg-gray-100 text-gray-700 text-sm rounded-full hover:bg-gray-200 cursor-pointer">
Vue
</span>
<span class="px-3 py-1 bg-gray-100 text-gray-700 text-sm rounded-full hover:bg-gray-200 cursor-pointer">
Node.js
</span>
</div>
</div>
</aside>
</div>
</main>
</div>
性能优化建议
移动优先策略
/* 移动优先的CSS生成 */
/* 基础样式(移动端) */
.container {
padding: 1rem;
}
/* 平板及以上 */
@media (min-width: 768px) {
.container {
padding: 2rem;
}
}
/* 桌面及以上 */
@media (min-width: 1024px) {
.container {
padding: 3rem;
}
}
减少媒体查询数量
// 优化断点使用
// 避免过多的断点变化
// 好的做法
<div class="text-sm md:text-base lg:text-lg">
// 避免的做法
<div class="text-xs sm:text-sm md:text-base lg:text-lg xl:text-xl 2xl:text-2xl">
图片响应式优化
<!-- 响应式图片 -->
<picture>
<source media="(min-width: 1024px)" srcset="large.webp" type="image/webp">
<source media="(min-width: 768px)" srcset="medium.webp" type="image/webp">
<source media="(min-width: 1024px)" srcset="large.jpg">
<source media="(min-width: 768px)" srcset="medium.jpg">
<img src="small.jpg" alt="响应式图片" class="w-full h-auto">
</picture>
<!-- 使用CSS控制图片显示 -->
<div class="relative">
<img src="mobile.jpg" alt="移动端" class="w-full h-auto md:hidden">
<img src="desktop.jpg" alt="桌面端" class="w-full h-auto hidden md:block">
</div>
本章总结
通过本章学习,我们全面掌握了:
- 响应式设计基础:核心原则和UnoCSS的实现方法
- 断点系统:默认断点、自定义断点和高级变体
- 响应式布局:容器、网格、Flexbox等布局技巧
- 高级技巧:显示隐藏、排版、表单等响应式处理
- 实际应用:电商页面、博客布局等完整案例
- 性能优化:移动优先、减少媒体查询、图片优化等
核心要点
- 移动优先是现代响应式设计的基础
- 合理使用断点,避免过度复杂化
- 响应式不仅仅是布局,还包括字体、间距、交互等
- 性能优化是响应式设计的重要考虑因素
下一步
在下一章中,我们将学习如何创建自定义规则和变体,进一步扩展UnoCSS的功能。
练习题
- 响应式导航:创建一个在移动端折叠、桌面端展开的导航栏
- 卡片网格:实现一个响应式的产品卡片网格布局
- 自定义断点:为特定项目需求创建自定义断点系统
- 性能测试:比较不同响应式策略的性能差异
- 完整页面:设计并实现一个完整的响应式着陆页