我们知道通过 className 增加
md:
等关键字可以让我们在 css 中判断小、中、大屏等。
针对场景的屏幕尺寸,tailwind 设计了 5 档断点:
Breakpoint prefix Minimum width CSS sm
40rem (640px) @media (width >= 40rem) { ... }
md
48rem (768px) @media (width >= 48rem) { ... }
lg
64rem (1024px) @media (width >= 64rem) { ... }
xl
80rem (1280px) @media (width >= 80rem) { ... }
2xl
96rem (1536px) @media (width >= 96rem) { ... }
来自 tailwindcss Responsive design - Using responsive utility variants to build adaptive user interfaces
比如想让一个元素在小屏隐藏,但其他屏幕展示。可以如下:
tsx
<div className='hidden md:block'> ...
页面出现大量的
hidden md:block、hidden md:inline、hidden md:flex ...
?追求 DRY 的同学可以去看我的另一篇文章。
但是有时候仅仅通过 hidden className 即 display none CSS 方式隐藏还不够,比如 antd 的 Modal
虽然弹窗主体隐藏了,但是遮罩并未隐藏,表现的现象就是页面出现灰黑色的遮罩。某些情况下基于性能考虑,需要将 DOM 节点完成移除,这就要求我们通过 js 来实现断点逻辑。
基于 tailwindcss 的断点参数,实现 JS 版本
我们基于 ahooks 的 useResponsive
,然后自定义断点以符合 tailwindcss 的要求。
tsx
// src\hooks\useResponsive.ts
import { configResponsive, useResponsive as useResponsiveAhooks } from 'ahooks'
const config = {
sm: 0,
md: 768,
lg: 1024,
} as const
configResponsive(config)
type IResponsive = {
/** 📱 */
mobile: boolean
/** 📱 or iPad */
mobileOrTablet: boolean
/** iPad or 💻 */
tabletAndUp: boolean
/** 💻 */
large: boolean
}
export function useResponsive(): IResponsive {
// @ts-expect-error
const responsive: Record<keyof typeof config, boolean> = useResponsiveAhooks()
// console.log('responsive:', responsive)
return {
mobile: !responsive.md,
mobileOrTablet: responsive.sm && responsive.md && !responsive.lg,
tabletAndUp: responsive.sm && responsive.md,
large: responsive.sm && responsive.md && responsive.lg,
}
}
没有找到平板的 emoji 😅。
使用:
tsx
const responsive = useResponsive()
if (responsive.mobile) {
return <Drawer ...>
}
return <Modal ...>
通过 useResponsive
我们实现了在手机端用抽屉,其他大屏则用弹窗的需求。
还有哪些情况需要用到
总之需要根据屏幕尺寸动态移除元素的地方都可以用到。比如:flex 布局中如果存在 gap,子元素若仅 display none,gap 仍然存在,需要将隐藏的子元素移除出 DOM 才能消除多余的 gap。